设计模式.pdf

抽象方法

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import abstractmethod, ABCMeta
  5. # ------抽象产品------
  6. class PhoneShell(metaclass=ABCMeta):
  7. @abstractmethod
  8. def show_shell(self):
  9. pass
  10. class CPU(metaclass=ABCMeta):
  11. @abstractmethod
  12. def show_cpu(self):
  13. pass
  14. class OS(metaclass=ABCMeta):
  15. @abstractmethod
  16. def show_os(self):
  17. pass
  18. # ------抽象工厂------
  19. class PhoneFactory(metaclass=ABCMeta):
  20. @abstractmethod
  21. def make_shell(self):
  22. pass
  23. @abstractmethod
  24. def make_cpu(self):
  25. pass
  26. @abstractmethod
  27. def make_os(self):
  28. pass
  29. # ------具体产品------
  30. class SmallShell(PhoneShell):
  31. def show_shell(self):
  32. print("普通手机小手机壳")
  33. class BigShell(PhoneShell):
  34. def show_shell(self):
  35. print("普通手机大手机壳")
  36. class AppleShell(PhoneShell):
  37. def show_shell(self):
  38. print("苹果手机壳")
  39. class SnapDragonCPU(CPU):
  40. def show_cpu(self):
  41. print("骁龙CPU")
  42. class MediaTekCPU(CPU):
  43. def show_cpu(self):
  44. print("联发科CPU")
  45. class AppleCPU(CPU):
  46. def show_cpu(self):
  47. print("苹果CPU")
  48. class Android(OS):
  49. def show_os(self):
  50. print("Android系统")
  51. class IOS(OS):
  52. def show_os(self):
  53. print("iOS系统")
  54. # ------具体工厂------
  55. class MiFactory(PhoneFactory):
  56. def make_cpu(self):
  57. return SnapDragonCPU()
  58. def make_os(self):
  59. return Android()
  60. def make_shell(self):
  61. return BigShell()
  62. class HuaweiFactory(PhoneFactory):
  63. def make_cpu(self):
  64. return MediaTekCPU()
  65. def make_os(self):
  66. return Android()
  67. def make_shell(self):
  68. return SmallShell()
  69. class IPhoneFactory(PhoneFactory):
  70. def make_cpu(self):
  71. return AppleCPU()
  72. def make_os(self):
  73. return IOS()
  74. def make_shell(self):
  75. return AppleShell()
  76. # ------客户端------
  77. class Phone:
  78. def __init__(self, cpu, os, shell):
  79. self.cpu = cpu
  80. self.os = os
  81. self.shell = shell
  82. def show_info(self):
  83. print("手机信息:")
  84. self.cpu.show_cpu()
  85. self.os.show_os()
  86. self.shell.show_shell()
  87. def make_phone(factory):
  88. cpu = factory.make_cpu()
  89. os = factory.make_os()
  90. shell = factory.make_shell()
  91. return Phone(cpu, os, shell)
  92. p1 = make_phone(IPhoneFactory())
  93. p1.show_info()

适配器

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import ABCMeta, abstractmethod
  5. class Payment(metaclass=ABCMeta):
  6. # abstract class
  7. @abstractmethod
  8. def pay(self, money):
  9. pass
  10. class Alipay(Payment):
  11. def pay(self, money):
  12. print("支付宝支付%d元." % money)
  13. class WechatPay(Payment):
  14. def pay(self, money):
  15. print("微信支付%d元." % money)
  16. class BankPay:
  17. def cost(self, money):
  18. print("银联支付%d元." % money)
  19. class ApplePay:
  20. def cost(self, money):
  21. print("苹果支付%d元." % money)
  22. # # 类适配器
  23. # class NewBankPay(Payment, BankPay):
  24. # def pay(self, money):
  25. # self.cost(money)
  26. # 对象适配器
  27. class PaymentAdapter(Payment):
  28. def __init__(self, payment):
  29. self.payment = payment
  30. def pay(self, money):
  31. self.payment.cost(money)
  32. p = PaymentAdapter(BankPay())
  33. p.pay(100)
  34. # 组合
  35. # class A:
  36. # pass
  37. #
  38. # class B:
  39. # def __init__(self):
  40. # self.a = A()

