常用设计模式

什么是设计模式?

Christopher Alexander:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样你就能一次又一次地使用该方案而不必做重复劳动。”

每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。

  设计模式四个基本要素:模式名称、问题、解决方案、效果

什么是接口?

  一种特殊的类,声明了若干方法,要求继承该接口的类必须实现这些方法。

  作用:限制继承接口的类的方法的名称及调用方式;隐藏了类的内部实现。  

  接口就是一种抽象的基类(父类),限制继承它的类必须实现接口中定义的某些方法

python第一种接口写法:

class Payment:   #接口类缺陷,如果子类不调用不会抛出异常
    def pay(self,money):
        raise NotImplementedError   #抛出一个没有实现的异常,继承他的子类中必须实现pay方法,否则抛出异常

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


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

#----client------
def paymethod(payment,money):   #第一个参数为付款类实例,第二个参数为付款金额
    payment.pay(money)  

paymethod(ApplePay(),100)

python第二种接口写法: 

from abc import abstractmethod, ABCMeta

class Payment(metaclass=ABCMeta):  #抽象类,必须声明元类为ABCMeta,则为抽象类
    @abstractmethod    #加装饰器则为抽象方法,子类必须实现
    def pay(self, money):   #只要子类没有实现此方法就报错
        raise NotImplementedError
  def fun(self): #普通方法,子类无须实现
    pass
   class Alipay(Payment): def pay(self, money): print("支付宝支付%s元"%money) class ApplePay(Payment): def pay(self, money): print("苹果支付%s元"%money) class WechatPay(Payment): def pay(self, money): print("微信支付%s元"%money) p = WechatPay() #如果类中未实现父类中约束的方法就报错

设计模式六大原则

开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

里氏(Liskov)替换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象。

依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。

接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用。

单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

创建型模式

单例模式

目的:保证一个类只有一个实例,并提供一个访问它的全局访问点。

适用场景: 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时

优点: 对唯一实例的受控访问 ,单例相当于全局变量,但防止了命名空间被污染

与单例模式功能相似的概念:全局变量、静态变量(方法)  

from abc import abstractmethod, ABCMeta

class Singleton(object):   #继承单例类的子类都为单例模式
    def __new__(cls, *args, **kwargs):   #构建实例对象,返回实例供__inin__函数使用
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


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


a = MyClass("a")

print(a)
print(a.name)

b = MyClass('b')  
#
print(b)  #与a的内存地址相同
print(b.name)
#
print(a)
print(a.name)  

简单工厂模式

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

优点: 隐藏了对象创建的实现细节 ,客户端不需要修改代码

缺点: 违反了单一职责原则,将创建逻辑几种到一个工厂类里 当添加新产品时,需要修改工厂类代码,违反了开闭原则

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(True)
        elif method == "applepay":
            return ApplePay()
        else:
            raise NameError(method)

f = PaymentFactory()
p = f.create_payment("alipay")
p.pay(100) 

工厂方法模式

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

角色: 抽象工厂角色(Creator) ,具体工厂角色(Concrete Creator) ,抽象产品角色(Product) ,具体产品角色(Concrete Product)

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

适用场景: 需要生产多种、大量复杂对象的时候, 需要降低耦合度的时候 ,当系统中的产品种类需要经常扩展的时候

优点: 每个具体产品都对应一个具体工厂类,不需要修改工厂类代码 ,工厂类可以不知道它所创建的对象的类, 隐藏了对象创建的实现细节

缺点 每增加一个具体产品类,就必须增加一个相应的具体工厂类

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()




# 用户输入
# 支付宝,120

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

 抽象工厂模式 

内容:定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。 

例:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。

角色: 抽象工厂角色(Creator), 具体工厂角色(Concrete Creator), 抽象产品角色(Product), 具体产品角色(Concrete Product), 客户端(Client)

相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。

适用场景: 系统要独立于产品的创建与组合时, 强调一系列相关的产品对象的设计以便进行联合使用时 提供一个产品类库,想隐藏产品的具体实现时

