设计模式是通过总结、优化的,对咱们常常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样可以直接做用于咱们的代码。反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言。一个好的设计模式应该可以用大部分编程语言实现(若是作不到所有的话,具体取决于语言特性)。最为重要的是,设计模式也是一把双刃剑,若是设计模式被用在不恰当的情形下将会形成灾难,进而带来无穷的麻烦。然而若是设计模式在正确的时间被用在正确地地方,它将是你的救星。node
起初,你会认为“模式”就是为了解决一类特定问题而特别想出来的明智之举。说的没错,看起来的确是经过不少人一块儿工做,从不一样的角度看待问题进而造成的一个最通用、最灵活的解决方案。也许这些问题你曾经见过或是曾经解决过,可是你的解决方案极可能没有模式这么完备。python
虽然被称为“设计模式”,可是它们同“设计“领域并不是紧密联系。设计模式同传统意义上的分析、设计与实现不一样,事实上设计模式将一个完整的理念根植于程序中,因此它可能出如今分析阶段或是更高层的设计阶段。颇有趣的是由于设计模式的具体体现是程序代码,所以可能会让你认为它不会在具体实现阶段以前出现(事实上在进入具体实现阶段以前你都没有意识到正在使用具体的设计模式)。算法
能够经过程序设计的基本概念来理解模式:增长一个抽象层。抽象一个事物就是隔离任何具体细节,这么作的目的是为了将那些不变的核心部分从其余细节中分离出来。当你发现你程序中的某些部分常常由于某些缘由改动,而你不想让这些改动的部分引起其余部分的改动,这时候你就须要思考那些不会变更的设计方法了。这么作不只会使代码可维护性更高,并且会让代码更易于理解,从而下降开发成本。shell
设计模式的定义:为了解决面向对象系统中重要和重复的设计封装在一块儿的一种代码实现框架,可使得代码更加易于扩展和调用编程
四个基本要素:模式名称,问题,解决方案,效果设计模式
定义:一种特殊的类,声明了若干方法,要求继承该接口的类必须实现这种方法微信
做用:限制继承接口的类的方法的名称及调用方式,隐藏了类的内部实现app
from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod # 定义抽象方法的关键字 def pay(self, money): pass # @abstractmethod # def pay(self,money): # raise NotImplementedError class AiliPay(Payment): # 子类继承接口,必须实现接口中定义的抽象方法,不然不能实例化对象 def pay(self, money): print('使用支付宝支付%s元' % money) class ApplePay(Payment): def pay(self, money): print('使用苹果支付支付%s元' % money)
定义:保证一个类只有一个实例,并提供一个访问它的全局访问点框架
适用场景:当一个类只能有一个实例而客户能够从一个众所周知的访问点访问它时dom
优势:对惟一实例的受控访问,至关于全局变量,可是又能够防止此变量被篡改
*args, **kargs): # if cls not in _instance: # _instance[cls] = cls(*args, **kargs) # return _instance[cls] # # return _singleton # # # @Singleton # class A(object): # a = 1 # # def __init__(self, x=0): # self.x = x # # # a1 = A(2) # a2 = A(3) """方式三:使用类""" # import threading # import time # # # class Singleton(object): # # def __init__(self): # # time.sleep(1) # pass # @classmethod # def instance(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # Singleton._instance = Singleton(*args, **kwargs) # return Singleton._instance # # # def task(arg): # obj = Singleton.instance() # print(obj) # # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() """解决方法:加锁""" # import time # import threading # # # class Singleton(object): # _instance_lock = threading.Lock() # # def __init__(self): # time.sleep(1) # # @classmethod # def instance(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # with Singleton._instance_lock: # if not hasattr(Singleton, "_instance"): # Singleton._instance = Singleton(*args, **kwargs) # return Singleton._instance # # # # # def task(arg): # obj = Singleton.instance() # print(obj) # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() # time.sleep(20) # obj = Singleton.instance() # print(obj) """方法四:基于__new__方法""" # # import threading # # class Singleton(object): # _instance_lock = threading.Lock() # # def __init__(self): # pass # # def __new__(cls, *args, **kwargs): # if not hasattr(Singleton, "_instance"): # with Singleton._instance_lock: # if not hasattr(Singleton, "_instance"): # Singleton._instance = object.__new__(cls) # return Singleton._instance # # # obj1 = Singleton() # obj2 = Singleton() # print(obj1,obj2) # # # def task(arg): # obj = Singleton() # print(obj) # # # for i in range(10): # t = threading.Thread(target=task,args=[i,]) # t.start() # """方法五:元类实现单例模式""" import threading class SingletonType(type): _instance_lock = threading.Lock() def __call__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): with SingletonType._instance_lock: if not hasattr(cls, "_instance"): cls._instance = super(SingletonType,cls).__call__(*args, **kwargs) return cls._instance class Foo(metaclass=SingletonType): def __init__(self,name): self.name = name obj1 = Foo('name') obj2 = Foo('name') print(obj1,obj2)
定义:不直接向客户暴露对象建立的实现细节,而是经过一个工厂类来负责建立产品类的实例
角色:工厂角色,抽象产品角色,具体产品角色
优势:隐藏了对象建立代码的细节,客户端不须要修改代码
缺点:违反了单一职责原则,将建立逻辑集中到一个工厂里面,当要添加新产品时,违背了开闭原则
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): """ 抽象产品角色 """ @abstractmethod def pay(self, money): pass class AiliPay(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(object): """ 工厂角色 """ @staticmethod def create_payment(method): if method == 'alipay': return AiliPay() elif method == 'yuebao': return AiliPay(True) elif method == 'applepay': return ApplePay() else: return NameError p = PaymentFactory() f = p.create_payment('yuebao') f.pay(100)
定义:定义一个建立对象的接口(工厂接口),让子类决定实例化哪一个接口
角色:抽象工厂角色,具体工厂角色,抽象产品角色,具体产品角色
适用场景:须要生产多种,大量复杂对象的时候,须要下降代码耦合度的时候,当系统中的产品类常常须要扩展的时候
优势:每一个具体的产品都对应一个具体工厂,不须要修改工厂类的代码,工厂类能够不知道它所建立的具体的类,隐藏了对象建立的实现细节
缺点:每增长一个具体的产品类,就必须增长一个相应的工厂类
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): """ 抽象产品角色 """ @abstractmethod def pay(self, money): pass class AiliPay(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(object): """ 工厂角色 """ @staticmethod def create_payment(method): if method == 'alipay': return AiliPay() elif method == 'yuebao': return AiliPay(True) elif method == 'applepay': return ApplePay() else: return NameError p = PaymentFactory() f = p.create_payment('yuebao') f.pay(100) # 若是要新增支付方式 class WechatPay(Payment): def pay(self, money): print('使用微信支付%s元' % money) class WechatPayFactory(PaymentFactory): def create_payment(self): return WechatPay() w = WechatPayFactory() wc = w.create_payment() wc.pay(200)
定义:定义一个工厂类接口,让工厂子类来建立一系列相关或相互依赖的对象
角色:抽象工厂角色,具体工厂角色,抽象产品角色,具体产品角色,客户端
适用场景:系统要独立于产品的建立和组合时,强调一系列相关产品的对象设计以便进行联合调试时,提供一个产品类库,想隐藏产品的具体实现时
优势:将客户端与类的具体实现相分离,每一个工厂建立了一个完整的产品系列,易于交换产品.有利于产品的一致性
缺点:难以支持新种类的产品
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ 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 Andriod(OS): def show_os(self): print('安卓系统') class IOS(OS): def show_os(self): print('iOS系统') # ------具体工厂------ class MiFactory(PhoneFactory): def make_shell(self): return BigShell() def make_os(self): return Andriod() def make_cpu(self): return SnapDragonCPU() class HuaweiFactory(PhoneFactory): def make_shell(self): return SmallShell() def make_os(self): return Andriod() def make_cpu(self): return MediaTekCPU() class AppleFactory(PhoneFactory): def make_shell(self): return AppleShell() def make_os(self): return IOS() def make_cpu(self): return AppleCPU() # ------客户端------ class Phone: def __init__(self, shell, os, cpu): self.shell = shell self.os = os self.cpu = cpu def show_info(self): print('手机信息') self.cpu.show_cpu() self.shell.show_shell() self.os.show_os() def make_phone(factory): cpu = factory.make_cpu() os = factory.make_os() shell = factory.make_shell() return Phone(shell, os, cpu) p1 = make_phone(AppleFactory()) p1.show_info()
定义:将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示
角色:抽象建造者,具体建造者,指挥者,产品
适用场景:当建立复杂对象的算法应该独立于对象的组成部分以及它的装配方式,当构造过程容许被构造的对象有不一样的表示
优势:隐藏了一个产品的内部结构和装配过程,将构造代码与表示代码分开,能够对构造过程进行更精确的控制
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ 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.body, self.arm, self.leg) # ------建造者------ class PlayerBuilder(metaclass=ABCMeta): @abstractmethod def build_face(self): pass @abstractmethod def build_body(self): pass @abstractmethod def build_arm(self): pass @abstractmethod def build_leg(self): pass @abstractmethod def get_player(self): pass # ------具体建造者------ class BeautifulWoman(PlayerBuilder): def __init__(self): self.player = Player() def build_face(self): self.player.face = '白脸蛋' def build_body(self): self.player.body = '好身材' def build_arm(self): self.player.arm = '细胳膊' def build_leg(self): self.player.leg = '大长腿' def get_player(self): return self.player # ------指挥者------ class PlayerDirecter(object): @staticmethod def build_player(builder): builder.build_face() builder.build_body() builder.build_arm() builder.build_leg() return builder.get_player() director = PlayerDirecter() builder = BeautifulWoman() p = director.build_player(builder) print(p)
定义:将一个接口转换为客户但愿的另外一个接口,该模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做
角色:目标接口,待适配的类,适配器
适用场景:想使一个已经存在的类,但其接口不符合你的要求.想对一些已经存在的子类.不可能每个都是用子类来进行适配,对象适配器能够适配其父类接口
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ 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 fuqian(self, money): print('微信支付%s元' % money) # ------类适配器------ class RealWeChatPay(Payment, WeChatPay): def pay(self, money): return self.fuqian(money) # -----对象适配器----- class PayAdapter(Payment): def __init__(self, payment): self.payment = payment def pay(self, money): return self.payment.fuqian(money) # RealWeChatPay().pay(100) p = PayAdapter(WeChatPay()) p.pay(200)
定义:将对象组合成树形结构以表示'部分-总体'的层次结构.组合模式使得用户对单个对象和组合对象的使用具备一致性
角色:抽象组件,叶子组件,复合组件,客户端
适用场景:表示对象的'部分-总体'层次结构,但愿用户忽略组合对象与单个对象的不一样,用户统一使用组合结构中的全部对象
优势:定义了包含基本对象和组合对象的类层次结构,简化客户端代码,即客户端能够一致的使用组合对象和单个对象,更容易新增新类型的组件
缺点:很难限制组合中的组件
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import abstractmethod, ABCMeta # -------抽象组件-------- class Graph(metaclass=ABCMeta): @abstractmethod def draw(self): pass @abstractmethod def add(self, graph): pass def get_children(self): pass # ---------叶子组件-------- class Point(Graph): def __init__(self, x, y): self.x = x self.y = y def draw(self): print(self) def add(self, graph): raise TypeError def get_children(self): raise TypeError def __str__(self): return '点(%s,%s)' % (self.x, self.y) class Line(Graph): def __init__(self, p1, p2): self.p1 = p1 self.p2 = p2 def draw(self): print(self) def add(self, graph): raise TypeError def get_children(self): raise TypeError def __str__(self): return '线段(%s,%s)' % (self.p1, self.p2) # --------复合组件--------- class Picture(Graph): def __init__(self): self.children = [] def add(self, graph): self.children.append(graph) def get_children(self): return self.children def draw(self): print('-----复合图形-----') for g in self.children: g.draw() print('结束') # ---------客户端--------- 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()
定义:为其余对象提供一种代理以控制对特定对象的访问
角色:抽象实体,实体,代理
适用场景:远程代理(为远程的对象提供代理),虚代理(根据须要建立很大的对象,即懒加载),保护代理(控制对原始对象的访问,用于具备不一样访问权限的对象)
优势:远程代理(能够隐藏对象位于远程地址空间的事实),虚代理(可对大对象的加载进行优化),保护代理(容许在访问一个对象时有一些附加的处理逻辑,例如权限控制)
-*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ 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) def get_content(self): return self.subj.get_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() # 保护代理 class ProxyC(Subject): def __init__(self, filename): self.subj = RealSubject(filename) def get_content(self): return '???' # 客户端 filename = 'abc.txt' username = input('>>') if username != 'zhangyafei': p = ProxyC(filename) else: p = ProxyB(filename) print(p.get_content())
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖它的对象都会获得通知并被自动更新.观察者模式又称为'发布订阅'模式
角色:抽象主题,具体主题(发布者),抽象观察者,具体观察者(订阅者)
适用场景:当一个抽象模型有两个方面,其中一个方面依赖于另外一个方面.将二者封装在独立的对象中以使它们各自独立的改变和复用
当一个对象的改变须要同时改变其余对象,并且不知道具体有多少对象以待改变
当一个对象必须通知其余对象,而又不知道其余对象是谁,即这些对象之间是解耦的
优势:目标和观察者之间的耦合最小,支持广播通讯
缺点:多个观察者之间互不知道对方的存在,所以一个观察者对主题的修改可能形成错误的更新
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import ABCMeta, abstractmethod # 抽象主题 class Oberserver(metaclass=ABCMeta): @abstractmethod def update(self): pass # 具体主题 class Notice: def __init__(self): self.observers = [] def attach(self, obs): self.observers.append(obs) def detach(self, obs): self.observers.remove(obs) 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 @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(Oberserver): def __init__(self): self.company_info = None def update(self, noti): self.company_info = noti.company_info # 消息订阅-发送 notice = ManagerNotice() alex = Manager() tony = Manager() notice.attach(alex) notice.attach(tony) notice.company_info = "公司运行良好" print(alex.company_info) print(tony.company_info) notice.company_info = "公司将要上市" print(alex.company_info) print(tony.company_info) notice.detach(tony) notice.company_info = "公司要破产了,赶快跑路" print(alex.company_info) print(tony.company_info)
定义:定义一系列的算法把它们一个个封装起来,而且使它们可相互替换.该模式使得算法可独立于使用它的客户而变化
角色:抽象策略,具体策略,上下文
适用场景:许多相关的类仅仅是行为有异,需使用一个算法的不一样变体,算法使用了客户端无需知道的数据,一个类中的多个行为以多个条件语句存在能够将其封装在不一样的策略类中
优势:定义了一系列可重用的算法和行为,消除了一些条件语句,可提供相同行为的不一样实现
缺点:客户必须了解不一样的策略,策略与上下文之间的通讯开销,增长了对象的数目
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ import random from abc import ABCMeta, abstractmethod # 抽象策略 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.partation(data, left, right) self.quick_sort(data, left, mid - 1) self.quick_sort(data, mid + 1, right) def partation(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() random.shuffle(context.data) context.set_strategy(QuickSort()) context.do_strategy()
定义:使多个对象有机会处理请求,从而避免请求的发布者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象能处理它为止
角色:抽象处理者,具体处理者,客户端
适用场景:有多个对象能够处理一个请求,哪一个对象处理由运行时决定
优势:下降耦合度,一个对象无需知道是其余哪个对象处理其请求
缺点:请求不保证被接收,链的末端没有处理或链配置错误
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import ABCMeta, abstractmethod class Handler(metaclass=ABCMeta): @abstractmethod def handel_leave(self, day): pass class GeneralManagerHandler(Handler): def handel_leave(self, day): if day < 10: print('总经理批准请假%s天' % day) else: print('不能请假') class DepartmentManagerHandler(Handler): def __init__(self): self.successor = GeneralManagerHandler() def handel_leave(self, day): if day < 7: print('部门经理批准请假%s天' % day) else: print('部门经理无权批假') self.successor.handel_leave(day) class ProjectDirectorHandler(Handler): def __init__(self): self.successor = DepartmentManagerHandler() def handel_leave(self, day): if day < 3: print('项目经理批准请假%s天' % day) else: print('项目经理无权批假') self.successor.handel_leave(day) day = 6 h = ProjectDirectorHandler() h.handel_leave(day)
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ from abc import ABCMeta, abstractmethod # --模仿js事件处理 class Handler(metaclass=ABCMeta): @abstractmethod def add_event(self, func): pass @abstractmethod def handler(self): pass class BodyHandler(Handler): def __init__(self): self.func = None def add_event(self, func): self.func = func def handler(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 handler(self): if self.func: return self.func() else: return self.successor.handler() # 客户端 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'] = div div['children'] = 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) a['event_handler'].handler()
定义:提供一种方法可顺序访问一个聚合对象中的各个元素,而又不须要暴露该对象的内部指示
适用场景:实现方法__iter__,__next__
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ class LinkedList: class Node: def __init__(self, item=None): self.item = item self.next = None class LinkedListIterator: def __init__(self, node): self.node = node # 实现next方法,返回下一个元素 def __next__(self): if self.node: cur_node = self.node self.node = cur_node.next return cur_node.item def __iter__(self): return self def __init__(self, iterable=None): self.head = LinkedList.Node(0) self.tail = self.head self.extend(iterable) # 链表尾部追加元素 def append(self, obj): s = LinkedList.Node(obj) self.tail.next = s self.tail = s # 链表自动增长长度 def extend(self, iterable): for obj in iterable: self.append(obj) self.head.item += len(iterable) def __iter__(self): return self.LinkedListIterator(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 = LinkedList(li) print(lk)
定义:定义一个操做中算法的骨架,将一些步骤延迟到子类中,模板方法使得子类能够不改变一个算法的结构便可重定义该算法某些特定的步骤
角色:抽象类(定义抽象的原子操做,实现一个模板方法做为算法的骨架),具体类(实现原子操做)
适用场景:一次性实现一个算法不变的部分,各个子类的公共行为,应该被提取出来集中到公共的父类中以免代码重复,控制子类扩展
# -*- coding: utf-8 -*- """ @Datetime: 2019/4/17 @Author: Zhang Yafei """ 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')