5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Observer Patternを用いた簡素なMVCのpython実装例

Last updated at Posted at 2017-09-26

はじめに

アプリケーションを設計する際、Model-View-Controller (MVC) はもっとも基本的なアーキテクチャの一つです。
ここでは、Pythonのシンプルなコードを使って「コンソール入力→モデル更新→ビュー更新」という流れを体験できる最小のMVC構成を紹介します。

MVCの構造

以下の図は、今回実装するMVCの関係を示しています。

このように、

  • View はユーザーの入力や出力を担当します。
  • Controller は View と Model の仲介役として動きます。
  • Model はデータを保持し、変更があったときに View に通知します。

単純なMVC実装

最初に、1つの View のみを扱う最小構成を見てみましょう。

class Model:
    def __init__(self):
        self.__observer = None
        self.__text = None

    # Viewを登録
    def add_observer(self, observer):
        self.__observer = observer

    # データ取得
    @property
    def text(self):
        return self.__text

    # データ更新時に通知
    @text.setter
    def text(self, text):
        self.__text = text

        # 3. モデルの変更をビューに通知
        self.__observer.update(self)


class View:
    def input(self):
        # ユーザーから文字列を入力
        txt = input("Enter text: ")
        return txt

    # モデルの変更を受け取って出力
    def update(self, model):
        print(model.text)


class Controller:
    def __init__(self):
        self.model = Model()
        self.view = View()
        self.model.add_observer(self.view)

    def start(self):
        # 1. View から入力を受け取る
        received = self.view.input()

        # 2. 受け取った値をモデルに書き込む
        self.model.text = received


if __name__ == '__main__':
    Controller().start()

このコードを実行すると、次のような流れで動きます:

Enter text: Hello MVC
Hello MVC

ユーザーの入力が View → Controller → Model へと伝わり、
Model が変更されると Observer(View)が更新されて出力されます。

複数のView(Observer)に対応する

次に、複数のViewが同じModelを監視できるように拡張してみます。

class Model:
    def __init__(self):
        self.__observers = []
        self.__text = None

    # 複数Observerを登録
    def add_observer(self, observer):
        self.__observers.append(observer)

    # 全Observerに通知
    def notify_observers(self):
        for observer in self.__observers:
            observer.update(self)

    @property
    def text(self):
        return self.__text

    @text.setter
    def text(self, text):
        self.__text = text
        self.notify_observers()


class View:
    def input(self):
        return input("Enter text: ")

    def update(self, model):
        print(f"Updated View: {model.text}")


class Controller:
    def __init__(self):
        self.model = Model()
        self.view1 = View()
        self.view2 = View()
        # 2つのViewをObserverとして登録
        self.model.add_observer(self.view1)
        self.model.add_observer(self.view2)

    def start(self):
        # 1. View から入力を受け取る
        received = self.view1.input()

        # 2. 受け取った値をモデルに書き込む
        self.model.text = received


if __name__ == '__main__':
    Controller().start()

出力結果は以下のようになります:

Enter text: Python MVC
Updated View: Python MVC
Updated View: Python MVC

2つのViewが同じModelを監視しているため、両方が同時に更新されます。


まとめ

このサンプルで学べるポイント:

  • MVCは関心の分離を目的としている
  • Modelの変更をObserver(View)に通知することで、
    双方向依存を防ぎつつデータの一貫性を保てる
  • Pythonのクラスとプロパティを使えば、
    MVCの流れをシンプルに表現できる

このような小さな実験を通じて、
後にGUIアプリやWebフレームワーク(Django、Flaskなど)を学ぶ際にも構造の理解が深まります。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?