一.创立模式

1.简略工厂模式:

定义:

不间接向客户端裸露对象创立的实现细节,而是通过一个工厂类来负责创立产品类的实例。

应用场景:

长处:

  • 暗藏了对象创立的实现细节
  • 客户端不须要批改代码

毛病:

  • 违反了繁多职责准则,将创立逻辑几种到一个工厂类里
  • 当增加新产品时,须要批改工厂类代码,违反了开闭准则
from abc import abstractmethod, ABCMetaclass Payment(metaclass=ABCMeta):    @abstractmethod    def pay(self, money):        passclass Alipay(Payment):    def __init__(self, enable_yuebao=False):        self.enable_yuebao = enable_yuebao    def pay(self, money):        if self.enable_yuebao:            print("余额宝领取%s元" % money)        else:            print("支付宝领取%s元" % money)class ApplePay(Payment):    def pay(self, money):        print("苹果领取%s元" % money)class PaymentFactory:    def create_payment(self, method):        if method == "alipay":            return Alipay()        elif method == 'yuebao':            return Alipay(enable_yuebao=True)        elif method == "applepay":            return ApplePay()        else:            raise NameError(method)f = PaymentFactory()p = f.create_payment("yuebao")p.pay(100)

2.工厂办法模式:

定义:

定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。

实用场景:

  • 须要生产多种、大量简单对象的时候。
  • 须要升高耦合度的时候。
  • 当零碎中的产品种类须要常常扩大的时候。

长处:

  • 每个具体产品都对应一个具体工厂类,不须要批改工厂类代码
  • 暗藏了对象创立的实现细节

毛病:

  • 每减少一个具体产品类,就必须减少一个相应的具体工厂类
from abc import abstractmethod, ABCMetaclass Payment(metaclass=ABCMeta):    @abstractmethod    def pay(self, money):        passclass Alipay(Payment):    def pay(self, money):        print("支付宝领取%s元" % money)class ApplePay(Payment):    def pay(self, money):        print("苹果领取%s元" % money)class PaymentFactory(metaclass=ABCMeta):    @abstractmethod    def create_payment(self):        passclass AlipayFactory(PaymentFactory):    def create_payment(self):        return Alipay()class ApplePayFactory(PaymentFactory):    def create_payment(self):        return ApplePay()af = AlipayFactory()ali = af.create_payment()ali.pay(120)

3.形象工厂模式:

定义:

定义一个工厂类接口,让工厂子类来创立一系列相干或相互依赖的对象。

实用场景:

  • 零碎要独立于产品的创立与组合时
  • 强调一系列相干的产品对象的设计以便进行联结应用时
  • 提供一个产品类库,想暗藏产品的具体实现时

