注意)このTicketはあくまで自分用のメモ。厳密な定義などは参考サイトを参照のこと
Observerパターンについて学ぶ
参考サイト1の動画で紹介されているJavsScriptのコードを自分なりにpythonに書き直して学習する。今回はグラフ表示のためmatplotlibを利用した。もし実行する場合は下記を実行すること。
pip install matplotlib
Observerパターンとは
参考サイト1を参照、分かりやすい。
pythonで書いてみた
import matplotlib as mpl
mpl.use('Agg') # backendsを指定する
import matplotlib.pyplot as plt
'''
入力データ:x座標のデータとy座標のデータが交互に登場して半角スペースで区切って列挙してあるものとする
入力データ例:10 30 20 20 30 40
'''
class Subject():
def __init__(self):
self.observers = []
def add(self,observer):
self.observers.append(observer)
def notify(self):
for observer in self.observers:
observer.update()
class GraphModel(Subject):
def __init__(self):
super().__init__()
self.data = []
def sync(self,data):
self.data = data
self.notify()
class ChartView():
def __init__(self,model):
self.model = model
self.model.add(self)
def generateGraphData(self):
self.labels = list(map(self.generateLabel, self.model.data[0::2]))
self.vals = list(map(int, self.model.data[1::2]))
def generateLabel(self,label):
return str(label) + "'s"
def update(self):
self.render()
class Figure():
def __init__(self,fig,order):
self.ROW = 3
self.COLUMN = 1
self.order = order
self.fig = fig
def addPlot(self):
self.fig.add_subplot(self.ROW,self.COLUMN,self.order)
class LineChartView(ChartView,Figure):
def __init__(self, model, fig, order):
ChartView.__init__(self,model)
Figure.__init__(self,fig,order)
def render(self):
self.generateGraphData()
self.addPlot()
plt.plot(self.labels, self.vals)
class BarChartView(ChartView,Figure):
def __init__(self, model, fig, order):
ChartView.__init__(self,model)
Figure.__init__(self,fig,order)
def render(self):
self.generateGraphData()
self.addPlot()
plt.bar(self.labels, self.vals)
class PieChartView(ChartView,Figure):
def __init__(self, model, fig, order):
ChartView.__init__(self,model)
Figure.__init__(self,fig,order)
def render(self):
self.generateGraphData()
self.addPlot()
plt.pie(self.vals,labels=self.labels)
if __name__=='__main__':
MODEL = GraphModel()
fig = plt.figure()
PieChartView(MODEL,fig,order=1)
LineChartView(MODEL,fig,order=2)
BarChartView(MODEL,fig,order=3)
MODEL.sync(input().split())
plt.savefig("hoge.png")
入力データ
10 30 20 10 30 40
実行結果
書いた感想
Observerパターンを利用しないパターンをまず書いて、次に利用するパターンを書いてみた。ObserverパターンのSubjectがObserverを追加して、追加したObserverに通知を送る。通知を送られたObserverが決まった動作をする。という一連の流れを実装したが、別にこの流れでなくても実装自体は可能だった。ただ、Observerパターンに沿うようにコードを書いているときに徐々に変更や追加に強い、疎結合のコードになっていっているのを感じた。
Observerパターン どういったときに使う?
オブジェクトの状態が変化したときに、それを通知して、通知を受けったオブジェクトが処理を実行するといった仕組みを作るときに使える。参考サイト1では主にフロントエンドの実装で使うことが多いと言っていたが、下記例のようにバックエンドでも使える仕組み。
例.
エクセルのようにデータがあってグラフが複数あるときに、データが変更されたらグラフの表示を変えるときに使える。(参考サイト1)
メーリングリストで、何らかのイベント(新製品情報など)があったとき、購読者リストに登録している人にメッセージを送る。(参考サイト3から引用)
書いたコード
github
nousecase.py:Observerパターンを利用しないでグラフを表示するコード。何をやっているのか理解するのに便利。
usecase.py:上記に表記したコード。Observerパターンを利用している。