• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MC_Hotdog
Yeah, you're right I'm still riding that crappy bike
博客园    首页    新随笔    联系   管理    订阅  订阅

设计模式

设计模式

  解决不断重复问题的方案,而这个方案之后就可以一次又一次的不断重复的使用

设计模式分类

  创建型模式:对对象创建会消耗系统的很多的资源,单独对对象的创建进行研究        

  •  简单工厂模式(Simple Factory)
  •  工厂方法模式(Factory Method)
  •  抽象工厂模式(Abstract Factory)
  •  创建者模式(Builder)
  •  原型模式(Prototype)
  •  单例模式(Singleton)

  结构型模式:对对象的结构、继承、依赖关系设计,这些会影响到后续程序的维护性、代码的健壮性、耦合性等

  • 外观模式(Facade)
  • 适配器模式(Adapter)
  • 代理模式(Proxy)
  • 装饰模式(Decorator)
  • 桥模式(Bridge)
  • 组合模式(Composite)
  • 享元模式(Flyweight)

  行为性模式:对对象的行为设计的好的话,对象的行为就会更清晰,它们之间的协作效率就会提高  

  • 模板方法模式(Template Method)
  • 观察者模式(Observer)
  • 状态模式(State)
  • 策略模式(Strategy)
  • 职责链模式(Chain of Responsibility)
  • 命令模式(Command)
  • 访问者模式(Visitor)
  • 调停者模式(Mediator)
  • 备忘录模式(Memento)
  • 迭代器模式(Iterator)
  • 解释器模式(Interpreter)

原则

  开闭原则:只能加代码,但是不能修改

  里氏替换原则:引用父类的地方必须能透明地使用其子类的对象

  依赖倒置原则:针对接口编程,而不是针对实现编程

  接口隔离原则:使用多个专门的接口,不使用总的单一接口

         多继承存在一个问题:钻石继承问题  A类是B.C类,D类也继承B.C类 A类就不知道从哪里继承来的

  迪米特原则:简单的说就是降低耦合

  单一职责:一个类只负责一个职责

接口说明

  当我们继承,继承父类时候,必须实现某个方法

  当我们使用from abc import ABCMeta, abstractmethod虚类也是实现某个抽象方法

简单工厂模式

  使用场景:  

    当类不知道它所必须创建的对象类的时候

    当一个类希望由它的子类来指定它所创建的对象的时候

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from abc import ABCMeta, abstractmethod
 5 
 6 
 7 class Payment(metaclass=ABCMeta):
 8     """抽象产品角色"""
 9 
10     @abstractmethod
11     def pay(self, money):
12         raise NotImplementedError
13 
14 
15 class AliPay(Payment):
16     """具体产品角色"""
17 
18     def pay(self, money):
19         print("支付宝支付%s元" % money)
20 
21 
22 class ApplePay(Payment):
23     """具体产品角色"""
24 
25     def pay(self, money):
26         print("苹果支付%s" % money)
27 
28 
29 class PaymentFactory:
30     """工厂角色"""
31 
32     def create_payment(self, method):
33         if method == "ApplePay":
34             return ApplePay()
35         elif method == "AliPay":
36             return AliPay()
37         else:
38             raise NameError(method)
39 
40 
41 pf = PaymentFactory()
42 p = pf.create_payment("ApplePay")
43 p.pay(100) 

总结:使用简单工厂模式时候,首先要定义一个抽象产品类,其次要实现具体的产品类,最后实现工厂类 

  优点:隐藏了对象创建的实现细节,客服端不需要修改代码

  缺点:违反了单一职责原则,将创建逻辑几种到工厂类里

     当添加新产品时候,需要修改工厂代码,违反开闭原则

工厂方法设计模式

  定义一个工厂接口,然后具体到某一个工厂

  使用场景:

    需要生产多种大量复杂对象的时候,需要降低耦合度的,系统需要经常扩展的情况下

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from abc import ABCMeta, abstractmethod
 5 
 6 
 7 class Payment(metaclass=ABCMeta):
 8     """抽象产品角色"""
 9 