长处:

  • 将客户端与类的具体实现相拆散
  • 每个工厂创立了一个残缺的产品系列,使得易于替换产品系列
  • 有利于产品的一致性(即产品之间的束缚关系

毛病:

  • 难以反对新品种的(形象)产品
from abc import abstractmethod, ABCMeta# ------形象产品------class PhoneShell(metaclass=ABCMeta):    @abstractmethod    def show_shell(self):        passclass CPU(metaclass=ABCMeta):    @abstractmethod    def show_cpu(self):        passclass OS(metaclass=ABCMeta):    @abstractmethod    def show_os(self):        pass# ------形象工厂------class PhoneFactory(metaclass=ABCMeta):    @abstractmethod    def make_shell(self):        pass    @abstractmethod    def make_cpu(self):        pass    @abstractmethod    def make_os(self):        pass# ------具体产品------class SmallShell(PhoneShell):    def show_shell(self):        print("一般手机小手机壳")class BigShell(PhoneShell):    def show_shell(self):        print("一般手机大手机壳")class AppleShell(PhoneShell):    def show_shell(self):        print("苹果手机壳")class SnapDragonCPU(CPU):    def show_cpu(self):        print("骁龙CPU")class MediaTekCPU(CPU):    def show_cpu(self):        print("联发科CPU")class AppleCPU(CPU):    def show_cpu(self):        print("苹果CPU")class Android(OS):    def show_os(self):        print("Android零碎")class IOS(OS):    def show_os(self):        print("iOS零碎")# ------具体工厂------class MiFactory(PhoneFactory):    def make_cpu(self):        return SnapDragonCPU()    def make_os(self):        return Android()    def make_shell(self):        return BigShell()class HuaweiFactory(PhoneFactory):    def make_cpu(self):        return MediaTekCPU()    def make_os(self):        return Android()    def make_shell(self):        return SmallShell()class IPhoneFactory(PhoneFactory):    def make_cpu(self):        return AppleCPU()    def make_os(self):        return IOS()    def make_shell(self):        return AppleShell()# ------客户端------class Phone:    def __init__(self, cpu, os, shell):        self.cpu = cpu        self.os = os        self.shell = shell    def show_info(self):        print("手机信息:")        self.cpu.show_cpu()        self.os.show_os()        self.shell.show_shell()def make_phone(factory):    cpu = factory.make_cpu()    os = factory.make_os()    shell = factory.make_shell()    return Phone(cpu, os, shell)p1 = make_phone(HuaweiFactory())p1.show_info()

4.建造者模式:

定义:

将一个简单对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的示意。

实用场景:

  • 当创立简单对象的算法(Director)应该独立于该对象的组成部分以及它们的拆卸形式(Builder)时
  • 当结构过程容许被结构的对象有不同的示意时(不同Builder)。

长处:

  • 暗藏了一个产品的内部结构和拆卸过程
  • 将结构代码与示意代码离开
  • 能够对结构过程进行更精密的管制

毛病:

from abc import abstractmethod, ABCMeta# ------产品------class Player:    def __init__(self, face=None, body=None, arm=None, leg=None):        self.face = face        self.arm = arm        self.leg = leg        self.body = body    def __str__(self):        return "%s, %s, %s, %s" % (self.face, self.arm, self.body, self.leg)# ------建造者------class PlayerBuilder(metaclass=ABCMeta):    @abstractmethod    def build_face(self):        pass    @abstractmethod    def build_arm(self):        pass    @abstractmethod    def build_leg(self):        pass    @abstractmethod    def build_body(self):        pass    @abstractmethod    def get_player(self):        passclass BeautifulWomanBuilder(PlayerBuilder):    def __init__(self):        self.player = Player()    def build_face(self):        self.player.face = "丑陋脸蛋"    def build_arm(self):        self.player.arm = "细胳膊"    def build_body(self):        self.player.body = "细腰"    def build_leg(self):        self.player.leg = "长腿"    def get_player(self):        return self.playerclass PlayerDirector:    def build_player(self, builder):        builder.build_body()        builder.build_arm()        builder.build_leg()        builder.build_face()        return builder.get_player()director = PlayerDirector()builder = BeautifulWomanBuilder()p = director.build_player(builder)print(p)

5.单例模式:

定义:

保障一个类只有一个实例,并提供一个拜访它的全局拜访点。

实用场景:

  • 当类只能有一个实例而且客户能够从一个家喻户晓的拜访点拜访它时

长处:

  • 对惟一实例的受控拜访
  • 单例相当于全局变量,但避免了命名空间被净化。

毛病:

class Singleton(object):    def __new__(cls, *args, **kw):        if not hasattr(cls, '_instance'):            cls._instance = super(Singleton, cls).__new__(cls, )        return cls._instanceclass MyClass(Singleton):    a = 1    def __init__(self, name):        self.name = nameone = MyClass('egon')two = MyClass('alex')print(id(one))print(id(two))print(one == two)print(one is two)
def singleton(cls, *args, **kw):    instances = {}    def get_instance():        if cls not in instances:            instances[cls] = cls(*args, **kw)        return instances[cls]    return get_instance@singletonclass MyClass2:    a = 1one = MyClass2()two = MyClass2()print(id(one))  # 31495472print(id(two))  # 31495472print(one == two)print(one is two)
# Python的模块是人造的单例模式。# module_name.pyclass MySingleton(object):    def foo(self):        print('danli')my_singleton = MySingleton()# to usefrom .module_name import my_singletonmy_singleton.foo()print(id(my_singleton))from .module_name import my_singletonmy_singleton.foo()print(id(my_singleton))
class Singleton(type):    _instances = {}    def __call__(cls, *args, **kwargs):        if cls not in cls._instances:            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)        return cls._instances[cls]# Python2# class MyClass:#     __metaclass__ = Singleton# Python3class MyClass(metaclass=Singleton):    passone = MyClass()two = MyClass()print(id(one))print(id(two))print(one == two)print(one is two)