桥接模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/20
  4. from abc import ABCMeta, abstractmethod
  5. class Shape(metaclass=ABCMeta):
  6. def __init__(self, color):
  7. self.color = color
  8. @abstractmethod
  9. def draw(self):
  10. pass
  11. class Color(metaclass=ABCMeta):
  12. @abstractmethod
  13. def paint(self, shape):
  14. pass
  15. class Rectangle(Shape):
  16. name = "长方形"
  17. def draw(self):
  18. # 长方形逻辑
  19. self.color.paint(self)
  20. class Circle(Shape):
  21. name = "圆形"
  22. def draw(self):
  23. # 圆形逻辑
  24. self.color.paint(self)
  25. class Line(Shape):
  26. name = "直线"
  27. def draw(self):
  28. # 直线逻辑
  29. self.color.paint(self)
  30. class Red(Color):
  31. def paint(self, shape):
  32. print("红色的%s" % shape.name)
  33. class Green(Color):
  34. def paint(self, shape):
  35. print("绿色的%s" % shape.name)
  36. class Blue(Color):
  37. def paint(self, shape):
  38. print("蓝色的%s" % shape.name)
  39. shape = Line(Blue())
  40. shape.draw()
  41. shape2 = Circle(Green())
  42. shape2.draw()

创建者模式

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import ABCMeta, abstractmethod
  5. class Player:
  6. def __init__(self, face=None, body=None, arm=None, leg=None):
  7. self.face = face
  8. self.body = body
  9. self.arm = arm
  10. self.leg = leg
  11. def __str__(self):
  12. return "%s, %s, %s, %s" % (self.face, self.body, self.arm, self.leg)
  13. class PlayerBuilder(metaclass=ABCMeta):
  14. @abstractmethod
  15. def build_face(self):
  16. pass
  17. @abstractmethod
  18. def build_body(self):
  19. pass
  20. @abstractmethod
  21. def build_arm(self):
  22. pass
  23. @abstractmethod
  24. def build_leg(self):
  25. pass
  26. class SexyGirlBuilder(PlayerBuilder):
  27. def __init__(self):
  28. self.player = Player()
  29. def build_face(self):
  30. self.player.face = "漂亮脸蛋"
  31. def build_body(self):
  32. self.player.body = "苗条"
  33. def build_arm(self):
  34. self.player.arm = "漂亮胳膊"
  35. def build_leg(self):
  36. self.player.leg = "大长腿"
  37. class Monster(PlayerBuilder):
  38. def __init__(self):
  39. self.player = Player()
  40. def build_face(self):
  41. self.player.face = "怪兽脸"
  42. def build_body(self):
  43. self.player.body = "怪兽身材"
  44. def build_arm(self):
  45. self.player.arm = "长毛的胳膊"
  46. def build_leg(self):
  47. self.player.leg = "长毛的腿"
  48. class PlayerDirector: # 控制组装顺序
  49. def build_player(self, builder):
  50. builder.build_body()
  51. builder.build_face()
  52. builder.build_arm()
  53. builder.build_leg()
  54. return builder.player
  55. # client
  56. builder = Monster()
  57. director = PlayerDirector()
  58. p = director.build_player(builder)
  59. print(p)

责任链模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/26
  4. from abc import ABCMeta, abstractmethod
  5. class Handler(metaclass=ABCMeta):
  6. @abstractmethod
  7. def handle_leave(self, day):
  8. pass
  9. class GeneralManager(Handler):
  10. def handle_leave(self, day):
  11. if day <= 10:
  12. print("总经理准假%d天" % day)
  13. else:
  14. print("你还是辞职吧")
  15. class DepartmentManager(Handler):
  16. def __init__(self):
  17. self.next = GeneralManager()
  18. def handle_leave(self, day):
  19. if day <= 5:
  20. print("部门经理准假%s天" % day)
  21. else:
  22. print("部门经理职权不足")
  23. self.next.handle_leave(day)
  24. class ProjectDirector(Handler):
  25. def __init__(self):
  26. self.next = DepartmentManager()
  27. def handle_leave(self, day):
  28. if day <= 3:
  29. print("项目主管准假%d天" % day)
  30. else:
  31. print("项目主管职权不足")
  32. self.next.handle_leave(day)
  33. # Client
  34. day = 12
  35. h = ProjectDirector()
  36. h.handle_leave(day)

