post-custom-banner

소프트웨어 패턴중 하나입니다.
최근 MVVM으로 구성되지 않은 앱을 찾기 어려울정도로 대중화가 되어있기 때문에 MVVM으로 가는
발판으로 생각하고 포스팅을 시작합니다.


MVP란?

먼저 명명부터 알아봅시다.
Model - View - Presenter로 구성되어 있습니다.

Model

  • 앱에 사용된는 데이터와 데이터를 처리하는 부분입니다.(비즈니스 로직)
  • View 또는 Presenter등 다른 어떤 요소에도 의존적이지 않은 독립적인 영역입니다.
  • 데이터, 서버라고 생각하면 편합니다.

View

  • 사용자에게 보여지는 UI 입니다.
  • Activity,Fragmet의 xml이 View에 해당되며 Pressenter에 이벤트를 전달합니다.
  • Activity와 Fragment는 뷰의 일부분입니다.

Presenter

  • M 과 V 사이에 다리역할을 한다고 생각합시다.
  • View로부터 이벤트를 받아와서 처리하고 , Modeld에게 알려 업데이트를 합니다.
  • View에 연결되는 것이 아니라 인터페이스로 연결됩니다.
  • 중간에서 자료 전달하는 역할을 합니다.

동작의 순서

  1. 사용자의 Action들은 View를 통해 입력받는다.
  2. View는 데이터를 Presenter에 요청합니다.
  3. Presenter는 Model에게 데이터를 요청합니다.
  4. Model은 Presenter에서 요청받은 데이터를 응답합니다.
  5. Presenter는 View에게 데이터를 응답합니다.
  6. View는 Presenter가 응답한 데이터를 이용하여 화면을 나타냅니다

특징

Presenter는 View와 Model의 인스턴스를 가지고 있어 둘을 연결하는 접착제 역할을 합니다.

Presenter와 View는 1:1 관계입니다.

장점

MVP 패턴의 장점은 View와 Model의 의존성이 없다는 것입니다. MVP 패턴은 MVC 패턴의 단점이었던 View와 Model의 의존성을 해결하였습니다.

단점

MVC 패턴의 단점인 View와 Model 사이의 의존성은 해결되었지만, View와 Presenter 사이의 의존성이 높은 가지게 되는 단점이 있습니다. 어플리케이션이 복잡해 질 수록 View와 Presenter 사이의 의존성이 강해지는 단점이 있습니다.

interface Contract {

    //View와 Presenter 에서 필요한 메소드들을 가지고있음 interface
    interface View  {
        fun setCalcResult(res: Int)
        fun getFirstNum(): Int
        fun getSecondNum(): Int
    }
    interface Presenter  {
        fun calc(x: Int, y: Int, type: Char)
    }
}

뷰 - 클릭을 받아들이고 프레젠터로 입력값을 보낸다.
계산은 프레젠터에게 맡긴다.
프레젠터에서 뷰의 값을 받아서 계산할수 있도록 Presenter를 생성해준다.

그리고 Contract 인터페이스를 이용하여 결과값을 세팅해준다.

//View부분.
//presenter를 갖고있으며 , View를 상속받음.

class MainActivity : AppCompatActivity(), Contract.View {
    lateinit var binding : ActivityMainBinding
    val presenter by lazy { MainPresenter(this) }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.plus.setOnClickListener{
            presenter.calc(getFirstNum(),getSecondNum(),'+')
        }
        binding.minus.setOnClickListener{
            presenter.calc(getFirstNum(),getSecondNum(),'-')
        }
        binding.divide.setOnClickListener{
            presenter.calc(getFirstNum(),getSecondNum(),'/')
        }
        binding.multiply.setOnClickListener{
            presenter.calc(getFirstNum(),getSecondNum(),'*')
        }
    }

    override fun setCalcResult(res: Int) { binding.result.text = res.toString() }
    override fun getFirstNum(): Int = binding.leftValue.text.toString().toInt()
    override fun getSecondNum(): Int = binding.rightValue.text.toString().toInt()
}

프레젠터 - 실질적인 데이터 계산을 하는 곳
데이터의 결과값을 view.setCalcResult를 한다.
View와의 통신을 하기 위해서 매개변수로 view를 가지고 있는다.
calc라는 메소드는 view에서 받아온 값들을 계산해주고, view에게 다시 setCalcResult를 돌려준다.
view.setCalcResult(res)는 Contract.View에 들어있다.
메인액티비티에서 오버라이딩하여 값을 xml에 보여준다.

class MainPresenter(val view: Contract.View) : Contract.Presenter {

    //View에서 보여줄 값들을계산함.
    override fun calc(x: Int, y: Int, type: Char) {
        val res = when (type) {
            '+' -> x + y
            '-' -> x - y
            '*' -> x * y
            '/' -> x / y
            else -> 0
        }
        view.setCalcResult(res)
    }
}
profile
러닝커브를 따라서 등반중입니다.
post-custom-banner

0개의 댓글