Python 设计模式

什么是设计模式?

设计模式是通过总结、优化的,对咱们常常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样可以直接做用于咱们的代码。反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言。一个好的设计模式应该可以用大部分编程语言实现(若是作不到所有的话,具体取决于语言特性)。最为重要的是,设计模式也是一把双刃剑,若是设计模式被用在不恰当的情形下将会形成灾难,进而带来无穷的麻烦。然而若是设计模式在正确的时间被用在正确地地方,它将是你的救星。javascript

起初,你会认为“模式”就是为了解决一类特定问题而特别想出来的明智之举。说的没错,看起来的确是经过不少人一块儿工做,从不一样的角度看待问题进而造成的一个最通用、最灵活的解决方案。也许这些问题你曾经见过或是曾经解决过,可是你的解决方案极可能没有模式这么完备。html

虽然被称为“设计模式”,可是它们同“设计“领域并不是紧密联系。设计模式同传统意义上的分析、设计与实现不一样,事实上设计模式将一个完整的理念根植于程序中,因此它可能出如今分析阶段或是更高层的设计阶段。颇有趣的是由于设计模式的具体体现是程序代码,所以可能会让你认为它不会在具体实现阶段以前出现(事实上在进入具体实现阶段以前你都没有意识到正在使用具体的设计模式)。java

能够经过程序设计的基本概念来理解模式:增长一个抽象层。抽象一个事物就是隔离任何具体细节,这么作的目的是为了将那些不变的核心部分从其余细节中分离出来。当你发现你程序中的某些部分常常由于某些缘由改动,而你不想让这些改动的部分引起其余部分的改动,这时候你就须要思考那些不会变更的设计方法了。这么作不只会使代码可维护性更高,并且会让代码更易于理解,从而下降开发成本。python

这里列举了三种最基本的设计模式:算法

  1. 建立模式,提供实例化的方法,为适合的情况提供相应的对象建立方法。
  2. 结构化模式,一般用来处理实体之间的关系,使得这些实体可以更好地协同工做。
  3. 行为模式,用于在不一样的实体建进行通讯,为实体之间的通讯提供更容易,更灵活的通讯方法。

设计模式的六大原则

开闭原则:软件实体如类,模块,函数应该对扩展开放,对修改关闭 
里氏替换原则:全部饮用积累的地方必须透明地使用其子类的对象
依赖倒置原则:高层模块不该该依赖低层模块,两者都应该依赖其抽象;抽象不该该依赖细节,细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程
接口隔离原则:使用多个专门的接口,而不该该使用单一的总接口,即客户端不该该依赖那么它不须要的接口
迪米特法则:软件实体应当尽量少地与其余实体发生相互做用
单一职责原则:不要存在多于一个致使类变动的缘由。通俗的说,一个类只负责一项职责

 

哪些设计模式?

建立型shell

1. Factory Method(工厂方法)编程

2. Abstract Factory(抽象工厂)设计模式

3. Builder(建造者)微信

4. Prototype(原型)app

5. Singleton(单例)

结构型

6. Adapter Class/Object(适配器)

7. Bridge(桥接)

8. Composite(组合)

9. Decorator(装饰)

10. Facade(外观)

11. Flyweight(享元)

12. Proxy(代理)

行为型

13. Interpreter(解释器)

14. Template Method(模板方法)

15. Chain of Responsibility(责任链)

16. Command(命令)

17. Iterator(迭代器)

18. Mediator(中介者)

19. Memento(备忘录)

20. Observer(观察者)

21. State(状态)

22. Strategy(策略)

23. Visitor(访问者)

 

 

建立型模式

一、单例模式

看着碍眼,首先把以前提到过的最容易理解的讲掉。

内容:保证一个类只有一个实例,并提供一个访问它的全局访问点
优势:
    1、对惟一实例的受控访问
    二、单例至关于全局变量,但防止了命名空间被污染

代码实现:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__init__(cls)
        return cls._instance


class MyClass(Singleton):
    def __init__(self, name=None):
        self.name = name

 

先补充一个概念

类接口

#python 类的第一种接口写法


class Payment:
    def pay(self, money):
        raise NotImplementedError  # 报错,没用重写此方法