6.原型模式:

定义:

用原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象。

实用场景:

  • 通过动静装载;
  • 为了防止创立一个与产品类档次平行的工厂类档次时;
  • 当一个类的实例只能有几个不同状态组合中的一种时。建设相应数目的原型并克隆它们可能比每次用适合的状态手工实例化该类更不便一些。
import copyclass Prototype:    def __init__(self):        self._objects = {}    def register_object(self, name, obj):        """Register an object"""        self._objects[name] = obj    def unregister_object(self, name):        """Unregister an object"""        del self._objects[name]    def clone(self, name, **attr):        """Clone a registered object and update inner attributes dictionary"""        obj = copy.deepcopy(self._objects.get(name))        obj.__dict__.update(attr)        return objdef main():    class A:        def __str__(self):            return "I am A"    a = A()    prototype = Prototype()    prototype.register_object('a', a)    b = prototype.clone('a', a=1, b=2, c=3)    print(a)    print(b.a, b.b, b.c)if __name__ == '__main__':    main()

二.构造模式

1.适配器模式:

定义:

将一个类的接口转换成客户心愿的另一个接口。适配器模式使得本来因为接口不兼容而不能一起工作的那些类能够一起工作。

实用场景:

  • 想应用一个曾经存在的类,而它的接口不合乎你的要求
  • (对象适配器)想应用一些曾经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口。对象适配器能够适配它的父类接口。

类适配器:

  • 用一个具体的Adapter类对Adaptee和Target进行匹配。后果是当咱们想要匹配一个类以及所有他的子类时,类Adaptee将不能胜任工作。
  • 使得Adapter能够重定义Adaptee的局部行为,因为Adapter是Adaptee的一个子类。
  • 仅仅引入一个对象,并不需要额定的指针以间接失去Adaptee。

对象适配器:

  • 容许一个Adapter与多个Adaptee——即Adaptee自身以及它所有的子类(如果有子类的话)一同时工作。Adapter也能够一次给所有的Adaptee增加性能。
  • 使得重定义Adaptee的行为比拟艰难。这酒须要生成Adaptee的子类并且使得Adapter援用这个子类而不是援用Adaptee自身。
from abc import abstractmethod, ABCMetaclass Payment(metaclass=ABCMeta):    @abstractmethod    def pay(self, money):        raise NotImplementedErrorclass Alipay(Payment):    def pay(self, money):        print("支付宝领取%s元" % money)class ApplePay(Payment):    def pay(self, money):        print("苹果领取%s元" % money)# ------待适配类------class WechatPay:    def cost(self, money):        print("微信领取%s元" % money)# 类适配器class RealWechatPay(WechatPay, Payment):    def pay(self, money):        return self.cost(money)# 对象适配器class RealWechatPay2(Payment):    def __init__(self):        self.payment = WechatPay()    def pay(self, money):        return self.payment.cost(money)p = RealWechatPay2()p.pay(111)

2.组合模式:

定义:

将对象组合成树形构造以示意“局部-整体”的层次结构。组合模式使得用户对单个对象和组合对象的应用具备一致性。

实用场景:

  • 示意对象的“局部-整体”层次结构(特地是构造是递归的)
  • 心愿用户疏忽组合对象与单个对象的不同,用户对立地应用组合构造中的所有对象