优点: 将客户端与类的具体实现相分离 ,每个工厂创建了一个完整的产品系列,使得易于交换产品系列 ,有利于产品的一致性(即产品之间的约束关系)

缺点: 难以支持新种类的(抽象)产品

  1 from abc import abstractmethod, ABCMeta
  2 
  3 # ------抽象产品------
  4 class PhoneShell(metaclass=ABCMeta):
  5     @abstractmethod
  6     def show_shell(self):
  7         pass
  8 
  9 class CPU(metaclass=ABCMeta):
 10     @abstractmethod
 11     def show_cpu(self):
 12         pass
 13 
 14 class OS(metaclass=ABCMeta):
 15     @abstractmethod
 16     def show_os(self):
 17         pass
 18 
 19 
 20 # ------抽象工厂------
 21 
 22 class PhoneFactory(metaclass=ABCMeta):
 23     @abstractmethod
 24     def make_shell(self):
 25         pass
 26 
 27     @abstractmethod
 28     def make_cpu(self):
 29         pass
 30 
 31     @abstractmethod
 32     def make_os(self):
 33         pass
 34 
 35 
 36 # ------具体产品------
 37 
 38 
 39 class SmallShell(PhoneShell):
 40     def show_shell(self):
 41         print("普通手机小手机壳")
 42 
 43 class BigShell(PhoneShell):
 44     def show_shell(self):
 45         print("普通手机大手机壳")
 46 
 47 class AppleShell(PhoneShell):
 48     def show_shell(self):
 49         print("苹果手机壳")
 50 
 51 
 52 class SnapDragonCPU(CPU):
 53     def show_cpu(self):
 54         print("骁龙CPU")
 55 
 56 
 57 class MediaTekCPU(CPU):
 58     def show_cpu(self):
 59         print("联发科CPU")
 60 
 61 
 62 class AppleCPU(CPU):
 63     def show_cpu(self):
 64         print("苹果CPU")
 65 
 66 
 67 class Android(OS):
 68     def show_os(self):
 69         print("Android系统")
 70 
 71 
 72 class IOS(OS):
 73     def show_os(self):
 74         print("iOS系统")
 75 
 76 
 77 # ------具体工厂------
 78 
 79 class MiFactory(PhoneFactory):
 80     def make_cpu(self):
 81         return SnapDragonCPU()
 82 
 83     def make_os(self):
 84         return Android()
 85 
 86     def make_shell(self):
 87         return BigShell()
 88 
 89 
 90 class HuaweiFactory(PhoneFactory):
 91     def make_cpu(self):
 92         return MediaTekCPU()
 93 
 94     def make_os(self):
 95         return Android()
 96 
 97     def make_shell(self):
 98         return SmallShell()
 99 
100 
101 class IPhoneFactory(PhoneFactory):
102     def make_cpu(self):
103         return AppleCPU()
104 
105     def make_os(self):
106         return IOS()
107 
108     def make_shell(self):
109         return AppleShell()
110 
111 
112 # ------客户端------
113 
114 
115 class Phone:
116     def __init__(self, cpu, os, shell):
117         self.cpu = cpu
118         self.os = os
119         self.shell = shell
120 
121     def show_info(self):
122         print("手机信息:")
123         self.cpu.show_cpu()
124         self.os.show_os()
125         self.shell.show_shell()
126 
127 
128 def make_phone(factory):
129     cpu = factory.make_cpu()
130     os = factory.make_os()
131     shell = factory.make_shell()
132     return Phone(cpu, os, shell)
133 
134 
135 p1 = make_phone(IPhoneFactory())
136 p1.show_info()
View Code

建造者模式

目的:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

角色: 抽象建造者(Builder), 具体建造者(Concrete Builder), 指挥者(Director) ,产品(Product)

建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。

适用场景: 当创建复杂对象的算法(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)  

结构型模式

适配器模式

目的:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

角色: 目标接口(Target), 待适配的类(Adaptee), 适配器(Adapter)

两种实现方式: 类适配器:使用多继承    

        对象适配器:使用组合