class Alipay(Payment):
    def pay(self, money):
        print('支付宝支付%s元' % money)


class Wechatpay(Payment):
    def pay(self, money):
        print('微信支付%s元' % money)


class Testpay(Payment):
    def fuqian(self, money):
        print('money', money)


def payx(payment, money):
    payment.pay(money)
payx(Testpay(), 100)


# 第二种接口写法
from abc import ABCMeta, abstractmethod


class Payment(metaclass=ABCMeta):
    @abstractmethod  # 类的抽象方法 def pay(self, money):
        pass


class Alipay(Payment):
    def pay(self, money):
        print('支付宝支付%s元' % money)


class Wechatpay(Payment):
    pass

def payx(payment, money):
    payment.pay(money)


payx(Wechatpay(), 100)

在Python中实现抽象方法最简单地方式是:上面的接口一的写法,任何继承自Payment的类必须覆盖实现方法pay,不然会抛出异常。这种抽象方法的实现有它的弊端,若是你写一个类继承Pizza,可是忘记实现get_radius,异常只有在你真正使用的时候才会抛出来。

还有一种方式可让错误更早的触发,使用Python提供的abc模块,对象被初始化以后就能够抛出异常:上面的接口二的写法。使用@abstractmethod后,当你尝试初始化Pyament或者任何子类的时候立马就会获得一个TypeError,而无需等到真正调用pay的时候才发现异常。

 

简单工厂模式

内容:不直接向客户端暴露对象建立的实现细节,而是经过一个工厂类来负责建立产品类的实例
角色:
  一、工厂角色 PaymentFactory

  二、抽象产品角色 Payment

  三、具体产品角色 Alipay & WechatPay
优势:
  一、隐藏了对象建立的实现细节  # 实例化过程,还有余额宝建立过程
  二、客户端不须要修改代码  # 客户端只有调用,传入参数就好
缺点:
  一、违反了单一职责原则,将建立逻辑集中到一个工厂类里
  二、当添加新产品时,须要修改工厂代码,违反了开闭原则

#!/usr/bin/env python3
# encoding: utf-8
# Author: Dandy
from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass


class Alipay(Payment):

    def __init__(self, enabled_yuebao = False):
        self.enabled_yuebao = enabled_yuebao

    def pay(self, money):
        if self.enabled_yuebao:
            print('余额宝支付%s元' % money)
        else:
            print('支付宝支付%s元' % money)


class Wechatpay(Payment):
    def pay(self, money):
        print('微信支付%s元' % money)


class PaymentFactory:
    def create_payment(self, method):
        if method == 'alipay':
            return Alipay()
        elif method == 'yuebaopay':
            return Alipay(True)
        elif method == 'wechatpay':
            return Wechatpay()
        else:
            raise NameError(method)


f = PaymentFactory()
p = f.create_payment('yuebaopay')
p.pay(100)

# 不暴露出建立对象的实现细节,而直接将实例化对象返回

 

具体产品继承并重写抽象类,工厂实例化具体产品到对象。 

 

工厂方法模式(Factory Method)

 

内容:定义一个用于建立对象的接口(工厂接口),让子类决定实例化哪个产品类。Factory Method 使个类的实例化延迟到其子类。

角色:
  一、抽象工厂角色  payment factory
  二、具体工厂角色  allipay factory
  三、抽象产品角色  payment
  四、具体产品角色  alipay

工厂方法模式相比简单工厂模式将每一个具体产品都对应了一个具体工厂。

使用场景

  一、须要生产多种,大量复杂对象的时候
  二、须要下降耦合度的时候
  三、当系统中的产品种类须要常常扩展的时候

优势:
  一、每一个具体产品都对应一个具体工厂类,不须要修改工厂类代码
  二、隐藏了对象建立的实现细节
缺点:
  一、每增长一个具体产品类,就必须增长一个相应的具体工厂类 

from abc import abstractmethod, ABCMeta


class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass


class AlipayFactory(PaymentFactory):

    def create_payment(self):
        return Alipay()


class ApplePayFactory(PaymentFactory):
    def create_payment(self, money):
        return ApplePay()


class Alipay(Payment):
    def pay(self, money):
        print('支付宝支付%s元' % money)