10     @abstractmethod
11     def pay(self, money):
12         raise NotImplementedError
13 
14 
15 class AliPay(Payment):
16     """具体产品角色"""
17 
18     def __init__(self, use_huabei=False):
19         self.use_huabei = use_huabei
20 
21     def pay(self, money):
22         if self.use_huabei:
23             print("花呗支付%s元" % money)
24         else:
25             print("支付宝支付%s元" % money)
26 
27 
28 class ApplePay(Payment):
29     """具体产品角色"""
30 
31     def pay(self, money):
32         print("苹果支付%s" % money)
33 
34 
35 class PaymentFactory(metaclass=ABCMeta):
36     """抽象工厂角色"""
37 
38     @abstractmethod
39     def create_payment(self):
40         pass
41 
42 
43 class AliPayFactory(PaymentFactory):
44     """具体工厂角色"""
45 
46     def create_payment(self):
47         return AliPay()
48 
49 
50 class ApplePayFactory(PaymentFactory):
51     def create_payment(self):
52         return ApplePay()
53 
54 
55 class HuaBeiFactory(PaymentFactory):
56     def create_payment(self):
57         return AliPay(use_huabei=True)
58 
59 
60 af = AliPayFactory()
61 ali = af.create_payment()
62 ali.pay(120)
63 
64 af1 = HuaBeiFactory()
65 ali1 = af1.create_payment()
66 ali1.pay(120)

总结:要使用工厂方法设计模式时候,要实现抽象产品类,具体产品类,抽象工厂类,具体工厂类

    优点:不需要修改工厂类代码,隐藏对象的实现细节

    缺点:每增加一个具体产品,都需要加一个相应的具体工厂类

抽象工厂模式

  使用场景:

    系统要独立于产品的创建于组合(着重组合)

    强调一系列相关的产品对象的设计以便进行联合使用   

  1 #!/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 
  4 from abc import abstractmethod, ABCMeta
  5 
  6 
  7 # -------抽象产品---------
  8 class PhoneShell(metaclass=ABCMeta):
  9     @abstractmethod
 10     def show_shell(self):
 11         pass
 12 
 13 
 14 class CPU(metaclass=ABCMeta):
 15     @abstractmethod
 16     def show_cpu(self):
 17         pass
 18 
 19 
 20 class OS(metaclass=ABCMeta):
 21     @abstractmethod
 22     def show_os(self):
 23         pass
 24 
 25 
 26 # ------------------抽象工厂-------------------
 27 class PhoneFactory(metaclass=ABCMeta):
 28     @abstractmethod
 29     def make_shell(self):
 30         pass
 31 
 32     @abstractmethod
 33     def make_cpu(self):
 34         pass
 35 
 36     @abstractmethod
 37     def make_os(self):
 38         pass
 39 
 40 
 41 # ----------------具体产品--------------
 42 class SmallShell(PhoneShell):
 43     def show_shell(self):
 44         print("普通的小手机壳")
 45 
 46 
 47 class BigShell(PhoneShell):
 48     def show_shell(self):
 49         print("普通的大手机壳")
 50 
 51 
 52 class AppleShell(PhoneShell):
 53     def show_shell(self):
 54         print("苹果手机壳")
 55 
 56 
 57 class AppleCPU(CPU):
 58     def show_cpu(self):
 59         print("苹果cpu")
 60 
 61 
 62 class SnapDragonCPU(CPU):
 63     def show_cpu(self):
 64         print("骁龙cpu")
 65 
 66 
 67 class IOS(OS):
 68     def show_os(self):
 69         print("ios系统")
 70 
 71 
 72 class Android(OS):
 73     def show_os(self):
 74         print("安卓系统")
 75 
 76 
 77 # -----------------具体工厂-------------
 78 class MiFactory(PhoneFactory):
 79     def make_cpu(self):
 80         return SnapDragonCPU()
 81 
 82     def make_os(self):
 83         return Android()
 84 
 85     def make_shell(self):
 86         return BigShell()
 87 
 88 
 89 class AppleFactory(PhoneFactory):
 90     def make_cpu(self):
 91         return AppleCPU()
 92 
 93     def make_os(self):
 94         return IOS()
 95 
 96     def make_shell(self):
 97         return AppleShell()
 98 
 99 
