目次
● Adapter パターン
● Bridge パターン
● Composite パターン
● Decorator パターン
● Facade パターン
● Flyweight パターン
● Proxy パターン
その他のデザインパターン
● Adapter パターン
Adapter.py
# ---------------------------------------------------------------------------------------
# Adapter パターン
# ---------------------------------------------------------------------------------------
# 互換性のないインタフェースを持つクラス同士を接続できるようにします
from abc import ABCMeta, abstractmethod
# 抽象的な製品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# 具象クラス(製品)
class VisaPay(Payment):
def pay(self, money):
print("Visa支払い:{0}円".format(money))
# 具象クラス(製品)
class MasterPay(Payment):
def pay(self, money):
print("Master支払い:{0}円".format(money))
# BankPayクラスはを編集しない理由があるとします。
class BankPay(object):
def show_pay(self, money):
print("銀行支払い:{0}円".format(money))
# クラスアダプタ(継承を用いる方法)
class NewBankPay(Payment, BankPay):
def pay(self, money):
self.show_pay(money)
# オブジェクトアダプタ(委譲を用いる方法)
class PaymentAdapter(Payment):
def __init__(self, payment):
self.payment = payment
def pay(self, money):
self.payment.show_pay(money)
if __name__ == '__main__':
# クラスアダプタ
print("--- 継承を用いる方法 ---")
p1 = NewBankPay()
p1.pay(1000)
# オブジェクトアダプタ
print("--- 委譲を用いる方法 ---")
p2 = PaymentAdapter(BankPay())
p2.pay(3000)
実行結果:
--- 継承を用いる方法 ---
銀行支払い:1000円
--- 委譲を用いる方法 ---
銀行支払い:3000円
● Bridge パターン
Bridge.py
# ---------------------------------------------------------------------------------------
# Bridge パターン
# ---------------------------------------------------------------------------------------
# 抽象化と実現を分離して、継承関係を関連関係に変換することで、それぞれ、独立して変更できるようにします。
from abc import ABCMeta, abstractmethod
class ShapeInterface(metaclass=ABCMeta):
def __init__(self, color):
self.color = color
@abstractmethod
def draw(self):
pass
class ColorInterface(metaclass=ABCMeta):
@abstractmethod
def print_info(self, shape):
pass
class Triangle(ShapeInterface):
shape_name = "三角"
def draw(self):
self.color.print_info(self)
class Circle(ShapeInterface):
shape_name = "円"
def draw(self):
self.color.print_info(self)
class Blue(ColorInterface):
def print_info(self, shape):
print("ブルー{0}".format(shape.shape_name))
class Yellow(ColorInterface):
def print_info(self, shape):
print("黄色{0}".format(shape.shape_name))
if __name__ == '__main__':
# ブルー三角というオブジェクトを作成
tb = Triangle(Blue())
tb.draw()
# 黄色三角というオブジェクトを作成
ty = Triangle(Yellow())
ty.draw()
# 黄色円というオブジェクトを作成
cy = Circle(Yellow())
cy.draw()
実行結果:
ブルー三角
黄色三角
黄色円
● Composite パターン
Composite.py
# ---------------------------------------------------------------------------------------
# Composite パターン
# ---------------------------------------------------------------------------------------
# 容器と中身を同一視することで、再帰的な構造を構築できるようにします。
class Component:
def __init__(self, name):
self.name = name
self.children = []
def add(self, comp):
self.children.append(comp)
def remove(self, comp):
self.remove(comp)
def show(self, depth):
buf = ''
for i in range(depth):
buf += '-----'
print(buf + self.name)
for comp in self.children:
comp.show(depth + 1)
class Leaf(Component):
def add(self, comp):
print('追加できません')
def remove(self, comp):
print('削除できません')
class Node(Component):
pass
if __name__ == '__main__':
root = Node('Dドライブ')
root.add(Leaf('ファイル1'))
root.add(Leaf('ファイル2'))
fd1 = Node('※フォルダー1')
fd2 = Node('※フォルダー2')
fd3 = Node('※フォルダー3')
root.add(fd1)
root.add(fd2)
root.add(fd3)
fd1.add(Leaf('Fd1のファイル11'))
fd1.add(Leaf('Fd1のファイル12'))
fd2.add(Leaf('Fd2のファイル21'))
root.show(1)
実行結果:
-----Dドライブ
----------ファイル1
----------ファイル2
----------※フォルダー1
---------------Fd1のファイル11
---------------Fd1のファイル12
----------※フォルダー2
---------------Fd2のファイル21
----------※フォルダー3
● Decorator パターン
Decorator.py
# ---------------------------------------------------------------------------------------
# Decorator パターン
# ---------------------------------------------------------------------------------------
# 構造を変更せずに、既存のオブジェクトに新しい機能を追加できるようにします。
class Foo:
def method1(self):
print('Foo:method1')
def method2(self):
print('Foo:method2')
def method3(self):
print('Foo:method3')
class FooDecorator:
def __init__(self, foo):
self.foo = foo
def method2(self):
print('.' * 20)
print('FooDecorator:method2')
self.foo.method2()
print('-' * 20)
def __getattr__(self, item):
return getattr(self.foo, item)
if __name__ == '__main__':
fd = FooDecorator(Foo())
fd.method2()
fd.method1()
fd.method3()
実行結果:
....................
FooDecorator:method2
Foo:method2
--------------------
Foo:method1
Foo:method3
● Facade パターン
Facade.py
# ---------------------------------------------------------------------------------------
# Facade パターン
# ---------------------------------------------------------------------------------------
# 複雑なサブシステム内の機能を利用するため、シンプルなインターフェースを提供します。
class SubSystem1:
def method_a(self):
print('Run SubSystem1.method_a')
class SubSystem2:
def method_b(self):
print('Run SubSystem2.method_b')
class SubSystem3:
def method_c(self):
print('Run SubSystem3.method_c')
class FacadeSystem:
def __init__(self):
self.subsystem1 = SubSystem1()
self.subsystem2 = SubSystem2()
self.subsystem3 = SubSystem3()
def method(self):
self.subsystem1.method_a()
self.subsystem2.method_b()
self.subsystem3.method_c()
if __name__ == '__main__':
facade = FacadeSystem()
facade.method()
実行結果:
Run SubSystem1.method_a
Run SubSystem2.method_b
Run SubSystem3.method_c
● Flyweight パターン
Flyweight.py
# ---------------------------------------------------------------------------------------
# Flyweight パターン
# ---------------------------------------------------------------------------------------
# 生成済みのオブジェクトを共有し、余分なオブジェクトの生成を防止します。
class Flyweight:
def __init__(self, name):
self.name = name
def show(self):
print('Flyweight Name: {0}'.format(self.name))
class FlyweightFactory:
def __init__(self):
self.objs = {}
def get_object(self, objname):
# 生成済みのオブジェクトを再利用
obj = self.objs.get(objname)
if not obj:
obj = Flyweight(objname)
self.objs[objname] = obj
return obj
def display(self):
for obj in self.objs.values():
obj.show()
print('オブジェクト数: {0}'.format(len(self.objs)))
if __name__ == '__main__':
flyweight_factory = FlyweightFactory()
f1 = flyweight_factory.get_object('AA')
f2 = flyweight_factory.get_object('BB')
f3 = flyweight_factory.get_object('AA')
flyweight_factory.display()
実行結果:
Flyweight Name: AA
Flyweight Name: BB
オブジェクト数: 2
● Proxy パターン
Proxy.py
# ---------------------------------------------------------------------------------------
# Proxy パターン
# ---------------------------------------------------------------------------------------
# オブジェクトへのアクセスを制御するために、そのオブジェクトの代理を提供します。
from abc import ABCMeta, abstractmethod
class Staff(metaclass=ABCMeta):
@abstractmethod
def work(self):
pass
class RealStaff(Staff):
def work(self):
print('RealStaff:work')
class ProxyStaff(Staff):
def __init__(self):
self.real_staff = None
def work(self):
if self.real_staff is None:
self.real_staff = RealStaff()
print('ProxyStaff:work')
self.real_staff.work()
if __name__ == '__main__':
proxy_staff = ProxyStaff()
proxy_staff.work()
実行結果:
ProxyStaff:work
RealStaff:work
その他のデザインパターン
Pythonで生成に関するデザインパターンを作成してみた
Pythonで振る舞いに関するデザインパターンを作成してみた