class ApplePay(Payment):
    def pay(self, money):
        print('苹果支付%s元' % money)


ali = AlipayFactory()
ali = ali.create_payment()
ali.pay(120)

抽象产品类被具体产品类继承,具体工厂继承抽象工厂并调用具体产品,不一样的具体工厂返回不一样的相对应的具体产品对象给用户。

 

 

抽象工厂模式(Abstract Factory)

抽象工厂模式
内容:定义一个工厂类接口,让工厂子类来建立一系列相关或相互依赖的对象
例如:生产一部手机须要,手机壳,cpu,操做系统三类对象进行组装,其中每类对象都有不一样的种类。对每一个具体工厂,分别生产一部手机所须要的三个对象。
角色:
  一、抽象工厂角色  PhoneFactory
  二、具体工厂角色  AppleFactory
  三、抽象产品角色  PhoneShell、CPU、OS
  四、具体产品角色  AppleShell
  五、客户端  
相比工厂方法模式,抽象工厂模式中的每一个具体工厂都生产一套产品。
适用场景:
  一、系统要独立于产品的建立和组合时
  二、强调一系列相关产品对象的设计以便进行联合使用时
  三、提供一个产品的类库,想隐藏产品的具体实现时
优势:
  一、将客户端与类的具体实现分离
  二、每一个工厂建立了一个完整的产品系列,使得易于交换产品系列
  三、有利于产品的一致性(即产品之间的约束关系)
缺点:
  一、难以支持新种类的(抽象)产品

代码

from abc import abstractmethod, ABCMeta

# ***** 抽象产品 ****
class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass


class CPU(metaclass=ABCMeta):
    @abstractmethod
    def show_cpu(self):
        pass


class OS(metaclass=ABCMeta):
    @abstractmethod
    def show_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('苹果')


class Android(OS):
    def show_os(self):
        print('Android系统')


class IOS(OS):
    def show_os(self):
        print('IOS 系统')


# ***************抽象工厂**************
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass


# ***************** 具体工厂 *************

class AppleFactory(PhoneFactory):
    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return IOS()

    def make_shell(self):
        return AppleShell()


class HuaweiFactory(PhoneFactory):
    def make_cpu(self):
        return SnapDragonCPU()

    def make_shell(self):
        return BigShell()

    def make_os(self):
        return Android()

# ************************ 客户端 **************************
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(AppleFactory())
p1.show_info()

 

 

建造者模式

 

内容:将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。
角色:
  一、抽象建造者
  二、具体建造者
  三、指挥者
  四、产品