100 # ----------------客服端----------------
101 class Phone:
102     def __init__(self, cpu, os, shell):
103         self.cpu = cpu
104         self.os = os
105         self.shell = shell
106 
107     def show_info(self):
108         print("手机信息是:")
109         self.cpu.show_cpu()
110         self.os.show_os()
111         self.shell.show_shell()
112 
113 
114 def make_phone(factory):
115     cpu = factory.make_cpu()
116     os = factory.make_os()
117     shell = factory.make_shell()
118     return Phone(cpu, os, shell)
119 
120 
121 p1 = make_phone(AppleFactory())
122 p1.show_info()
123 
124 """
125 手机信息是:
126 苹果cpu
127 ios系统
128 苹果手机壳
129 """ 

总结:要使用抽象工厂模式的时候,要实现抽象产品,抽象工厂,具体产品,具体工厂,客服端

    优点:将客服端与类的具体实现相分离

       每个工厂创建了一个完整的产品系列

       有利于产品的一致性(产品之间的约束关系) 

    缺点:难以支持新种类的(抽象)产品 

建造者模式

  内容:

    将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  使用场景:

    建造者模式着重一步步构造一个复杂对象,与上述抽象工厂模式对比它着重多个系列的产品对象

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from abc import abstractmethod, ABCMeta
 5 
 6 
 7 # -------------------产品--------------------
 8 class Player:
 9     def __init__(self, face=None, body=None, arm=None, leg=None):
10         self.face = face
11         self.arm = arm
12         self.leg = leg
13         self.body = body
14 
15     def __str__(self):
16         return "%s, %s, %s, %s的猴子" % (self.face, self.arm, self.leg, self.body)
17 
18 
19 class PlayerBuilder(metaclass=ABCMeta):
20     @abstractmethod
21     def build_face(self):
22         pass
23 
24     @abstractmethod
25     def build_arm(self):
26         pass
27 
28     @abstractmethod
29     def build_leg(self):
30         pass
31 
32     @abstractmethod
33     def build_body(self):
34         pass
35 
36     @abstractmethod
37     def get_player(self):
38         pass
39 
40 
41 class BeautifulWomanBuilder(PlayerBuilder):
42     def __init__(self):
43         self.player = Player()
44 
45     def build_face(self):
46         self.player.face = "脸蛋漂亮"
47 
48     def build_arm(self):
49         self.player.arm = "细胳膊"
50 
51     def build_body(self):
52         self.player.body = "细腰"
53 
54     def build_leg(self):
55         self.player.leg = "大长腿"
56 
57     def get_player(self):
58         return self.player
59 
60 
61 class PlayerDirector:
62     """指挥者"""
63     def build_player(self, builder):
64         builder.build_body()
65         builder.build_face()
66         builder.build_arm()
67         builder.build_leg()
68         return builder.get_player()
69 
70 
71 pd = PlayerDirector()
72 pb = BeautifulWomanBuilder()
73 p = pd.build_player(pb)
74 print(p) 

总结:如果场景适合的情况下,需要创建抽象建造者类,具体建造者,指挥者,产品

     优点:隐藏了一个产品的内部结构和装配过程

        将构造代码与表示代码分开

        可以对构造过程进行更精细的控制

单例模式

  内容:保证一个类只有一个实例,并提供一个访问它的全局访问点

  使用场景:当类只能有一个实例而且客服可以从一个众所周知的访问点访问(日志对象,数据库连接,文件对象,都要关闭才能连接,import,相似全局变量)  

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 class Singleton(object):
 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 
11 
12 class Myclass(Singleton):
13     def __init__(self, name=None):
14         if name is not None:
15             self.name = name
16 
17 
18 a = Myclass("a")
19 print(a)
20 print(a.name)
21 
22 b = Myclass("b")
23 print(b)
24 print(b.name)
25 
26 print(a)
27 print(a.name)
28 """
29 <__main__.Myclass object at 0x000001FC1CBDFA20>
30 a
31 <__main__.Myclass object at 0x000001FC1CBDFA20>
32 b
33 <__main__.Myclass object at 0x000001FC1CBDFA20>
34 b
35 """ 