适用场景: 想使用一个已经存在的类,而它的接口不符合你的要求 (对象适配器)想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

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 huaqian(self, money):
print("微信支付%s元"%money)

#------类适配器------

class RealWeChatPay(Payment, WechatPay):
def pay(self, money):
return self.huaqian(money)


#------对象适配器------
class PayAdapter(Payment):
def __init__(self, payment): #payment为待适配对象
self.payment = payment

def pay(self, money):
return self.payment.huaqian(money)


RealWeChatPay().pay(100)
#PayAdapter(WechatPay()).pay(1000)

组合模式

目的:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

角色: 抽象组件(Component), 叶子组件(Leaf), 复合组件(Composite) ,客户端(Client)

适用场景: 表示对象的“部分-整体”层次结构(特别是结构是递归的) ,希望用户忽略组合对象与单个对象的不同,用户统一地使用组合结构中的所有对象

优点: 定义了包含基本对象和组合对象的类层次结构, 简化客户端代码,即客户端可以一致地使用组合对象和单个对象, 更容易增加新类型的组件

缺点: 很难限制组合中的组件

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()

 代理模式

内容:为其他对象提供一种代理以控制对这个对象的访问。  

角色: 抽象实体(Subject) ,实体(RealSubject) ,代理(Proxy)

适用场景: 远程代理:为远程的对象提供代理

     虚代理:根据需要创建很大的对象

     保护代理:控制对原始对象的访问,用于对象有不同访问权限时

优点: 远程代理:可以隐藏对象位于远程地址空间的事实

    虚代理:可以进行优化,例如根据要求创建对象

   保护代理:允许在访问一个对象时有一些附加的内务处理

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!="alex":
    p = ProxyC(filename)
else:
    p = ProxyA(filename)

print(p.get_content())  

行为型模式

责任链模式

内容:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

角色: 抽象处理者(Handler), 具体处理者(ConcreteHandler), 客户端(Client)

例: 请假部门批准:leader部门经理总经理 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 = 1
h = ProjectDirectorHandler()
h.handle_leave(day)

迭代器模式 

目的:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示

实现方法:__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

    def extend(self, iterable):
        for obj in iterable:
            self.append(obj)
        self.head.item += len(iterable)

    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)

 观察者模式

目的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。观察者模式又称“发布-订阅”模式 

角色: 抽象主题(Subject), 具体主题(ConcreteSubject)——发布者 ,抽象观察者(Observer), 具体观察者(ConcreteObserver)——订阅者

适用场景: 当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用。 当对一个对象的改变需要同时改变其它            对象,而不知道具体有多少对象有待改变。 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

优点: 目标和观察者之间的抽象耦合最小 ,支持广播通信

缺点: 多个观察者之间互不知道对方存在,因此一个观察者对主题的修改可能造成错误的更新。

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)

    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(Observer):
    def __init__(self):
        self.company_info = None

    def update(self, noti):
        self.company_info = noti.company_info


notice = ManagerNotice()    #发布者

AAA = Manager()
BBB = Manager()

#print(alex.company_info)
#print(wusir.company_info)

notice.attach(AAA)
notice.attach(BBB)
#
notice.company_info="公司运行良好"

notice.company_info="公司将要上市"

策略模式 

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

角色: 抽象策略(Strategy), 具体策略(ConcreteStrategy), 上下文(Context)

适用场景: 许多相关的类仅仅是行为有异, 需要使用一个算法的不同变体 ,算法使用了客户端无需知道的数据 一个类中的多种行为以多个条件语句的形式存在,可以将这些行为             封装如不同的策略类中。

优点: 定义了一系列可重用的算法和行为, 消除了一些条件语句 ,可以提供相同行为的不同实现

缺点: 客户必须了解不同的策略, 策略与上下文之间的通信开销, 增加了对象的数目

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()

模板方法模式

内容:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

角色: 抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。 具体类(ConcreteClass):实现原子操作

适用场景: 一次性实现一个算法的不变的部分 ,各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复 ,控制子类扩展

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")

  

 

 

posted @ 2017-05-31 11:49  amchen  阅读(145)  评论(0)    收藏  举报