zoukankan      html  css  js  c++  java
  • 设计模式

    设计模式

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

    设计模式分类

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

    •  简单工厂模式(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)

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

       实现两种方式:

        类适配器:使用多继承

        对象适配器:使用组合

     

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

     

  • 相关阅读:
    chmod命令
    ls命令
    数组值去重-小技巧
    使用redis接管session
    使用redis接管cookie
    redis操作封装类
    HTTP协议详解
    Linux网络编程--多播
    Live555 分析(三):客服端
    Live555 分析(二):服务端
  • 原文地址:https://www.cnblogs.com/Alexephor/p/11414988.html
Copyright © 2011-2022 走看看