设计模式从大的分类上可以分为 创建型设计模式、结构型设计模式、行为模式

Python是一门动态到骨子里的编程语言,它有着一等函数对象、“鸭子类型”、可自定义的数据模型等各种灵活特性。因此,我们极少会用Python来一比一还原经典设计模式,而几乎总是会为每种设计模式找到更适合Python的表现形式。

设计模式 6 大原则

  • SOLID 原则(前五个可以成为 SOLID 原则)

单一职责原则Single Responsibility Principle

定义:一个类或者一个接口,最好只负责一项职责。

问题由来:类T负责两个不同的职责P1和P2。由于职责P1需要发生改变而需要修改T类时,有可能导致原来运行正常的职责P2功能发生故障。

解决方法:遵循单一职责原则。分别建立两个类T1和T2,使类T1负责职责P1,类T2负责职责P2。这样,当修改类T1也不会影响职责P2;同理,当修改类T2时不会影响职责P1。

开闭原则Open Close Principle

定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

里氏替换原则Liskov Substitution Principle

定义:所有引用基类的地方必须能透明地使用其子类的对象。

问题由来:有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。

解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。

继承包含这样一层含义:父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。

继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。

接口隔离原则Interface Segregation Principle

定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 否则将会造成接口污染。类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。

解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。

依赖倒置原则Dependence Inversion Principle

定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。其核心思想是:依赖于抽象。

问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。

解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

迪米特法则Demeter Principle

定义:一个对象应该对其他对象保持最少的了解。其核心精神是:不和陌生人说话,通俗之意是一个对象对自己需要耦合关联调用的类应该知道的更少。这样会导致类之间的耦合度降低,每个类都尽量减少对其他类的依赖,因此,这也很容易使得系统的功能模块相互独立,之间不存在很强的依赖关系。

问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。

解决方案:尽量降低类与类之间的耦合。

合成复用原则Composite Reuse Principle

原则是尽量使用合成/聚合的方式,而不是使用继承。

单例模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 1:单例模式

class AppConfig:

    _instance = None

    def __new__(cls):
        if cls._instance is None:
            inst = super().__new__(cls)
            cls._instance = inst
        return cls._instance

# 2:全局对象

class AppConfig:
    ...

_config = AppConfig()

一个模块级的全局对象用更少的代码满足了同样的需求。

方法 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 方法1,实现__new__方法
# 并在将一个类的实例绑定到类变量_instance上,
# 如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
# 如果cls._instance不为None,直接返回cls._instance
class Singleton(object):
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance


class MyClass(Singleton):
    a = 1


one = MyClass()
two = MyClass()

two.a = 3
print one.a
# 3
# one和two完全相同,可以用id(), ==, is检测
print id(one)
# 29097904
print id(two)
# 29097904
print one == two
# True
print one is two
# True

方法 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 方法2,共享属性;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)
# 同一个类的所有实例天然拥有相同的行为(方法),
# 只需要保证同一个类的所有实例具有相同的状态(属性)即可
# 所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict)
# 可参看:http://code.activestate.com/recipes/66531/
class Borg(object):
    _state = {}

    def __new__(cls, *args, **kw):
        ob = super(Borg, cls).__new__(cls, *args, **kw)
        ob.__dict__ = cls._state
        return ob


class MyClass2(Borg):
    a = 1


one = MyClass2()
two = MyClass2()

# one和two是两个不同的对象,id, ==, is对比结果可看出
two.a = 3
print one.a
# 3
print id(one)
# 28873680
print id(two)
# 28873712
print one == two
# False
print one is two
# False
# 但是one和two具有相同的(同一个__dict__属性),见:
print id(one.__dict__)
# 30104000
print id(two.__dict__)
# 30104000

就是 https://github.com/faif/python-patterns/blob/master/patterns/creational/borg.py 另外一种实现。

方法 3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 方法3:本质上是方法1的升级(或者说高级)版
# 使用__metaclass__(元类)的高级python用法
class Singleton2(type):
    def __init__(cls, name, bases, dict):
        super(Singleton2, cls).__init__(name, bases, dict)
        cls._instance = None

    def __call__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = super(Singleton2, cls).__call__(*args, **kw)
        return cls._instance