长处:

  • 定义了蕴含根本对象和组合对象的类层次结构
  • 简化客户端代码,即客户端能够统一地应用组合对象和单个对象
  • 更容易减少新类型的组件

毛病:

  • 很难限度组合中的组件
from abc import abstractmethod, ABCMetaclass Graphic(metaclass=ABCMeta):    @abstractmethod    def draw(self):        pass    @abstractmethod    def add(self, graphic):        pass    def getchildren(self):        pass# 图元class Point(Graphic):    def __init__(self, x, y):        self.x = x        self.y = y    def draw(self):        print(self)    def add(self, graphic):        raise TypeError    def getchildren(self):        raise TypeError    def __str__(self):        return "点(%s, %s)" % (self.x, self.y)class Line(Graphic):    def __init__(self, p1, p2):        self.p1 = p1        self.p2 = p2    def draw(self):        print(self)    def add(self, graphic):        raise TypeError    def getchildren(self):        raise TypeError    def __str__(self):        return "线段[%s, %s]" % (self.p1, self.p2)class Picture(Graphic):    def __init__(self):        self.children = []    def add(self, graphic):        self.children.append(graphic)    def getchildren(self):        return self.children    def draw(self):        print("------复合图形------")        for g in self.children:            g.draw()        print("------END------")pic1 = Picture()point = Point(2,3)pic1.add(point)pic1.add(Line(Point(1,2), Point(4,5)))pic1.add(Line(Point(0,1), Point(2,1)))pic2 = Picture()pic2.add(Point(-2,-1))pic2.add(Line(Point(0,0), Point(1,1)))pic = Picture()pic.add(pic1)pic.add(pic2)pic.draw()#pic1.draw()#point.draw()

3.代理模式:

定义:

为其余对象提供一种代理以管制对这个对象的拜访。

实用场景:

  • 近程代理:为近程的对象提供代理
  • 虚代理:依据须要创立很大的对象
  • 爱护代理:管制对原始对象的拜访,用于对象有不同拜访权限时

长处:

  • 近程代理:能够暗藏对象位于近程地址空间的事实
  • 虚代理:能够进行优化,例如依据要求创建对象
  • 爱护代理:容许在拜访一个对象时有一些附加的内务解决

毛病:

from abc import ABCMeta, abstractmethodclass Subject(metaclass=ABCMeta):    @abstractmethod    def get_content(self):        pass    def set_content(self, content):        passclass RealSubject(Subject):    def __init__(self, filename):        self.filename = filename        print("读取%s文件内容" % filename)        f = open(filename)        self.__content = f.read()        f.close()    def get_content(self):        return self.__content    def set_content(self, content):        f = open(self.filename, 'w')        f.write(content)        self.__content = content        f.close()# ---近程代理class ProxyA(Subject):    def __init__(self, filename):        self.subj = RealSubject(filename)    def get_content(self):        return self.subj.get_content()    def set_content(self, content):        return self.subj.set_content(content)# ---虚代理class ProxyB(Subject):    def __init__(self, filename):        self.filename = filename        self.subj = None    def get_content(self):        if not self.subj:            self.subj = RealSubject(self.filename)        return self.subj.get_content()x = ProxyB('abc.txt')# print(x.get_content())# ---爱护代理class ProxyC(Subject):    def __init__(self, filename):        self.subj = RealSubject(filename)    def get_content(self):        self.subj.get_content()    def set_content(self, content):        raise PermissionError# filename = "abc.txt"# username = input()# if username!="alex":#     p = ProxyC(filename)# else:#     p = ProxyA(filename)## print(p.get_content())

三.行为模式

1.责任链模式:

定义:

使多个对象都有机会解决申请,从而防止申请的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该申请,直到有一个对象解决它为止。

实用场景:

  • 有多个对象能够解决一个申请,哪个对象解决由运行时决定
  • 在不明确接收者的状况下,向多个对象中的一个提交一个申请

长处:

  • 升高耦合度:一个对象无需晓得是其余哪一个对象解决其申请