组合模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/21
  4. from abc import ABCMeta, abstractmethod
  5. # 抽象组件
  6. class Graphic(metaclass=ABCMeta):
  7. @abstractmethod
  8. def draw(self):
  9. pass
  10. # 叶子组件
  11. class Point(Graphic):
  12. def __init__(self, x, y):
  13. self.x = x
  14. self.y = y
  15. def __str__(self):
  16. return "点(%s, %s)" % (self.x, self.y)
  17. def draw(self):
  18. print(str(self))
  19. # 叶子组件
  20. class Line(Graphic):
  21. def __init__(self, p1, p2):
  22. self.p1 = p1
  23. self.p2 = p2
  24. def __str__(self):
  25. return "线段[%s, %s]" % (self.p1, self.p2)
  26. def draw(self):
  27. print(str(self))
  28. # 复合组件
  29. class Picture(Graphic):
  30. def __init__(self, iterable):
  31. self.children = []
  32. for g in iterable:
  33. self.add(g)
  34. def add(self, graphic):
  35. self.children.append(graphic)
  36. def draw(self):
  37. print("------复合图形------")
  38. for g in self.children:
  39. g.draw()
  40. print("------复合图形------")
  41. p1 = Point(2,3)
  42. l1 = Line(Point(3,4), Point(6,7))
  43. l2 = Line(Point(1,5), Point(2,8))
  44. pic1 = Picture([p1, l1, l2])
  45. p2 = Point(4,4)
  46. l3 = Line(Point(1,1), Point(0,0))
  47. pic2 = Picture([p2, l3])
  48. pic = Picture([pic1, pic2])
  49. pic.draw()

外观模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/26
  4. class CPU:
  5. def run(self):
  6. print("CPU开始运行")
  7. def stop(self):
  8. print("CPU停止运行")
  9. class Disk:
  10. def run(self):
  11. print("硬盘开始工作")
  12. def stop(self):
  13. print("硬盘停止工作")
  14. class Memory:
  15. def run(self):
  16. print("内存通电")
  17. def stop(self):
  18. print("内存断电")
  19. class Computer: # Facade
  20. def __init__(self):
  21. self.cpu = CPU()
  22. self.disk = Disk()
  23. self.memory = Memory()
  24. def run(self):
  25. self.cpu.run()
  26. self.disk.run()
  27. self.memory.run()
  28. def stop(self):
  29. self.cpu.stop()
  30. self.disk.stop()
  31. self.memory.stop()
  32. # Client
  33. computer = Computer()
  34. computer.run()
  35. computer.stop()

工厂方法模式

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import ABCMeta, abstractmethod
  5. class Payment(metaclass=ABCMeta):
  6. # abstract class
  7. @abstractmethod
  8. def pay(self, money):
  9. pass
  10. class Alipay(Payment):
  11. def __init__(self, use_huabei=False):
  12. self.use_huaei = use_huabei
  13. def pay(self, money):
  14. if self.use_huaei:
  15. print("花呗支付%d元." % money)
  16. else:
  17. print("支付宝余额支付%d元." % money)
  18. class WechatPay(Payment):
  19. def pay(self, money):
  20. print("微信支付%d元." % money)
  21. class BankPay(Payment):
  22. def pay(self, money):
  23. print("银行卡支付%d元." % money)
  24. class PaymentFactory(metaclass=ABCMeta):
  25. @abstractmethod
  26. def create_payment(self):
  27. pass
  28. class AlipayFactory(PaymentFactory):
  29. def create_payment(self):
  30. return Alipay()
  31. class WechatPayFactory(PaymentFactory):
  32. def create_payment(self):
  33. return WechatPay()
  34. class HuabeiFactory(PaymentFactory):
  35. def create_payment(self):
  36. return Alipay(use_huabei=True)
  37. class BankPayFactory(PaymentFactory):
  38. def create_payment(self):
  39. return BankPay()
  40. # client
  41. pf = HuabeiFactory()
  42. p = pf.create_payment()
  43. p.pay(100)