class MyClass3(object):
    __metaclass__ = Singleton2


one = MyClass3()
two = MyClass3()

two.a = 3
print one.a
# 3
print id(one)
# 31495472
print id(two)
# 31495472
print one == two
# True
print one is two
# True

方法 4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 方法4:也是方法1的升级(高级)版本,
# 使用装饰器(decorator),
# 这是一种更pythonic,更elegant的方法,
# 单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的
def singleton(cls, *args, **kw):
    instances = {}

    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return _singleton


@singleton
class MyClass4(object):
    a = 1

    def __init__(self, x=0):
        self.x = x


one = MyClass4()
two = MyClass4()

two.a = 3
print one.a
# 3
print id(one)
# 29660784
print id(two)
# 29660784
print one == two
# True
print one is two
# True
one.x = 1
print one.x
# 1
print two.x
# 1

单例模式与 borg 的区别

  • 如果是需要保证只有一个实例,那就选择单例模式
  • Borg 允许多个实例被创建,但所有的实例都共享状态和行为方式。通过这种“数据重载”实现。

工厂模式(解决对象创建的问题)

处理对象创建、实例化延迟到子类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Dog:
    def speak(self):
        print("wang wang")

class Cat:
    def speak(self):
        print("miao miao")

def animal_factory(name):
    if name == 'dog':
        return Dog()
    elif name == 'cat':
        return Cat()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
"""
工厂模式:实例化延迟到子类
缺点是使用类作为代价,且factory修改不封闭,每增加product就要修改
但可以使用配置文件,就可以封闭了
"""
class Product_opt:
    def getResult(self):
        pass
class Product_add(Product_opt):
    def getResult(self):
        return self.num1+self.num2
class Product_sub(Product_opt):
    def getResult(self):
        return self.num1-self.num2
class Product_err(Product_opt):
    def getResult(self):
        print "error"
        return 0
class Factory:
    operation={}
    operation["+"]=Product_add()
    operation["-"]=Product_sub()
    def createproduct(self,ch):
        if ch in self.operation:
            op = self.operation[ch]
        else:
            op = Product_err()
        return op
if __name__=="__main__":
    num1=input("a:")
    op=raw_input("operation:")
    num2=input("b:")
    factory=Factory()
    product=factory.createproduct(op)
    product.num1=num1
    product.num2=num2
    print product.getResult()

工厂方法适合对象种类较少的情况,如果有多种不同类型对象需要创建,使用抽象工厂模式。

抽象工厂

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 理解
# Abstract_Factory模式是Factory的扩展,
# Factory用于生产一类产品而抽象工厂用于生产多个产品系列
"""
创建型设计模式
"""
""" 例子:
# 两个工厂,一个生产狗玩具,一个生产猫玩具,而玩具共有两类一类机器玩具,一类毛绒玩具
"""
class Abstract_Factory:
    def __init__(self, factory=None):
        self.toy_factory = factory


class cat_Factory(Abstract_Factory):
    # 当然这里可以象Factory_Method使用查表
    def create_soft_cat(self):
        return soft_cat_toy();

    def create_machine_cat(self):
        return machine_cat_toy()


class dog_Factory(Abstract_Factory):
    def create_soft_dog(self):
        return soft_dog_toy();

    def create_machine_dog(self):
        return machine_dog_toy();


class Abstract_Product_dog:
    def getname(self):
        pass

    def speak(self):
        print "wangwang"


class soft_dog_toy(Abstract_Product_dog):
    def getname(self):
        return "soft dog toy"


class machine_dog_toy(Abstract_Product_dog):
    def getname(self):
        return "machine dog toy"


class Abstract_Product_cat:
    def getname(self):
        pass

    def speak(self):
        print "miaomiao"


class soft_cat_toy(Abstract_Product_cat):
    def getname(self):
        return "soft cat toy"


class machine_cat_toy(Abstract_Product_cat):
    def getname(self):
        return "machine cat toy"