毛病:

  • 申请不保障被接管:链的末端没有解决或链配置谬误
from abc import ABCMeta, abstractmethodclass Handler(metaclass=ABCMeta):    @abstractmethod    def handle_leave(self, day):        passclass GeneralManagerHandler(Handler):    def handle_leave(self, day):        if day < 10:            print("总经理批准%d天假" % day)            return True        else:            print("呵呵")            return Falseclass DepartmentManagerHandler(Handler):    def __init__(self):        self.successor = GeneralManagerHandler()    def handle_leave(self, day):        if day < 7:            print("部门经理批准%d天假" % day)            return True        else:            print("部门经理无权准假")            return self.successor.handle_leave(day)class ProjectDirectorHandler(Handler):    def __init__(self):        self.successor = DepartmentManagerHandler()    def handle_leave(self, day):        if day < 3:            print("我的项目主管批准%d天假" % day)            return True        else:            print("我的项目主管无权准假")            return self.successor.handle_leave(day)day = 11h = ProjectDirectorHandler()print(h.handle_leave(day))

2.迭代器模式:

定义:

提供一种办法程序拜访一个聚合对象中的各个元素,而又不须要裸露该对象的外部示意。

实用场景:

  • 拜访一个聚合对象的内容而无需裸露它的外部示意。
  • 反对对聚合对象的多种遍历。
  • 为遍历不同的聚合构造提供一个对立的接口(即, 反对多态迭代)

实现办法:

iter__、__next

class LinkList:    """链表 头结点保留链表的长度"""    class Node:        def __init__(self, item=None):            self.item = item            self.next = None    class LinkListIterator:        def __init__(self, node):            self.node = node        def __next__(self):            if self.node:                cur_node = self.node                self.node = cur_node.next                return cur_node.item            else:                raise StopIteration        def __iter__(self):            return self    def __init__(self, iterable=None):        self.head = LinkList.Node(0)        self.tail = self.head        self.extend(iterable)    def append(self, obj):        s = LinkList.Node(obj)        self.tail.next = s        self.tail = s        self.head.item += 1    def extend(self, iterable):        for obj in iterable:            self.append(obj)    def __iter__(self):        return self.LinkListIterator(self.head.next)    def __len__(self):        return self.head.item    def __str__(self):        return "<<" + ", ".join(map(str, self)) + ">>"li = [i for i in range(100)]lk = LinkList(li)print(lk)

3.观察者模式:

定义:

定义对象间的一种一对多的依赖关系,当一个对象的状态产生扭转时, 所有依赖于它的对象都失去告诉并被自动更新。观察者模式又称“公布-订阅”模式

实用场景:

  • 当一个形象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们能够各自独立地扭转和复用。
  • 当对一个对象的扭转须要同时扭转其它对象,而不晓得具体有多少对象有待扭转。
  • 当一个对象必须告诉其它对象,而它又不能假设其它对象是谁。换言之,你不心愿这些对象是严密耦合的。

长处:

  • 指标和观察者之间的形象耦合最小
  • 反对播送通信

毛病:

  • 多个观察者之间互不晓得对方存在,因而一个观察者对主题的批改可能造成谬误的更新。
from abc import ABCMeta, abstractmethodclass Observer(metaclass=ABCMeta):    @abstractmethod    def update(self, notice):        passclass Notice:    def __init__(self):        self.observers = []    def attach(self, obs):        self.observers.append(obs)    def detach(self, obs):        self.observers.remove(obs)        # obs.company_info=None    def notify(self):        for obj in self.observers:            obj.update(self)class ManagerNotice(Notice):    def __init__(self, company_info=None):        super().__init__()        self.__company_info = company_info    def detach(self, obs):        super().detach(obs)        obs.company_info = None    @property    def company_info(self):        return self.__company_info    @company_info.setter    def company_info(self, info):        self.__company_info = info        self.notify()class Manager(Observer):    def __init__(self):        self.company_info = None    def update(self, noti):        self.company_info = noti.company_infonotice = ManagerNotice()alex = Manager()wusir = Manager()print(alex.company_info)print(wusir.company_info)notice.attach(alex)notice.attach(wusir)notice.company_info = "公司运行良好"print(alex.company_info)print(wusir.company_info)notice.company_info = "公司将要上市"print(alex.company_info)print(wusir.company_info)notice.detach(wusir)notice.company_info = "公司要破产了,赶快跑路"print(alex.company_info)print(wusir.company_info)notice.company_info = "公司曾经破产了"print(alex.company_info)print(wusir.company_info)