工厂模式

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import ABCMeta, abstractmethod
  5. class Payment(metaclass=ABCMeta):
  6. # abstract class
  7. @abstractmethod
  8. def pay(self, money):
  9. pass
  10. class Alipay(Payment):
  11. def __init__(self, use_huabei=False):
  12. self.use_huaei = use_huabei
  13. def pay(self, money):
  14. if self.use_huaei:
  15. print("花呗支付%d元." % money)
  16. else:
  17. print("支付宝余额支付%d元." % money)
  18. class WechatPay(Payment):
  19. def pay(self, money):
  20. print("微信支付%d元." % money)
  21. class PaymentFactory:
  22. def create_payment(self, method):
  23. if method == 'alipay':
  24. return Alipay()
  25. elif method == 'wechat':
  26. return WechatPay()
  27. elif method == 'huabei':
  28. return Alipay(use_huabei=True)
  29. else:
  30. raise TypeError("No such payment named %s" % method)
  31. # client
  32. pf = PaymentFactory()
  33. p = pf.create_payment('huabei')
  34. p.pay(100)

接口模式

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. # class Payment:
  5. # def pay(self, money):
  6. # raise NotImplementedError
  7. from abc import ABCMeta, abstractmethod
  8. # 接口
  9. # class Payment(metaclass=ABCMeta):
  10. # # abstract class
  11. # @abstractmethod
  12. # def pay(self, money):
  13. # pass
  14. #
  15. #
  16. # class Alipay(Payment):
  17. # def pay(self, money):
  18. # print("支付宝支付%d元." % money)
  19. #
  20. #
  21. # class WechatPay(Payment):
  22. # def pay(self, money):
  23. # print("微信支付%d元." % money)
  24. #
  25. #
  26. #
  27. # p = WechatPay()
  28. # p.pay(100)
  29. #
  30. # class User:
  31. # def show_name(self):
  32. # pass
  33. #
  34. # class VIPUser(User):
  35. # def show_name(self):
  36. # pass
  37. #
  38. # def show_user(u):
  39. # res = u.show_name()
  40. class LandAnimal(metaclass=ABCMeta):
  41. @abstractmethod
  42. def walk(self):
  43. pass
  44. class WaterAnimal(metaclass=ABCMeta):
  45. @abstractmethod
  46. def swim(self):
  47. pass
  48. class SkyAnimal(metaclass=ABCMeta):
  49. @abstractmethod
  50. def fly(self):
  51. pass
  52. class Tiger(LandAnimal):
  53. def walk(self):
  54. print("老虎走路")
  55. class Frog(LandAnimal, WaterAnimal):
  56. pass

观察者模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/27
  4. from abc import ABCMeta, abstractmethod
  5. class Observer(metaclass=ABCMeta): # 抽象订阅者
  6. @abstractmethod
  7. def update(self, notice): # notice 是一个Notice类的对象
  8. pass
  9. class Notice: # 抽象发布者
  10. def __init__(self):
  11. self.observers = []
  12. def attach(self, obs):
  13. self.observers.append(obs)
  14. def detach(self, obs):
  15. self.observers.remove(obs)
  16. def notify(self): # 推送
  17. for obs in self.observers:
  18. obs.update(self)
  19. class StaffNotice(Notice): # 具体发布者
  20. def __init__(self, company_info=None):
  21. super().__init__()
  22. self.__company_info = company_info
  23. @property
  24. def company_info(self):
  25. return self.__company_info
  26. @company_info.setter
  27. def company_info(self, info):
  28. self.__company_info = info
  29. self.notify() # 推送
  30. class Staff(Observer):
  31. def __init__(self):
  32. self.company_info = None
  33. def update(self, notice):
  34. self.company_info = notice.company_info
  35. # Client
  36. notice = StaffNotice("初始公司信息")
  37. s1 = Staff()
  38. s2 = Staff()
  39. notice.attach(s1)
  40. notice.attach(s2)
  41. notice.company_info = "公司今年业绩非常好,给大家发奖金!!!"
  42. print(s1.company_info)
  43. print(s2.company_info)
  44. notice.detach(s2)
  45. notice.company_info = "公司明天放假!!!"
  46. print(s1.company_info)
  47. print(s2.company_info)