if __name__ == "__main__":
    factory = Abstract_Factory(dog_Factory());
    dog1 = factory.toy_factory.create_soft_dog()
    dog1.speak()
    print dog1.getname()
    dog2 = factory.toy_factory.create_machine_dog()
    dog2.speak()
    print dog2.getname()
    factory = Abstract_Factory(cat_Factory())
    cat1 = factory.toy_factory.create_soft_cat()
    cat1.speak()
    print cat1.getname()
    cat2 = factory.toy_factory.create_machine_cat()
    cat2.speak()
    print cat2.getname()

构造模式(控制复杂对象的构造)

当对象需要多个部分组合起来一步步创建,并且创建和表示分离的时候。可以这么理解,你要买电脑,工厂模式直接返回一个你需要型号的电脑,但是构造模式允许你自定义电脑各种配置类型,组装完成后给你。这个过程你可以传入builder从而自定义创建的方式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# builder模式


class Computer:
    def __init__(self, serial_number):
        self.serial = serial_number
        self.memory = None      # in gigabytes
        self.hdd = None         # in gigabytes
        self.gpu = None

    def __str__(self):
        info = ('Memory: {}GB'.format(self.memory),
                'Hard Disk: {}GB'.format(self.hdd),
                'Graphics Card: {}'.format(self.gpu))
        return '\n'.join(info)


class ComputerBuilder:
    def __init__(self):
        self.computer = Computer('AG23385193')

    def configure_memory(self, amount):
        self.computer.memory = amount

    def configure_hdd(self, amount):
        self.computer.hdd = amount

    def configure_gpu(self, gpu_model):
        self.computer.gpu = gpu_model


class HardwareEngineer:
    def __init__(self):
        self.builder = None

    def construct_computer(self, memory, hdd, gpu):
        self.builder = ComputerBuilder()
        [step for step in (self.builder.configure_memory(memory),
                        self.builder.configure_hdd(hdd),
                        self.builder.configure_gpu(gpu))]

    @property
    def computer(self):
        return self.builder.computer

# 使用buidler,可以创建多个builder类实现不同的组装方式
engineer = HardwareEngineer()
engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti')
computer = engineer.computer
print(computer)

原型模式(解决对象拷贝问题)

原型与工厂模式的区别应该是少一个与与产品平行的工厂类,通过克隆自己,可以创造多个对象。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#例子
#有一个哺乳动物的原型,每个动物有名称,
#人有很多,所以有很多Object,我们通过clone得到人的对象,然后在附上不同属性
#猴子也有很多,我们也可以通过clone得到多个猴子
class Prototype(object):
    typename='mammalian'
    def __init__(self):
        pass
    def clone(self):
        pass
class Person(Prototype):
    def __init__(self):
        self.hair='black'
        self.Name='Person'
        Prototype.__init__(self)#调用父类初始化函数的一种方法
    def clone(self):
        return Person()
class Monkey(Prototype):
    def __init__(self):
        self.hair='red'
        self.Name='monkey'
        super(Prototype,self).__init__()#调用父类初始化的另一种方法
    def clone(self):
        return Monkey()
#client
if __name__=="__main__":
    p=Person()
    p1=p.clone()
    print p
    print p.typename,p.hair,p.Name
    print p1
    print p1.typename,p1.hair,p.Name
    Monkey=monkey()
    Monkey1=Monkey.clone()
    print Monkey
    print Monkey.typename,Monkey.hair,Monkey.Name
    print Monkey1
    print Monkey.typename,Monkey1.hair,Monkey.Name

适配器模式(解决接口不兼容问题)

结构型设计模式通过组合对象来实现新功能。

适配器模式通过引入间接层来实现不兼容接口之间的适配。现实中最好的例子就是手机充电口,不同型号安卓手机都可以用同样的充电线充电。在python中可以通过继承实现适配,也可以通过使用class的__dict__属性。 开闭原则:适配器模式和OOP中的开闭原则关系密切,开闭原则强调对扩展开放,对修改关闭。通过适配器模式我们可以通过创建适配器模式在不修改原有类代码的情况下实现新的功能。

当我们需要给不同的对象统一接口的时候可以使用适配器模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Dog:
    def __init__(self):
        self.name = "Dog"

    def bark(self):
        return "woof!"

