본문 바로가기

Architecture

디자인 패턴1. MVP 패턴

//View 와 Presenter 인터페이스를 소유한 Contract 인터페이스
interface Contract {

    interface View {
        fun showNewItem(item: String)
    }

    interface Presenter {
        var view: View
        var model: Model
        fun requestItem()
    }
}
/*
*   Presenter 는 View 와 Model 사이에 존재하며
*   View 에서 특정 이벤트가 발생하면 Presenter 는 Model 에게 데이터를 요청하고
*   Model 은 Presenter 에게 Remote 또는 Local 데이터를 전달한다
*   Presenter 는 Model 에서 전달받은 데이터를 View 에게 전달하고
*   View 는 데이터를 UI 에 반영한다.
* */
class Presenter : Contract.Presenter {
    //Presenter 는 View 와 Model 사이에서 징검다리 역할을 하므로 두 객체를 모두 소유하고 있다.
    override lateinit var view: Contract.View
    override lateinit var model: Model

    constructor(view: Contract.View) {
        this.view = view
        model = Model()
    }

    override fun requestItem() {
        val newItem = model.getItem()

        view.showNewItem(newItem)
    }
}
/*
*   Model 은 Repository 를 통해 Remote 또는 Local 데이터를 얻으며
*   얻은 데이터를 Presenter 에게 반환해준다.
* */
class Model {
    fun getItem(): String {
        return Repository.responseLocalData()
    }
}
class MainActivity : AppCompatActivity(), Contract.View {

    private val recyclerView: RecyclerView by lazy {
        findViewById(R.id.recyclerView)
    }

    private val fab: FloatingActionButton by lazy {
        findViewById(R.id.fab)
    }

    private lateinit var adapter: RecyclerViewAdapter
    private val itemList: MutableList<String> = mutableListOf()
    private var presenter: Contract.Presenter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        presenter = Presenter(this)

        initViews()
    }

    private fun initViews() {
        adapter = RecyclerViewAdapter(itemList)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter

        //Floating Action Button 에 클릭 이벤트가 발생하면
        //Presenter 에게 알리며 Presenter 는 Model 에게 데이터를 요청한다.
        fab.setOnClickListener {
            presenter?.requestItem()
        }
    }

    //Presenter 가 Model 에게 데이터를 받은 후 View 에 해당 데이터를 전달하면
    //View 는 해당 메서드를 통해 UI(RecyclerView) 에 반영한다.
    override fun showNewItem(item: String) {
        itemList.add(item)
        adapter.notifyDataSetChanged()
    }
}

View는 Presenter를 통해서만 데이터에 접근하므로 View와 Model 사이의 의존성이 사라진다.

View와 Presenter는 1:1 관계를 맺게되며 View를 하나 추가할 때 마다(ex: Activity 추가) 그에 맞게 Presenter도 하나씩 추가해서 정의해줘야한다.