代理模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/26
  4. from abc import ABCMeta, abstractmethod
  5. class Subject(metaclass=ABCMeta):
  6. @abstractmethod
  7. def get_content(self):
  8. pass
  9. @abstractmethod
  10. def set_content(self, content):
  11. pass
  12. class RealSubject(Subject):
  13. def __init__(self, filename):
  14. self.filename = filename
  15. f = open(filename, 'r', encoding='utf-8')
  16. print("读取文件内容")
  17. self.content = f.read()
  18. f.close()
  19. def get_content(self):
  20. return self.content
  21. def set_content(self, content):
  22. f = open(self.filename, 'w', encoding='utf-8')
  23. f.write(content)
  24. f.close()
  25. class VirtualProxy(Subject):
  26. def __init__(self, filename):
  27. self.filename = filename
  28. self.subj = None
  29. def get_content(self):
  30. if not self.subj:
  31. self.subj = RealSubject(self.filename)
  32. return self.subj.get_content()
  33. def set_content(self, content):
  34. if not subj:
  35. self.subj = RealSubject(self.filename)
  36. return self.subj.set_content(content)
  37. class ProtectedProxy(Subject):
  38. def __init__(self, filename):
  39. self.subj = RealSubject(filename)
  40. def get_content(self):
  41. return self.subj.get_content()
  42. def set_content(self, content):
  43. raise PermissionError("无写入权限")
  44. #subj = RealSubject("test.txt")
  45. #subj.get_content()
  46. subj = ProtectedProxy("test.txt")
  47. print(subj.get_content())
  48. subj.set_content("abc")

单例模式

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Date: 2018/12/1
  4. from abc import abstractmethod, ABCMeta
  5. class Singleton:
  6. def __new__(cls, *args, **kwargs):
  7. if not hasattr(cls, "_instance"):
  8. cls._instance = super(Singleton, cls).__new__(cls)
  9. return cls._instance
  10. class MyClass(Singleton):
  11. def __init__(self, a):
  12. self.a = a
  13. a = MyClass(10)
  14. b = MyClass(20)
  15. print(a.a)
  16. print(b.a)
  17. print(id(a), id(b))

策略模式

  1. # coding: utf-8
  2. # author: ztypl
  3. # date: 2018/12/27
  4. from abc import ABCMeta,abstractmethod
  5. class Strategy(metaclass=ABCMeta):
  6. @abstractmethod
  7. def execute(self, data):
  8. pass
  9. class FastStrategy(Strategy):
  10. def execute(self, data):
  11. print("用较快的策略处理%s" % data)
  12. class SlowStrategy(Strategy):
  13. def execute(self, data):
  14. print("用较慢的策略处理%s" % data)
  15. class Context:
  16. def __init__(self, strategy, data):
  17. self.data = data
  18. self.strategy = strategy
  19. def set_strategy(self, strategy):
  20. self.strategy = strategy
  21. def do_strategy(self):
  22. self.strategy.execute(self.data)
  23. # Client
  24. data = "[...]"
  25. s1 = FastStrategy()
  26. s2 = SlowStrategy()
  27. context = Context(s1, data)
  28. context.do_strategy()
  29. context.set_strategy(s2)
  30. context.do_strategy()

模板方法

# coding: utf-8
# author: ztypl
# date:   2018/12/27

from abc import ABCMeta, abstractmethod
from time import sleep


class Window(metaclass=ABCMeta):
    @abstractmethod
    def start(self):
        pass

    @abstractmethod
    def repaint(self):
        pass

    @abstractmethod
    def stop(self): # 原子操作/钩子操作
        pass

    def run(self):  # 模板方法
        self.start()
        while True:
            try:
                self.repaint()
                sleep(1)
            except KeyboardInterrupt:
                break
        self.stop()


class MyWindow(Window):
    def __init__(self, msg):
        self.msg = msg

    def start(self):
        print("窗口开始运行")

    def stop(self):
        print("窗口结束运行")

    def repaint(self):
        print(self.msg)


MyWindow("Hello...").run()