class Cat:
    def __init__(self):
        self.name = "Cat"

    def meow(self):
        return "meow!"

class Adapter:
    def __init__(self, obj, **adapted_methods):
        """适配器类接收适配器方法"""
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, item):
        return getattr(self.obj, item)

objects = []
dog = Dog()
objects.append(Adapter(dog, make_noise=dog.bark))
cat = Cat()
objects.append(Adapter(cat, make_noise=cat.meow))
for obj in objects:
    print("a {} goes {}".format(obj.name, obj.make_noise()))

装饰器模式(无需子类化实现扩展对象功能)

通常给一个对象添加新功能有三种方式:

  • 直接给对象所属的类添加方法。
  • 使用『组合』
  • 使用『继承』,优先使用组合而非继承。

装饰器模式提供了第四种选择,通过动态改变对象扩展对象功能。其他编程语言通常使用继承实现装饰器装饰器模式,而python内置了装饰器。装饰器有很多用途,比如数据校验,事务处理,缓存,日志等。比如用装饰器实现一个简单的缓存,Python 自带了functools.lru_cache。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

def log_time(func):  # 接受一个函数作为参数
    def _log(*args, **kwargs):
        beg = time.time()
        res = func(*args, **kwargs)
        print('use time: {}'.format(time.time() - beg))
        return res

    return _log

@log_time  # 装饰器语法糖
def mysleep():
    time.sleep(1)

mysleep()

# 另一种写法,和上面的调用方式等价
def mysleep2():
    time.sleep(1)

newsleep = log_time(mysleep2)
newsleep()

代理模式 (通过一层间接保护层实现更安全的接口访问)

访问真正的对象之前做一些操作。有四种常用的代理类型:

  • A remote proxy.使得访问远程对象就像本地访问一样,例如网络服务器。隐藏复杂性,使得访问本地远程统一。比如ORM
  • A virtual proxy。用来实现延迟访问,比如一些需要复杂计算的对象,python里可以实现lazy_property,性能改善
  • A protection/protective proxy. 控制敏感对象的访问,加上一层保护层,实现安全控制
  • A smart(reference) proxy. 访问对象时加上一层额外操作,例如引用计数和线程安全检查。weakref.proxy()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class AbstractSubject:
    def resquest(self):
        pass
        # Realsubject


class RealSubject(AbstractSubject):
    def request(self):
        print "i'm working"
        # Proxy


class Proxy(AbstractSubject):
    def __init__(self, subject):
        self.subject = subject

    def request(self, ip):
        if ip == '1':
            self.subject.request()
        else:
            print 'you ip isnot right'
            # client


if __name__ == "__main__":
    sub = RealSubject()
    proxy = Proxy(sub)
    proxy.request('')
    proxy.request('1')  

外观模式(外观模式: 简化复杂对象的访问问题)

外观模式用来简化复杂系统的访问。通过简化的接口只访问需要的部分,隐藏系统复杂性。想象一下公司接线员,虽然公司内部运行机制比较复杂,但是接线员可以迅速帮你解决特定问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from abc import ABCMeta, abstractmethod
from enum import Enum

State = Enum('State', 'new running sleeping restart zombie')


class Server(metaclass=ABCMeta):
    """ 抽象基类 """
    @abstractmethod
    def __init__(self):
        pass

    def __str__(self):
        return self.name

    @abstractmethod
    def boot(self):
        pass

    @abstractmethod
    def kill(self, restart=True):
        pass


class FileServer(Server):
    def __init__(self):
        '''actions required for initializing the file server'''
        self.name = 'FileServer'
        self.state = State.new

    def boot(self):
        print('booting the {}'.format(self))
        '''actions required for booting the file server'''
        self.state = State.running

    def kill(self, restart=True):
        print('Killing {}'.format(self))
        '''actions required for killing the file server'''
        self.state = State.restart if restart else State.zombie

    def create_file(self, user, name, permissions):
        '''check validity of permissions, user rights, etc.'''
        print("trying to create the file '{}' for user '{}' with permissions {}".format(name, user, permissions))