建造者模式与抽象工厂模式类似,也用来建立复杂对象。主要区别在于见照着模式着重一步步构造一个复杂对象,二抽象工厂模式着重于多个系列的产品对象
适用场景:
  一、当建立复杂对象的算法(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.body = body
        self.arm = arm
        self.leg = leg

    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_body(self):
        pass

    @abstractmethod
    def build_leg(self):
        pass

    @abstractmethod
    def get_player(self):
        pass


# *************************** 具体建造者 *********************************

class BeautifulWomenBuilder(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.player


# ****************** 指挥者 *********************

class PlayDirector:
    def build_player(self, builder):
        builder.build_face()
        builder.build_body()
        builder.build_leg()
        builder.build_arm()
        return builder.get_player()


director = PlayDirector()
builder = BeautifulWomenBuilder()
person = director.build_player(builder)

print(person)

 

 

建立型模式小结


适用abstra factory、 prototype或者builder的设计甚至比适用factory method的那些设计更灵活,但他们也更加复杂。一般,设计以适用Factory method开始,而且设计者发现须要更大的灵活性时,设计便会向其余建立模式演化。当你在设计标准之间进行权衡的时候,了解多个模式能够给你提供更多的选择余地。
一、依赖于继承的建立型模式:工厂方法模式
二、依赖于组合的建立型模式:抽象工厂模式,建立者模式


工厂方法模式:一类产品,每类产品有多种
抽象工厂模式:多类产品,每类产品有多种
建造者模式:多类产品,每类产品有一种,目的是把多种产品攒成大产品

 

 

结构型模式

适配器模式

 

 

内容:将一个类的接口转换成客户但愿的另外一个接口。适配器模式使得本来因为接口不兼容二不能一块儿工做的那些类能够一块儿工做。
角色:
  一、目标接口
  二、带适配的类
  三、适配器
两种实现方式:
类适配器:多继承
对象适配器:组合
适用场景
  一、想使用一个已经存在的类,而它的接口不符合你的要求
  二、(对象适配器)想使用一些已经存在的子类,但不能对每个都进行子类化以匹配它们的接口。对象适配器能够适配它的父亲接口。

 代码:

from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass


class Alipay(Payment):
    def pay(self, money):
        print('支付宝支付%s元' % money)


class Applepay(Payment):
    def pay(self, money):
        print('苹果支付%s元' % money)


# ************************* 新人代码 ******************************


class WeiXinZhiFu:
    def fuqian(self, money):
        print('微信支付%s元' % money)


class WangYinZhiFu:
    def fuqian(self, money):
        print('网银支付%s元' % money)


# 类适配器写法, 用继承
class WechatPay(Payment, WeiXinZhiFu):
    def pay(self, money):
        self.fuqian(money)


# 对象适配器  组合
class PayAdapter(Payment):
    def __init__(self, payment):
        self.payment = payment

    def pay(self, money):
        if hasattr(self, "pay"):
            return self.payment.pay(money)
        else:
            return self.payment.fuqian(money)


# paym = WechatPay()
# paym.pay(1000)

paym = PayAdapter(WangYinZhiFu())
paym.pay(1000)

 

 

组合模式

 

内容:将对象组合成树形结构以表示“部分-总体”的层次结构。组合模式使得用户对单个对象和最合对象的使用具备一致性。
角色:
  一、抽象组件
  二、叶子组件
  三、复合组件
  四、客户端
适用场景:
  一、表示对象的“部分-总体”层次结构(特别是结构是递归的)
  二、但愿用户忽略组合对象与单个对象的不一样,用户赞成地使用组合结构中的对象
优势:
  一、定义了包含基本对象和组合对象的类层次结构
  二、简化客户端代码,即客户端能够一致地使用组合对象和单个对象
  三、更容易增长新类型的组件
缺点:
  一、很难限制组合中的组件

代码:

from abc import abstractmethod, ABCMeta


class Graphic(metaclass=ABCMeta):

    @abstractmethod
    def draw(self):
        pass

    @abstractmethod
    def add(self):
        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 __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-----')


# p1 = Point(1, 2)
# p2 = Point(3, 4)
# l = Line(p1, p2)
# print(l)

pic1 = Picture()
pic1.add(Point(1, 4))
pic1.add(Line(Point(1, 2), Point(3, 2)))
pic1.add(Line(Point(7, 8), Point(9, 4)))

pic2 = Picture()
pic2.add(Point(-1, -1))
pic2.add(Line(Point(-1, -2), Point(3, 2)))

pic = Picture()
pic.add(pic1)
pic.add(pic2)

pic.draw()

 

装饰模式

意图: 
动态地给一个对象添加一些额外的职责。就增长功能来讲,Decorator 模式相比生成子类更为灵活。 
适用性:

 在不影响其余对象的状况下,以动态、透明的方式给单个对象添加职责。

 处理那些能够撤消的职责。

当不能采用生成子类的方法进行扩充时。一种状况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增加。另外一种状况多是由于类定义被隐藏,或类定义不能用于生成子类。

#!/usr/bin/python
#coding:utf8
'''
Decorator
'''
 
class foo(object):
    def f1(self):
        print("original f1")
 
    def f2(self):
        print("original f2")
 
 
class foo_decorator(object):
    def __init__(self, decoratee):
        self._decoratee = decoratee
 
    def f1(self):
        print("decorated f1")
        self._decoratee.f1()
 
    def __getattr__(self, name):
        return getattr(self._decoratee, name)
 
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()

 

 

 

 

代理模式

 


内容:为其余对象提供一种代理以控制对这个对象的访问
角色:
  一、抽象实体
  二、实体
  三、代理
适用场景:
  一、远程代理:为远程的对象提供代理
  二、虚代理:根据须要建立很大的对象
  三、保护代理:控制对原始对象的访问,用于对象有不一样访问权限时
优势:
  一、远程代理:能够隐藏对象位于远程地址空间的事实
  二、虚代理:能够进行优化,例如根据要求建立对象
  三、保护代理:容许在访问一个对象时有一些附加的内务处理

from abc import ABCMeta, abstractmethod


class Subject(metaclass=ABCMeta):
    @abstractmethod
    def get_content(self):
        pass


class RealSubject(Subject):
    def __init__(self, filename):
        print('读取%s文件内容' % filename)
        f = open(filename)
        self.content = f.read()
        f.close()

    def get_content(self):
        return self.content


class ProxyA(Subject):
    def __init__(self, filename):  # 实例化的时候进行建立
        self.subj = RealSubject(filename)  # 处理结果存在content里面

    def get_content(self):  # get_content只是获取最终结果
        return self.subj.get_content()


# ************************** 虚代理 ****************************

class ProxyB(Subject):
    def __init__(self, filename):  # 实例化的时候只是保存文件名
        self.filename = filename
        self.subj = None

    def get_content(self):  # 调用get_content的时候再执行处理
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.get_content()


# ************************* 保护代理 ****************************
class ProxyC(Subject):
    def __init__(self, filename):
        self.subj = RealSubject(filename)

    def get_content(self):
        return '????'


filename = 'abc.txt'
username = input('>>>>:')
if username != 'alex':
    p = ProxyC(filename)
else:
    p = ProxyA(filename)

p.get_content()

 

 

行为型模式

责任链模式

 


内容:是多个对象都有机会处理请求,从而避免请求的发送和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
角色:
  一、抽象处理者
  二、具体处理者
  三、客户端
例:
  一、请假部门批准:lead ==》 部门经理 ==〉 总经理
  二、javascript事件浮升机制

代码:

from abc import ABCMeta, abstractmethod


class Handler(metaclass=ABCMeta):
    @abstractmethod
    def handle_leave(self, day):
        pass


class GeneralManagerHandler(Handler):
    def handle_leave(self, day):
        if day < 10:
            print('总经理批准%d天假' % day)
        else:
            print('呵呵')


class DepartmentManagerHandler(Handler):
    def __init__(self):
        self.successor = GeneralManagerHandler()

    def handle_leave(self, day):
        if day < 7:
            print('部门经理批准%d天假' % day)
        else:
            print('部门经理无权准假')
            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)
        else:
            print('项目主管无权准假')
            self.successor.handle_leave(day)


day = 10
h = ProjectDirectorHandler()
h.handle_leave(day)

还有个高端点的实例:

# ******************* 高级点的例子--模仿js时间处理 ***************************
class Handler(metaclass=ABCMeta):
    @abstractmethod
    def add_event(self):
        pass

    @abstractmethod
    def handle(self):
        pass


class BodyHandler(Handler):
    def __init__(self):
        self.func = None

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            print('已经上浮到最上面一层元素,没法处理')


class ElementHandler(Handler):
    def __init__(self, successor):
        self.func = None
        self.successor = successor

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            return self.successor.handle()


body = {
    'type': 'body',
    'name': 'body',
    'children': [],
    'father': None
}
div = {
    'type': 'div',
    'name': 'div',
    'children': [],
    'father': body
}
a = {
    'type': 'a',
    'name': 'a',
    'children': [],
    'father': div
}
body['children'].append(div)
div['children'].append(a)

body['event_handler'] = BodyHandler()
div['event_handler'] = ElementHandler(div['father']['event_handler'])
a['event_handler'] = ElementHandler(a['father']['event_handler'])


def attach_event(element, func):
    element['event_handler'].add_event(func)


def func_div():
    print('这是给div的函数')


def func_a():
    print('这是给a的函数')


def func_body():
    print('这是给body的函数')


attach_event(div, func_div)
attach_event(a, func_a)
attach_event(body, func_body)

div['event_handler'].handle()

 

观察者模式

 


内容:定义对象见的一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖于它的对象都获得通知并被自动更新。观察者模式又称为“发布-订阅”模式
角色:
  一、抽象主题
  二、具体主题 -- 发布者
  三、抽象观察者
  三、具体观察者 -- 订阅者
适用场景:
  一、当一个抽象模型有两方面,其中一个方面依赖于另外一个方面。将这二者封装在独立对象中以使它们能够各自独立地改变和复用。
  二、当对一个对象的改变须要同时改变其余对象,而不知道具体有多少对象有待改变。
  三、当一个对象必须通知其余对象,而它又不能假定其余对象是谁。换言之,你不但愿这些对象是紧密耦合的。
优势:
  一、目标和观察者之间的抽象耦合最少
  二、支持广播通讯
缺点:
  一、多个观察者之间互不知道对方存在,所以一个观察者对主题的修改可能照成错误的更新。

代码:

'''
Observer
'''
 
 
class Subject(object):
    def __init__(self):
        self._observers = []
 
    def attach(self, observer):
        if not observer in self._observers:
            self._observers.append(observer)
 
    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass
 
    def notify(self, modifier=None):
        for observer in self._observers:
            if modifier != observer:
                observer.update(self)
 
# Example usage
class Data(Subject):
    def __init__(self, name=''):
        Subject.__init__(self)
        self.name = name
        self._data = 0
 
    @property
    def data(self):
        return self._data
 
    @data.setter
    def data(self, value):
        self._data = value
        self.notify()
 
class HexViewer:
    def update(self, subject):
        print('HexViewer: Subject %s has data 0x%x' %
              (subject.name, subject.data))
 
class DecimalViewer:
    def update(self, subject):
        print('DecimalViewer: Subject %s has data %d' %
              (subject.name, subject.data))
 
# Example usage...
def main():
    data1 = Data('Data 1')
    data2 = Data('Data 2')
    view1 = DecimalViewer()
    view2 = HexViewer()
    data1.attach(view1)
    data1.attach(view2)
    data2.attach(view2)
    data2.attach(view1)
 
    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15
    print("Setting Data 1 = 3")
    data1.data = 3
    print("Setting Data 2 = 5")
    data2.data = 5
    print("Detach HexViewer from data1 and data2.")
    data1.detach(view2)
    data2.detach(view2)
    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15
 
if __name__ == '__main__':
    main()

 

策略模式

 

内容:定义一系列的算法,把他们一个个封装起来,而且使它们能够相互替换。本模式使得算法可独立于使用它的客户而变化。
角色:
  一、抽象策略
  二、具体策略
  三、上下文
适用场景:
  一、许多相关的类仅仅是行为有异
  二、须要使用一个算法的不一样变体
  三、算法使用了客户端无需知道的数据
  四、一个类中的多种行为以多个条件语句的形式存在,能够将这些行为封装在不一样的策略中。
优势:
  一、定义了一系列可重用的算法和行为
  二、消除了一些条件语句
  三、能够提供相同行为的不一样实现
缺点:
  一、客户必须了解不一样的策略
  二、策略与上下文之间的通讯开销
  三、增长了对象的数目

代码:

from abc import ABCMeta, abstractmethod
import random


class Sort(metaclass=ABCMeta):
    @abstractmethod
    def sort(self, data):
        pass


class 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(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
        # print(ltmp)
        data[low: high + 1] = ltmp

    def mergesort(self, data, low, high):
        if low < high:
            mid = (low + high) // 2
            self.mergesort(data, low, mid)
            self.mergesort(data, mid + 1, high)
            self.merge(data, low, mid, high)

    def sort(self, data):
        print('归并排序')
        return self.mergesort(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 TypeError


li = list(range(10000))
random.shuffle(li)
context = Context(li, MergeSort())
context.do_strategy()

random.shuffle(context.data)

context.set_strategy(QuickSort())
context.do_strategy()

 


模版方法模式

 


内容:定义一个操做中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。
角色:
  一、抽象类:定义抽象的原子操做;实现一个模版方法做为算法骨架
  二、具体类:实现原子操做
适用场景:
  一、一次性实现一个算法的不变的部分
  二、各个子类中的公共行为应该被提取出来并集中到一个公共服类中,避免代码重复
  三、控制子类扩展

代码:

from abc import ABCMeta, abstractmethod


class 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')

 

大概就抽取一些重要的介绍,具体的能够上网找找blog看看

好比:https://www.cnblogs.com/Liqiongyu/p/5916710.html

或者大王的:https://www.cnblogs.com/alex3714/articles/5760582.html

相关文章
相关标签/搜索