总结:

  优点:对唯一实例的访问受控

代理模式

  内容:为其它对象提供一种代理以控制对这个对象的访问

  使用场景:远程代理:为远程的对象提供代理  虚代理:根据需要创建很大的对象省内存 保护代理:控制对原始对象的访问

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 """
 5 远程代理: 如果别的机器想用我的接口,我就要在本地实现一个socket连接类,煞笔250调用的时候先连接我再调用我的接口
 6 虚代理:根据需要创建对象 比如手机省流量无图片模式的时候,它需要看图才给它创建
 7 保护代理:存好的表数据对象,只能读不能写的时候
 8 """
 9 from abc import ABCMeta, abstractmethod
10 
11 
12 class Subject(metaclass=ABCMeta):
13     @abstractmethod
14     def get_content(self):
15         raise NotImplementedError
16 
17 
18 class RealSubject(Subject):
19     def __init__(self, filename):
20         print('打开文件开始读取文件%s' % filename)
21         f = open(filename)
22         self.content = f.read()
23         f.close()
24 
25     def get_content(self):
26         return self.content
27 
28 
29 class ProxyA(Subject):
30     def __init__(self, filename):
31         self.filename = filename
32         self.subj = None
33 
34     def get_content(self):
35         if not self.subj:
36             self.subj = RealSubject(self.filename)
37         return self.subj.get_content()
38 
39 
40 p = ProxyA("abc.txt")  # 根本没读取,只有调用get_content才去读,虚代理
41 print(p.get_content())
42 
43 # 还可以写保护代理 修改文件的时候如果没有权限就不能写

总结:场景适合的话要使用就要创建抽象实体类,具体实体类,代理类

   优点:

      保护:对对象有一些附加的操作达到对此对象的保护

      虚:根据需要创建对象,节省内存

      远程:为远程的对象提供代理,比如远程对象不能直接访问,我封装socket之后它连接上我才能访问

适配器模式

  内容:能使得原来接口不兼容而不能一起工作的那些类可以一起工作。理解成月老,哈哈哈哈搭线

  使用场景:接口不兼容 

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from abc import ABCMeta, abstractmethod
 5 
 6 
 7 class Payment(metaclass=ABCMeta):
 8     """抽象产品角色"""
 9 
10     @abstractmethod
11     def pay(self, money):
12         raise NotImplementedError
13 
14 
15 class AliPay(Payment):
16     """具体产品角色"""
17 
18     def pay(self, money):
19         print("支付宝支付%s元" % money)
20 
21 
22 class ApplePay(Payment):
23     """具体产品角色"""
24 
25     def pay(self, money):
26         print("苹果支付%s" % money)
27 
28 
29 class WechatPay:
30     def huaqian(self, money):
31         print("微信支付%s元" % money)
32 
33 
34 class BankPay:
35     def huaqian(self, money):
36         print("银联支付%s元" % money)
37 
38 
39 # 类适配器
40 class NewWechatPay(WechatPay, Payment):
41     def pay(self, money):
42         self.huaqian(money)
43 
44 
45 # 对象适配器
46 class PaymentAdapter(Payment):
47     def __init__(self, w):
48         self.payment = w  # 对象
49 
50     def pay(self, money):
51         self.payment.huaqian(120)
52 
53 
54 # p = NewWechatPay()
55 # p.pay(120)
56 
57 p = PaymentAdapter(WechatPay())
58 p.pay(120)
59 
60 p = PaymentAdapter(BankPay())
61 p.pay(120)

总结:如果在满足使用场景,要去使用抽象产品,具体产品不符合接口规范(待适配类),适配器类

   实现两种方式:

    类适配器:使用多继承

    对象适配器:使用组合

 

持续更新中........    

 

 

 

posted @ 2019-09-08 22:40  MC_Hotdog  阅读(258)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3