4.策略模式:

定义:

定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于应用它的客户而变动。

实用场景:

  • 许多相干的类仅仅是行为有异
  • 须要应用一个算法的不同变体
  • 算法应用了客户端无需晓得的数据
  • 一个类中的多种行为以多个条件语句的模式存在,能够将这些行为封装如不同的策略类中。

长处:

  • 定义了一系列可重用的算法和行为
  • 打消了一些条件语句
  • 能够提供雷同行为的不同实现

毛病:

  • 客户必须理解不同的策略
  • 策略与上下文之间的通信开销
  • 减少了对象的数目
from abc import ABCMeta, abstractmethodimport randomclass Sort(metaclass=ABCMeta):    @abstractmethod    def sort(self, data):        passclass QuickSort(Sort):    def quick_sort(self, data, left, right):        if left < right:            mid = self.partition(data, left, right)            self.quick_sort(data, left, mid - 1)            self.quick_sort(data, mid + 1, right)    def partition(self, data, left, right):        tmp = data[left]        while left < right:            while left < right and data[right] >= tmp:                right -= 1            data[left] = data[right]            while left < right and data[left] <= tmp:                left += 1            data[right] = data[left]        data[left] = tmp        return left    def sort(self, data):        print("疾速排序")        return self.quick_sort(data, 0, len(data) - 1)class MergeSort(Sort):    def merge(self, data, low, mid, high):        i = low        j = mid + 1        ltmp = []        while i <= mid and j <= high:            if data[i] <= data[j]:                ltmp.append(data[i])                i += 1            else:                ltmp.append(data[j])                j += 1        while i <= mid:            ltmp.append(data[i])            i += 1        while j <= high:            ltmp.append(data[j])            j += 1        data[low:high + 1] = ltmp    def merge_sort(self, data, low, high):        if low < high:            mid = (low + high) // 2            self.merge_sort(data, low, mid)            self.merge_sort(data, mid + 1, high)            self.merge(data, low, mid, high)    def sort(self, data):        print("归并排序")        return self.merge_sort(data, 0, len(data) - 1)class Context:    def __init__(self, data, strategy=None):        self.data = data        self.strategy = strategy    def set_strategy(self, strategy):        self.strategy = strategy    def do_strategy(self):        if self.strategy:            self.strategy.sort(self.data)        else:            raise TypeErrorli = list(range(100000))random.shuffle(li)context = Context(li, MergeSort())context.do_strategy()# print(context.data)random.shuffle(context.data)context.set_strategy(QuickSort())context.do_strategy()

5.模板模式:

定义:

定义一个操作中的算法的骨架,而将一些步骤提早到子类中。模板办法使得子类能够不扭转一个算法的构造即可重定义该算法的某些特定步骤。

实用场景:

  • 一次性实现一个算法的不变的局部
  • 各个子类中的公共行为应该被提取进去并集中到一个公共父类中以防止代码反复
  • 管制子类扩大
from abc import ABCMeta, abstractmethodclass IOHandler(metaclass=ABCMeta):    @abstractmethod    def open(self, name):        pass    @abstractmethod    def deal(self, change):        pass    @abstractmethod    def close(self):        pass    def process(self, name, change):        self.open(name)        self.deal(change)        self.close()class FileHandler(IOHandler):    def open(self, name):        self.file = open(name, "w")    def deal(self, change):        self.file.write(change)    def close(self):        self.file.close()f = FileHandler()f.process("abc.txt", "Hello World")