class ProcessServer(Server):
    def __init__(self):
        '''actions required for initializing the process server'''
        self.name = 'ProcessServer'
        self.state = State.new

    def boot(self):
        print('booting the {}'.format(self))
        '''actions required for booting the process server'''
        self.state = State.running

    def kill(self, restart=True):
        print('Killing {}'.format(self))
        '''actions required for killing the process server'''
        self.state = State.restart if restart else State.zombie

    def create_process(self, user, name):
        '''check user rights, generate PID, etc.'''
        print("trying to create the process '{}' for user '{}'".format(name, user))


class OperatingSystem:
    ''' 实现外观模式,外部使用的代码不必知道 FileServer 和 ProcessServer的
    内部机制,只需要通过 OperatingSystem类调用'''
    def __init__(self):
        self.fs = FileServer()
        self.ps = ProcessServer()

    def start(self):
        """ 被客户端代码使用 """
        [i.boot() for i in (self.fs, self.ps)]

    def create_file(self, user, name, permissions):
        return self.fs.create_file(user, name, permissions)

    def create_process(self, user, name):
        return self.ps.create_process(user, name)

def main():
    os = OperatingSystem()
    os.start()
    os.create_file('foo', 'hello', '-rw-r-r')
    os.create_process('bar', 'ls /tmp')

main()

享元模式(实现对象复用从而改善资源使用)

运用共享技术,减少大量细粒度对象对存储的开销

迭代器模式

  • python内置对迭代器模式的支持
  • 比如我们可以用for遍历各种Interable的数据类型
  • python里可以实现__next__和__iter__实现迭代器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class NumberWords:
    """Counts by word numbers, up to a maximum of five"""

    _WORD_MAP = (
        "one",
        "two",
        "three",
        "four",
        "five",
    )

    def __init__(self, start, stop):
        self.start = start
        self.stop = stop

    def __iter__(self):  # this makes the class an Iterable
        return self

    def __next__(self):  # this makes the class an Iterator
        if self.start > self.stop or self.start > len(self._WORD_MAP):
            raise StopIteration
        current = self.start
        self.start += 1
        return self._WORD_MAP[current - 1]


for number in NumberWords(start=1, stop=2):
    print(number)

观察者模式

  • 发布订阅是一种罪常用的实现方式
  • 发布订阅用于解耦逻辑
  • 可以通过回调等方式实现,当发生事件时,调用相应的回调函数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Publisher:
    def __init__(self):
        self.observers = []

    def add(self, observer):
        if observer not in self.observers:
            self.observers.append(observer)
        else:
            print('Failed to add observer')

    def remove(self, observer):
        try:
            self.observers.remove(observer)
        except ValueError:
            print('Failed to remove observer')

    def notify(self):
        [o.notify_by(self) for o in self.observers]


class Formatter(Publisher):
    def __init__(self, name):
        super().__init__()
        self.name = name
        self._data = 0

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, new_value):
        self._data = int(new_value)
        self.notify()


class BinaryFormatter:
    def notify_by(self, publisher):
        print(f'{type(self).__name__}:{publisher.name} has new bin data bin data = {bin(publisher.data)}')


df = Formatter('formatter')

bf1 = BinaryFormatter()
bf2 = BinaryFormatter()
df.add(bf1)
df.add(bf2)
print(df.observers)
df.data = 3

策略模式

  • 根据不同的输入采取不同的策略
  • 比如买东西超过10个打八折,超过20个打7折
  • 对外暴露统一的接口,内部采用不同的策略计算
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Order:
    def __init__(self, price, discount_strategy=None):
        self.price = price
        self.discount_strategy = discount_strategy

    def price_after_discount(self):
        if self.discount_strategy:
            discount = self.discount_strategy(self)
        else:
            discount = 0
        return self.price - discount

    def __repr__(self):
        return "Price: {}, price after discount: {}".format(self.price, self.price_after_discount())

def ten_percent_discount(order):
    return order.price * 0.10


def on_sale_discount(order):
    return order.price * 0.25 + 20


order0 = Order(100)
order1 = Order(100, discount_strategy=ten_percent_discount)
order2 = Order(1000, discount_strategy=on_sale_discount)
print(order0)
print(order1)
print(order2)

参考