共计 15837 个字符,预计需要花费 40 分钟才能阅读完成。
一. 创立模式
1. 简略工厂模式:
定义:
不间接向客户端裸露对象创立的实现细节,而是通过一个工厂类来负责创立产品类的实例。
应用场景:
无
长处:
- 暗藏了对象创立的实现细节
- 客户端不须要批改代码
毛病:
- 违反了繁多职责准则,将创立逻辑几种到一个工厂类里
- 当增加新产品时,须要批改工厂类代码,违反了开闭准则
from abc import abstractmethod, ABCMeta
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class 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, 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 PaymentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
class 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):
pass
class CPU(metaclass=ABCMeta):
@abstractmethod
def show_cpu(self):
pass
class 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):
pass
class 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.player
class 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._instance
class MyClass(Singleton):
a = 1
def __init__(self, name):
self.name = name
one = 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
@singleton
class MyClass2:
a = 1
one = MyClass2()
two = MyClass2()
print(id(one)) # 31495472
print(id(two)) # 31495472
print(one == two)
print(one is two)
# Python 的模块是人造的单例模式。# module_name.py
class MySingleton(object):
def foo(self):
print('danli')
my_singleton = MySingleton()
# to use
from .module_name import my_singleton
my_singleton.foo()
print(id(my_singleton))
from .module_name import my_singleton
my_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
# Python3
class MyClass(metaclass=Singleton):
pass
one = MyClass()
two = MyClass()
print(id(one))
print(id(two))
print(one == two)
print(one is two)
6. 原型模式:
定义:
用原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象。
实用场景:
- 通过动静装载;
- 为了防止创立一个与产品类档次平行的工厂类档次时;
- 当一个类的实例只能有几个不同状态组合中的一种时。建设相应数目的原型并克隆它们可能比每次用适合的状态手工实例化该类更不便一些。
import copy
class 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 obj
def 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, ABCMeta
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
raise NotImplementedError
class 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, ABCMeta
class 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, abstractmethod
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self):
pass
def set_content(self, content):
pass
class 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, 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)
return True
else:
print("呵呵")
return False
class 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 = 11
h = 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, abstractmethod
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, notice):
pass
class 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_info
notice = 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, 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(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 TypeError
li = 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, 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")
正文完