什么是设计模式php
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、通过分类的、代码设计经验的总结html
使用设计模式的目的java
为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构同样node
设计模式六大原则python
1、开闭原则(Open Close Principle) 开闭原则:对扩展开放,对修改关闭。在程序须要进行扩展的时候,不能去修改或影响原有的代码。 多使用接口和抽象类 2、里氏替换原则(Liskov Substitution Principle) 里氏替换:任何基类能够出现的地方,子类必定能够出现。 3、依赖倒置原则(Dependence Inversion Principle) 依赖倒置:针对接口编程,高层模块不该该依赖底层模块,两者都应该依赖抽象。即不依赖与对接口的实现类,依赖抽象类。 4、接口隔离原则(Interface Segregation Principle) 接口隔离:客户端不该该依赖它不须要的接口;一个类对另外一个类的依赖应该创建在最小的接口上,即细化接口功能。 使用多个隔离的接口,比使用单个庞大的接口要好。 5、单一职责原则(Single Responsibility Principle) 单一职责:一个类只负责一项职责。 单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则。 须要设计人员发现类的不一样职责并将其分离,而发现类的多重职责须要设计人员具备较强的分析设计能力和相关实践经验 6、最少知识原则(Demeter Principle) 最少知识:又叫迪米特法则。一个对象应当对其余对象有尽量少的了解。
下面将使用python编程语言实现GoF的23种设计模式,这些设计模式可分为3大类:建立型、结构型和行为型算法
建立型:
工厂方法模式 Factory Method Pattern
抽象工厂模式 Abstract Factory Pattern
建立者模式 Builder Pattern
原型模式 Prototype Pattern
单例模式 Singleton Pattern
结构型:
设配器模式 Adapter Pattern
桥接模式 Bridge Pattern
组合模式 Composite Pattern
外观模式 Facade Pattern
享元模式 Flyweight Pattern
代理模式 Proxy Pattern
装饰器模式 Decorator Pattern
行为模式:
职责链模式 Chain of Responsibility Pattern
命令模式 Command Pattern
解释器模式 Interpreter Pattern
迭代器模式 Iterator Pattern
中介者模式 Mediator Pattern
忘备录模式 Memento Pattern
观察者模式 Observer Pattern
状态模式 State Pattern
策略模式 Strategy Pattern
模板方法模式 Template Method Pattern
访问者模式 Visitor Pattern
设计模式详解编程
1.工厂模式设计模式
在简单工厂模式中,咱们在建立对象时不会对客户端暴露建立逻辑,而且是经过使用一个共同的接口来指向新建立的对象.
优势:客户端不须要修改代码。
缺点: 当须要增长新的运算类的时候,不只需新加运算类,还要修改工厂类,违反了开闭原则。
__author__ = 'Cq' class Shape(object): def draw(self): # 该方法若是没有被重写将会弹出异常 raise NotImplementedError class Circle(Shape): def draw(self): print("draw circle...") class Square(Shape): def draw(self): print("draw square...") class ShapeFactory(object): def create(self, shape): if shape == "circle": return Circle() elif shape == "square": return Square() else: return None def main(): fac = ShapeFactory() obj = fac.create("square") obj.draw() if "__main__" == __name__: main()
1 draw square...
在工厂模式中,对应每个产品都有相应的工厂
好处:增长一个运算类(例如N次方类),只须要增长运算类和相对应的工厂,两个类,不须要修改工厂类。
缺点:增长运算类,会修改客户端代码,工厂方法只是把简单工厂的内部逻辑判断移到了客户端进行。
__author__ = 'Cq' class AbstractProduct(object): def use(self): raise NotImplementedError class AbstractFactory(object): def create(self, owner): p = self.createProduct(owner) self.registerProduct(p) return p def createProduct(self, owner): raise NotImplementedError def registerProduct(self, p): raise NotImplementedError class IPhone(AbstractProduct): def __init__(self, name): self.__owner = name print("made %s's phone" % name) def use(self): print("%s use IPhone" % self.__owner) def getOwner(self): return self.__owner class Computer(AbstractProduct): def __init__(self, name): self.__owner = name print("made %s's computer" % name) def use(self): print("%s use computer" % self.__owner) def getOwner(self): return self.__owner class IPhoneFactory(AbstractFactory): def __init__(self): self.__owners = [] def createProduct(self, owner): return IPhone(owner) def registerProduct(self, p): self.__owners.append(p.getOwner()) def getOwners(self): return self.__owners class ComputerFactory(AbstractFactory): def __init__(self): self.__owners = [] def createProduct(self, owner): return Computer(owner) def registerProduct(self, p): self.__owners.append(p.getOwner()) def getOwners(self): return self.__owners def main(): fac_i = IPhoneFactory() fac_c = ComputerFactory() iphone1 = fac_i.create("alex") iphone2 = fac_i.create('seven') computer1 = fac_c.create("bob") computer2 = fac_c.create("tom") iphone1.use() iphone2.use() computer1.use() computer2.use() print(fac_i.getOwners()) print(fac_c.getOwners()) if "__main__" == __name__: main()
1 made alex's phone 2 made seven's phone 3 made bob's computer 4 made tom's computer 5 alex use IPhone 6 seven use IPhone 7 bob use computer 8 tom use computer 9 ['alex', 'seven'] 10 ['bob', 'tom']
2.抽象工厂模式缓存
抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品;而抽象工厂模式则须要面对多个产品。 抽象工厂角色: AbstractProduct(抽象产品) 负责定义抽象工厂角色所生成的抽象零件和产品的接口 AbstractFactory(抽象工厂) 负责定义用于生成抽象产品的接口 Client(委托者) 仅会调用抽象产品和抽象角色的接口来进行工做,对于具体的零件、产品和工厂一无所知 ConcreteProduct(具体产品) 负责实现抽象产品的接口 ConcreteFactory(具体工厂) 负责实现抽象工厂的接口 在什么状况下应当使用抽象工厂模式 1.一个系统不依赖于产品类实例如何被建立、组合和表达的细节,这对于全部形态的工厂模式是很是重要的。 2.这个系统的产品有多于一个的产品,而系统只消费其中某一种的产品。 3.同属于同一个产品的零件是在一块儿使用的,这一约束必须在系统的设计中体现出来。(好比:Intel主板必须使用Intel CPU、Intel芯片组) 4.系统提供一个产品类的库,全部的产品以一样的接口出现,从而使客户端不依赖于实现 优先:易于增长具体的工厂 缺点:难以增长新的零件
__author__ = 'Cq' class AbstractFactory(object): def __init__(self, name): self.fac_name = name def createCpu(self): raise NotImplementedError def createMainboard(self): raise NotImplementedError class IntelFactory(AbstractFactory): def __init__(self, name="Intel I7-series computer"): super(IntelFactory, self).__init__(name) def createCpu(self): return IntelCpu('I7-6500') def createMainboard(self): return IntelMainBoard('Intel-6000') class AmdFactory(AbstractFactory): def __init__(self, name="Amd 4 computer"): super(AmdFactory, self).__init__(name) def createCpu(self): return AmdCpu('amd444') def createMainboard(self): return AmdMainBoard('AMD-4000') class AbstractCpu(object): def __init__(self, name, instructions="", arch=""): self.series_name = name self.instructions = instructions self.arch = arch class IntelCpu(AbstractCpu): def __init__(self, series): super(IntelCpu, self).__init__(series) class AmdCpu(AbstractCpu): def __init__(self, series): super(AmdCpu, self).__init__(series) class AbstractMainboard(object): def __init__(self, name): self.series_name = name class IntelMainBoard(AbstractMainboard): def __init__(self, series): super(IntelMainBoard, self).__init__(series) class AmdMainBoard(AbstractMainboard): def __init__(self, series): super(AmdMainBoard, self).__init__(series) class ComputerEngineer(object): def __init__(self): self.cpu = None self.mainboard = None def makeComputer(self, factory_obj): self.prepareHardwares(factory_obj) def prepareHardwares(self, factory_obj): self.cpu = factory_obj.createCpu() self.mainboard = factory_obj.createMainboard() info = '''------- computer [%s] info: cpu: %s mainboard: %s -------- End -------- ''' % (factory_obj.fac_name, self.cpu.series_name, self.mainboard.series_name) print(info) def main(): engineer = ComputerEngineer() intel_computer = IntelFactory() engineer.makeComputer(intel_computer) amd_computer = AmdFactory() engineer.makeComputer(amd_computer) if "__main__" == __name__: main()
1 ------- computer [Intel I7-series computer] info: 2 3 cpu: I7-6500 4 mainboard: Intel-6000 5 6 -------- End -------- 7 8 9 ------- computer [Amd 4 computer] info: 10 11 cpu: amd444 12 mainboard: AMD-4000 13 14 -------- End --------
3.建立者模式安全
大都市中林立着许多高楼大厦,这些高楼大厦都是具备建筑结构的大型建筑。
在建筑大楼时,须要先打牢地基,搭建架构,而后自下而上地一层一层盖起来。
对于相似的,咱们首先建造这个物体的各个部分,而后分阶段将它们组装起来。
各个部分中的某些细节不一样,构建出的产品表象会略有不一样。
咱们能够把物体看作一个产品,经过一个指挥者按照产品的建立步骤来一步步执行产品的建立。
当须要建立不一样的产品时,只须要派生一个具体的建造者,重写相应的组件构建方法便可。
class AnimalBuilder(object): def __init__(self, name, category=""): self.name = name self.category = category def buildHead(self): raise NotImplementedError def buildBody(self): raise NotImplementedError def buildLimb(self): raise NotImplementedError def getInfo(self): raise NotImplementedError class Bird(AnimalBuilder): def __init__(self, name): super(Bird, self).__init__(name) def buildHead(self): print("创造了鸟的头部") def buildBody(self): print("创造了鸟的身体") def buildLimb(self): print("创造了鸟的四肢") def getInfo(self): print("这只鸟是一只%s" % self.name) class Fox(AnimalBuilder): def __init__(self, name): super(Fox, self).__init__(name) def buildHead(self): print("创造了狐狸的头部") def buildBody(self): print("创造了狐狸的身体") def buildLimb(self): print("创造了狐狸的四肢") def getInfo(self): print("这只狐狸是一只%s" % self.name) class AnimalDirector(object): def __init__(self, animal): self.__animal = animal def createAniaml(self): self.__animal.buildHead() self.__animal.buildBody() self.__animal.buildLimb() def setAnimal(self, animal): self.__animal = animal def main(): bird = Bird("猫头鹰") director = AnimalDirector(bird) director.createAniaml() bird.getInfo() fox = Fox("北极狐") director.setAnimal(fox) director.createAniaml() fox.getInfo() if "__main__" == __name__: main()
1 创造了鸟的头部 2 创造了鸟的身体 3 创造了鸟的四肢 4 这只鸟是一只猫头鹰 5 创造了狐狸的头部 6 创造了狐狸的身体 7 创造了狐狸的四肢 8 这只狐狸是一只北极狐
4.单例模式
程序在运行时,一般都会生成不少实例
当咱们在想在程序中只表示某个东西时只会存在一个时,就会有“只能建立一个实例”的需求
当存在多个实例时,实例之间相互影响,可能会产生意想不到的Bug,可是,若是咱们能够确保只有一个实例,就能够放心的编程了
class Singleton(object): def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance def main(): person = Singleton("alex") person2 = Singleton("bob") print(person.name) print(person2.name) if "__main__" == __name__: main()
1 bob 2 bob
# 解析代码: 1.p = Person(name, age) 2.首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(一般状况下是使用 super(Persion, cls).__new__(cls, ... ...) 这样的方式), 3.而后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self 因此,__init__ 和 __new__ 最主要的区别在于: 1.__init__ 一般用于初始化一个新实例,控制这个初始化的过程,好比添加一些属性, 作一些额外的操做,发生在类实例被建立完之后。它是实例级别的方法。 2.__new__ 一般用于控制生成一个新实例的过程。它是类级别的方法
5.适配器模式
应用场景:当咱们的电脑带到香港时,不能直接插插头使用,咱们电脑标准电压和香港通用电压不同,不能直接使用墙上的插口,须要中间加一个适配器,将电压转换为咱们电脑适用的电压。
一样是电脑,作相同的工做,却由于环境不一样不能使用。Adapter 模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。
将一个类的接口转换成客户但愿的另一个接口。
class Person(object): def speak(self): raise NotImplementedError def write(self): raise NotImplementedError class Native(Person): def __init__(self, name): self.name = name def speak(self): print("%s 在用中文说话" % self.name) def write(self): print("%s 在写中文" % self.name) class Foreigners(object): def __init__(self, name): self.name = name def foreignerSpeak(self): print("%s 在说蹩脚的中文" % self.name) def foreignerWrite(self): print("%s 在写中文" % self.name) class Translator(Person): def __init__(self, foreigner=None): self.foreigner = foreigner def speak(self): self.foreigner.foreignerSpeak() def write(self): self.foreigner.foreignerWrite() def main(): p1 = Native("wang wu") p2 = Foreigners("alex") trans = Translator(p2) p1.speak() trans.speak() p1.write() trans.write() if "__main__" == __name__: main()
1 wang wu 在用中文说话 2 alex 在说蹩脚的中文 3 wang wu 在写中文 4 alex 在写中文
6.桥接模式
Bridge的意思是桥梁。就像在现实世界中,桥梁的功能是将河流的两侧链接起来同样,Bridge模式的做用也是将两样东西链接起来,它们分别是类的功能层次结构和类的实现层次结构。 将抽象部分与实现部分分离,使它们均可以独立的变化。 使用组合的功能,链接多维度的事物。 适用性: 1.若是一个系统须要在构件的抽象化角色和具体化角色之间增长更多的灵活性,避免在两个层次之间创建静态的联系。 2.设计要求实现化角色的任何改变不该当影响客户端,或者说实现化角色的改变对客户端是彻底透明的。 3.一个构件有多于一个的抽象化角色和实现化角色,系统须要它们之间进行动态耦合。 4.虽然在系统中使用继承是没有问题的,可是因为抽象化角色和具体化角色须要独立变化,设计要求须要独立管理这二者。
class AbstractCollege(object): def __init__(self, name, major=None): self.name = name self.major = major def start(self): raise NotImplementedError class ComputerCollege(AbstractCollege): def __init__(self, name="计算机学院", major=None): super(ComputerCollege, self).__init__(name, major) def start(self): print("\n%s的" % self.name) self.major.start() class ArtCollege(AbstractCollege): def __init__(self, name="艺术学院", major=None): super(ArtCollege, self).__init__(name, major) def start(self): print("\n%s的" % self.name) self.major.start() class AbstractMajor(object): def __init__(self, name, course=None): self.name = name self.course = course def start(self): raise NotImplementedError class NetworkMajor(AbstractMajor): def __init__(self, name="网络专业", course=None): super(NetworkMajor, self).__init__(name, course) def start(self): print("%s的" % self.name) self.course.start() class PerformMajor(AbstractMajor): def __init__(self, name="表演专业", course=None): super(PerformMajor, self).__init__(name, course) def start(self): print("%s的" % self.name) self.course.start() class AbstractCourse(object): def __init__(self, name): self.name = name def start(self): raise NotImplementedError class PythonCourse(AbstractCourse): def __init__(self, name="Python编程"): super(PythonCourse, self).__init__(name) def start(self): print("%s 课程开始了" % self.name) class TheoryOfPerformanceCourse(AbstractCourse): def __init__(self, name="表演理论"): super(TheoryOfPerformanceCourse, self).__init__(name) def start(self): print("%s 课程开始了" % self.name) def main(): # 三个维度的事物以组合的方式结合在一块儿,互不影响,互相调用 coll1 = ComputerCollege() coll2 = ArtCollege() maj1 = NetworkMajor() maj2 = PerformMajor() cour1 = TheoryOfPerformanceCourse() cour2 = PythonCourse() coll1.major = maj1 coll2.major = maj2 maj1.course = cour1 maj2.course = cour2 coll1.start() coll2.start() if "__main__" == __name__: main()
1 计算机学院的 2 网络专业的 3 表演理论 课程开始了 4 5 艺术学院的 6 表演专业的 7 Python编程 课程开始了
7.组合模式
在计算机的文件系统中,有“文件夹”的概念。文件夹里面既能够放入文件,也能够放入其它文件夹。
将文件夹与文件都做为目录条目看待同样,将容器和内容做为同一种东西看待,容器中既能够放内容,也能够放小容器。
在子文件夹中,同样地既能够放入文件,也能够放入子文件夹。能够说,文件夹是造成一种容器结构、递归结构。
可以使容器与内容具备一致性,创造出递归结构的模式就是组合模式。
__author__ = 'Cq' class Entry(object): def getName(self): raise NotImplementedError def getSize(self): raise NotImplementedError def printList(self, prefix): raise NotImplementedError def add(self, entry): pass class File(Entry): def __init__(self, name, size): self.name = name self.size = size def getName(self): return self.name def getSize(self): return self.size def printList(self, prefix): print("file:[%s/%s] --> size:%s\n" % (prefix, self.name, self.getSize())) class Directory(Entry): def __init__(self, name): self.name = name self.directory = [] def getName(self): return self.name def getSize(self): size = 0 for i in self.directory: size += i.getSize() return size def printList(self, prefix=""): prefix += "/"+self.name print("[%s] --> size:%s " % (prefix, self.getSize())) for i in self.directory: i.printList(prefix) def add(self, entry): self.directory.append(entry) def main(): print("-----------Prepare the root file directory...") rootdir = Directory("root") bindir = Directory("bin") tmpdir = Directory("tmp") usrdir = Directory("usr") rootdir.add(bindir) rootdir.add(tmpdir) rootdir.add(usrdir) bindir.add(File("httpd", 2000)) usrdir.add(File("python", 5000)) rootdir.printList() print("\n-------------Prepare the usr file directory...") javadir = Directory("java") godir = Directory("go") phpdir = Directory("php") usrdir.add(javadir) usrdir.add(godir) usrdir.add(phpdir) javadir.add(File("hello.java", 20)) godir.add(File("hello.go", 100)) phpdir.add(File("hello.php", 50)) rootdir.printList() if "__main__" == __name__: main()
1 -----------Prepare the root file directory... 2 [/root] --> size:7000 3 [/root/bin] --> size:2000 4 file:[/root/bin/httpd] --> size:2000 5 6 [/root/tmp] --> size:0 7 [/root/usr] --> size:5000 8 file:[/root/usr/python] --> size:5000 9 10 11 -------------Prepare the usr file directory... 12 [/root] --> size:7170 13 [/root/bin] --> size:2000 14 file:[/root/bin/httpd] --> size:2000 15 16 [/root/tmp] --> size:0 17 [/root/usr] --> size:5170 18 file:[/root/usr/python] --> size:5000 19 20 [/root/usr/java] --> size:20 21 file:[/root/usr/java/hello.java] --> size:20 22 23 [/root/usr/go] --> size:100 24 file:[/root/usr/go/hello.go] --> size:100 25 26 [/root/usr/php] --> size:50 27 file:[/root/usr/php/hello.php] --> size:50
8.外观模式
程序这东西老是会变的愈来愈大。随着时间的推移,程序中的类会愈来愈多,并且,它们之间相互关联,这会致使程序结构也变得愈来愈复杂。 特别是在调用大型程序进行处理时,咱们须要格外注意哪些数量庞大的类之间错综复杂的关系。 不过与其这么作,不如为这个大型程序准备一个“窗口”,只须要简单地对“窗口”提出请求便可。 Facade模式,不只作到,还考虑到系统内部各个类之间的责任关系和依赖关系,按照正确的顺序调用各个类。 在如下状况下能够考虑使用外观模式: (1)设计初期阶段,应该有意识的将不一样层分离,层与层之间创建外观模式。 (2) 开发阶段,子系统愈来愈复杂,增长外观模式提供一个简单的调用接口。 (3) 维护一个大型遗留系统的时候,可能这个系统已经很是难以维护和扩展,但又包含很是重要的功能,为其开发一个外观类,以便新系统与其交互。 优势: (1)实现了子系统与客户端之间的松耦合关系。 (2)客户端屏蔽了子系统组件,减小了客户端所需处理的对象数目,并使得子系统使用起来更加容易。
__author__ = 'Cq' class Stock(): def __init__(self, name="股票"): self.name = name def buy(self): print('买 '+self.name) def sell(self): print('卖 '+self.name) class ETF(): def __init__(self, name="指数型基金"): self.name = name def buy(self): print('买 '+self.name) def sell(self): print('卖 '+self.name) class Future(): def __init__(self, name="期货"): self.name = name def buy(self): print('买 '+self.name) def sell(self): print('卖 '+self.name) class NationDebt(): def __init__(self, name="国债"): self.name = name def buy(self): print('买 '+self.name) def sell(self): print('卖 '+self.name) class Option(): def __init__(self, name="权证"): self.name = name def buy(self): print('买 '+self.name) def sell(self): print('卖 '+self.name) # 基金类 class Fund(): def __init__(self): self.stock = Stock() self.etf = ETF() self.future = Future() self.debt = NationDebt() self.option = Option() def buyFund(self): self.stock.buy() self.etf.buy() self.debt.buy() self.future.buy() self.option.buy() def sellFund(self): self.stock.sell() self.etf.sell() self.future.sell() self.debt.sell() self.option.sell() def main(): myfund = Fund() myfund.buyFund() myfund.sellFund() if __name__ == '__main__': main()
1 买 股票 2 买 指数型基金 3 买 国债 4 买 期货 5 买 权证 6 卖 股票 7 卖 指数型基金 8 卖 期货 9 卖 国债 10 卖 权证
9.原型模式
在开发的过程当中,有时候会有“在不指定类名的前提下生成实例”的需求。 在如下状况下能够考虑使用原型模式: (1)对象种类繁多,没法将它们整合到一个类中的 对象太多,若是将它们分别做为一个类,必须编写不少类文件 (2)难以根据类生成实例时 生成实例的过程太过复杂,很难根据类来生成实例。 咱们会预先将想生成的实例保存起来,而后在须要时经过复制来生成新的实例 (3)想解耦框架与生成的实例时 想让生成实例的框架不依赖与具体的类。这时,不能指定类名来生成实例,而事先“注册”一个“原型”实例,而后经过负责该实例来生成新的实例
__author__ = 'Cq' from copy import copy, deepcopy class Model(object): def __init__(self, mid): self.id = mid def display(self): raise NotImplementedError def clone(self): raise NotImplementedError def deepClone(self): raise NotImplementedError class Materials(object): def __init__(self, name): self.name = name class Teapot(Model): def __init__(self, name, mid, materials="塑料"): self.name = name self.materials = Materials(materials) super(Teapot, self).__init__(mid) def display(self): print(">> name:%s id:%s materials:%s" % (self.name, self.id, self.materials.name)) def clone(self): return copy(self) def deepClone(self): return deepcopy(self) class Manager(object): def __init__(self): self.dicts = {} def register(self, name, model): self.dicts[name] = model def create(self, model_name): return self.dicts[model_name].clone() def deepCreate(self, model_name): return self.dicts[model_name].deepClone() def main(): manager = Manager() blue = Teapot("blue model", "001") red = Teapot("red model", "002") white = Teapot("white model", "003") manager.register(blue.name, blue) manager.register(red.name, red) manager.register(white.name, white) blue_teapot = manager.create("blue model") blue_teapot.name = "blue rosewood teapot" blue2_teapot = manager.deepCreate("blue model") blue2_teapot.name = "blue stainless steel teapot" blue_teapot.materials.name = "花梨木" blue2_teapot.materials.name = "不锈钢" blue.display() blue_teapot.display() blue2_teapot.display() if '__main__' == __name__: main()
1 >> name:blue model id:001 materials:花梨木 2 >> name:blue rosewood teapot id:001 materials:花梨木 3 >> name:blue stainless steel teapot id:001 materials:不锈钢
# 结果解析: 因为blue_teapot(蓝色花梨木茶壶)实例没有深度复制实例(蓝色茶壶模型),致使materials对象没有被复制,当blue_teapot修改变量时,影响到了原来的实例 而blue2_teapot(蓝色不锈钢茶壶)实例对blue进行了深度复制,与原实例是如出一辙的copy对象,它们之间没有关联
10.享元模式
Flyweight是“轻量级”的意思,然而对象在计算机中是虚拟存在的东西,它的“重”和“轻”并不是指实际重量,然而是它们“使用的内存大小”。
使用内存多的对象就是“重”对象,使用内存少的对象就是“轻”对象。
Flyweight模式就是,经过尽可能共享实例来避免建立出新的实例。
抽象享元角色(Flyweight):此角色是全部的具体享元类的超类,为这些类规定出须要实现的公共接口或抽象类。那些须要外部状态(External State)的操做能够经过方法的参数传入。抽象享元的接口使得享元变得可能,可是并不强制子类实行共享,所以并不是全部的享元对象都是能够共享的。
具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。若是有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象能够在系统内共享。有时候具体享元角色又叫作单纯具体享元角色,由于复合享元角色是由单纯具体享元角色经过复合而成的。
复合享元(UnsharableFlyweight)角色:复合享元角色所表明的对象是不能够共享的,可是一个复合享元对象能够分解成为多个自己是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。这个角色通常不多使用。
享元工厂(FlyweightFactoiy)角色:本角色负责建立和管理享元角色。本角色必须保证享元对象能够被系统适当地共享。当一个客户端对象请求一个享元对象的时候,享元工厂角色须要检查系统中是否已经有一个符合要求的享元对象,若是已经有了,享元工厂角色就应当提供这个已有的享元对象;若是系统中没有一个适当的享元对象的话,享元工厂角色就应当建立一个新的合适的享元对象。
客户端(Client)角色:本角色还须要自行存储全部享元对象的外部状态。
内部状态与外部状态:在享元对象内部而且不会随着环境改变而改变的共享部分,能够称之为享元对象的内部状态,反之随着环境改变而改变的,不可共享的状态称之为外部状态。
__author__ = 'Cq' class FlyweightBase(object): _instances = dict() def __init__(self, *args, **kwargs): # 继承的子类必须初始化 raise NotImplementedError def __new__(cls, *args, **kwargs): # print(cls._instances,type(cls)) return cls._instances.setdefault( (cls, args, tuple(kwargs.items())), super(FlyweightBase, cls).__new__(cls) ) # setdefault返回父类的new方法,当实例化的类是同一类,而且传递的参数同样时,则返回之前半实例化的new方法对象(内存中已经存在) # 将触发BoardShoes子类或Sneaker子类的构造方法 def display(self): raise NotImplementedError class BoardShoes(FlyweightBase): def __init__(self, size, brand): self.size = size self.brand = brand def display(self): print("This pair of %s-yard board shoes is %s" % (self.size, self.brand)) class Sneaker(FlyweightBase): def __init__(self, size, brand): self.size = size self.brand = brand def display(self): print("This pair of %s-yard sneakers is %s" % (self.size, self.brand)) def main(): shoes1 = BoardShoes(40, "Nike") shoes2 = BoardShoes(40, "Nike") shoes3 = Sneaker(40, "Adidas") shoes1.display() print(">>id:", id(shoes1), "\n") shoes2.display() print(">>id:", id(shoes2), "\n") shoes3.display() print(">>id:", id(shoes3), "\n") if "__main__" == __name__: main()
1 This pair of 40-yard board shoes is Nike 2 >>id: 35780312 3 4 This pair of 40-yard board shoes is Nike 5 >>id: 35780312 6 7 This pair of 40-yard sneakers is Adidas 8 >>id: 35780368
11.代理模式
Proxys "代理人"的意思,它指的是代替别人进行工做的人。 在直接访问对象时带来的问题,好比说:要访问的对象在远程的机器上。在面向对象系统中,有些对象因为某些缘由(好比对象建立开销很大,或者某些操做须要安全控制,或者须要进程外的访问),直接访问会给使用者或者系统结构带来不少麻烦,咱们能够在访问此对象时加上一个对此对象的访问层。 当不必定须要本人亲自进行工做时,就能够寻找代理人去完成工做。 当代理人遇到没法本身解决的事情时就会去找本人解决该问题。 实现:增长中间层,实现与被代理类组合。
__author__ = 'Cq' class Printable(object): def setPrinterName(self, name): raise NotImplementedError def getPrinterName(self): raise NotImplementedError def print(self, string): raise NotImplementedError class Printer(Printable): def __init__(self, name): self.name = name def setPrinterName(self, name): self.name = name def getPrinterName(self): return self.name def print(self, string): print("----------%s----------" % self.name) print(string) class PrinterProxy(Printable): def __init__(self, name, printer=None): self.name = name self.real = printer def setPrinterName(self, name): if self.real is not None: self.real.setPrinterName(name) self.name = name def getPrinterName(self): return self.name def print(self, string): self.realize() self.real.print(string) def realize(self): if self.real is None: print("设置被代理人%s..." % self.name) self.real = Printer(self.name) def main(): p1 = Printer("Alice") p2 = PrinterProxy("Bob") # 使用打印机打印资料 p1.print("打印资料中...\n") # 使用打印机代理打印资料,未指定被代理人,自动建立被代理人 p2.print("打印代理打印资料中...\n") # 修改被代理人 p2.setPrinterName("Seven") p2.print("打印代理继续打印资料中...\n") # 删除被代理人,自动建立被代理人 p2.real = None p2.setPrinterName("Alex") p2.print("打印代理继续继续打印资料中...") if "__main__" == __name__: main()
1 ----------Alice---------- 2 打印资料中... 3 4 设置被代理人Bob... 5 ----------Bob---------- 6 打印代理打印资料中... 7 8 ----------Seven---------- 9 打印代理继续打印资料中... 10 11 设置被代理人Alex... 12 ----------Alex---------- 13 打印代理继续继续打印资料中...
12.装饰器模式
假如如今有一块蛋糕,若是只涂上奶油,其它什么都不加,就是奶油蛋糕。若是加上草莓,就是草莓奶油蛋糕。若是加上一块黑色巧克力板,上面用白色巧克力写上姓名,而后插上表明年龄的蜡烛,就变成了一块生日蛋糕。
不管是蛋糕、奶油蛋糕、草莓蛋糕仍是生日蛋糕,它们的核心都是蛋糕。
像这样不断地对对象添加装饰的设计模式称为装饰器模式
__author__ = 'Cq' ''' 该案例为字符串加上边框线条装饰,实现装饰器模式 ''' class Display(object): ''' 用于显示字符串的抽象类 ''' def getColumns(self): ''' 获取横向字符数 :return: ''' raise NotImplementedError def getRows(self): ''' 获取纵向行数 :return: ''' raise NotImplementedError def getRowText(self, row): ''' 获取第row行的字符串 :return: ''' raise NotImplementedError def show(self): for i in range(self.getRows()): print(self.getRowText(i)) class StringDisplay(Display): ''' 用于显示单行字符串的类 ''' def __init__(self, string): self.__string = string def getColumns(self): return len(self.__string) def getRows(self): return 1 def getRowText(self, row): if row == 0: return self.__string else: return None class Border(Display): ''' 用于显示装饰边框的抽象类 ''' def __init__(self, display): self.display = display class SideBorder(Border): ''' 用于显示左右边框的类 ''' def __init__(self, display, ch): super(SideBorder, self).__init__(display) self.borderChar = ch def getColumns(self): return 1 + self.display.getColumns() + 1 def getRows(self): return self.display.getRows() def getRowText(self, row): return self.borderChar + self.display.getRowText(row) + self.borderChar class FullBorder(Border): ''' 用于显示上下左右边框的类 ''' def __init__(self, display): super(FullBorder, self).__init__(display) def getColumns(self): return 1 + self.display.getColumns() + 1 def getRows(self): return 1 + self.display.getRows() + 1 def getRowText(self, row): if row == 0: return "+" + self.makeLine('-', self.display.getColumns()) + "+" elif row == self.display.getRows() + 1: return "+" + self.makeLine('-', self.display.getColumns()) + "+" else: return "|" + self.display.getRowText(row - 1) + "|" def makeLine(self, ch, count): string = "" for i in range(count): string += ch return string def main(): b1 = StringDisplay("Hello world!") b2 = SideBorder(b1, '#') b3 = FullBorder(b2) b1.show() print('=====================================') b2.show() print('=====================================') b3.show() print('=====================================') b4 = SideBorder(FullBorder(FullBorder(SideBorder(FullBorder(StringDisplay("你好,世界!")), '*'))), '/') b4.show() print('=====================================') if '__main__' == __name__: main()
1 Hello world! 2 ===================================== 3 #Hello world!# 4 ===================================== 5 +--------------+ 6 |#Hello world!#| 7 +--------------+ 8 ===================================== 9 /+------------+/ 10 /|+----------+|/ 11 /||*+------+*||/ 12 /||*|你好,世界!|*||/ 13 /||*+------+*||/ 14 /|+----------+|/ 15 /+------------+/ 16 =====================================
13.模板方法模式
组成模板的方法被定义在父类中。因为这些方法是抽象方法,因此只查看父类的代码是没法知道这些方法最终会进行何种具体处理的,惟一能知道的就是父类是如何调用这些方法的。
实现抽象方法的是子类,在子类中实现了抽象方法也就决定了具体的处理。
只要在不一样的子类中实现不一样的具体处理,当父类的模板方法被调用时程序行为也会不一样。
在父类中定义处理流程的框架,在子类中实现具体处理的模式就称为模板方法模式。
__author__ = 'Cq' class AbstractDevice(object): def powerOn(self): raise NotImplementedError def knobDown(self): raise NotImplementedError def startingUp(self): raise NotImplementedError class Servers(AbstractDevice): def powerOn(self): print("插上服务器电源线") def knobDown(self): print("按下服务器开机按钮") def startingUp(self): self.powerOn() self.knobDown() class Computer(AbstractDevice): def powerOn(self): print("插上电脑电源线") def knobDown(self): print("按下电脑开机按钮") def startingUp(self): self.powerOn() self.knobDown() def main(): s = Servers() c = Computer() s.startingUp() c.startingUp() if "__main__" == __name__: main()
1 插上服务器电源线 2 按下服务器开机按钮 3 插上电脑电源线 4 按下电脑开机按钮
14.责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
例如:
当外部请求程序进行某个处理,但程序暂时没法直接决定由哪一个对象负责处理时,就须要推卸责任。
这种状况下,咱们能够考虑将多个对象组成一条职责链,而后按照它们在职责链上的顺序一个一个地找出到底应该谁来负责处理。
这种模式称为“职责链”。
__author__ = 'Cq' class BaseHandler(object): ''' 处理基类 ''' def successor(self, successor): # 与下一个责任者关联 self._successor = successor class RequestHandlerL1(BaseHandler): ''' 第一级请求处理者 ''' name = "导员" def handle(self, request): if request < 2: print("审批者[%s],请假天数[%s],审批结果[审批经过]" % (self.name, request)) else: print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" %self.name) self._successor.handle(request) class RequestHandlerL2(BaseHandler): '''第二级请求处理者''' name = "班主任" def handle(self, request): if request < 7: print("审批者[%s],请假天数[%s],审批结果[审批经过]" % (self.name, request)) else: print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" % self.name) self._successor.handle(request) class RequestHandlerL3(BaseHandler): '''第三级请求处理者''' name = "教学院长" def handle(self, request): if request < 15: print("审批者[%s],请假天数[%s],审批结果[审批经过]" % (self.name, request)) else: print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" % self.name) self._successor.handle(request) class RequestHandlerL4(BaseHandler): '''第四级请求处理者''' name = "校长" def handle(self, request): if request < 90: print("审批者[%s],请假天数[%s],审批结果[审批经过]" % (self.name, request)) else: print("\033[31;1m[%s]请假天数太多了,不批\033[0m" % self.name) #self._successor.handle(request) class RequestAPI(object): h1 = RequestHandlerL1() h2 = RequestHandlerL2() h3 = RequestHandlerL3() h4 = RequestHandlerL4() h1.successor(h2) h2.successor(h3) h3.successor(h4) def __init__(self, name, days): self.name = name self.days = days def handle(self): # 出责任链最低级开始 self.h1.handle(self.days) def setDays(self, days): self.days = days def main(): r1 = RequestAPI("老王", 1) r1.handle() print(r1.__dict__, "\n") r1.setDays(5) r1.handle() print(r1.__dict__, "\n") r1.setDays(10) r1.handle() print(r1.__dict__, "\n") r1.setDays(30) r1.handle() print(r1.__dict__, "\n") r1.setDays(100) r1.handle() print(r1.__dict__, "\n") if "__main__" == __name__: main()
1 审批者[导员],请假天数[1],审批结果[审批经过] 2 {'name': '老王', 'days': 1} 3 4 [导员]无权审批,交给下一个审批者 5 审批者[班主任],请假天数[5],审批结果[审批经过] 6 {'name': '老王', 'days': 5} 7 8 [导员]无权审批,交给下一个审批者 9 [班主任]无权审批,交给下一个审批者 10 审批者[教学院长],请假天数[10],审批结果[审批经过] 11 {'name': '老王', 'days': 10} 12 13 [导员]无权审批,交给下一个审批者 14 [班主任]无权审批,交给下一个审批者 15 [教学院长]无权审批,交给下一个审批者 16 审批者[校长],请假天数[30],审批结果[审批经过] 17 {'name': '老王', 'days': 30} 18 19 [导员]无权审批,交给下一个审批者 20 [班主任]无权审批,交给下一个审批者 21 [教学院长]无权审批,交给下一个审批者 22 [校长]请假天数太多了,不批 23 {'name': '老王', 'days': 100}
15.观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 全部依赖于它的对象都获得通知并被自动更新。
Oberver的意思是“进行观察的人”,也就是“观察者”的意思。
当观察对象的状态发生变化时,会通知给观察者。
__author__ = 'Cq' class ObserverBase(object): '''被观察对象基类''' def __init__(self): self._observerd_list = [] def attach(self, observe_subject): ''' 添加观察者 :param observe_subject: :return: ''' if observe_subject not in self._observerd_list: self._observerd_list.append(observe_subject) print("[%s]已经将[%s]加入观察队列..." % (self.name, observe_subject.name)) def detach(self,observe_subject): ''' 解除观察关系 :param observe_subject: :return: ''' try: self._observerd_list.remove(observe_subject) print("再也不观察[%s]" % observe_subject) except ValueError: pass def notify(self): ''' 通知全部观察者 :return: ''' for objserver in self._observerd_list: objserver.update(self) class Observer(ObserverBase): '''被观察者类''' def __init__(self, name): super(Observer, self).__init__() self.name = name self._msg = '' @property def msg(self): ''' 当前情况 :return: ''' return self._msg @msg.setter def msg(self,content): self._msg = content self.notify() class GCDViewer(object): def __init__(self, name="共军观察者"): self.name = name def update(self, observer_subject): print("共军:收到[%s]消息[%s] "%(observer_subject.name,observer_subject.msg)) class GMDViewer(object): def __init__(self, name="国军观察者"): self.name = name def update(self, observer_subject): print("国军:收到[%s]消息[%s] " % (observer_subject.name,observer_subject.msg)) def main(): observer1 = Observer("共军放哨者") observer2 = Observer("国军放哨者") gongjun1 = GCDViewer() guojun1 = GMDViewer() observer1.attach(gongjun1) observer1.attach(guojun1) observer2.attach(guojun1) observer1.msg = "\033[32;1m敌人来了...\033[0m" observer2.msg = "\033[31;1m前方发现敌人,请紧急撤离,不要告诉共军\033[0m" if __name__ == "__main__": main()
1 [共军放哨者]已经将[共军观察者]加入观察队列... 2 [共军放哨者]已经将[国军观察者]加入观察队列... 3 [国军放哨者]已经将[国军观察者]加入观察队列... 4 共军:收到[共军放哨者]消息[敌人来了...] 5 国军:收到[共军放哨者]消息[敌人来了...] 6 国军:收到[国军放哨者]消息[前方发现敌人,请紧急撤离,不要告诉共军]
16.策略模式
一个系统有许多许多类,而区分它们的只是他们直接的行为。 不管什么程序,其目的都是解决问题。而为了解决问题,咱们又须要编写特定的算法。 使用Strategy模式能够总体地替换算法的实现部分。 即旅行的出游方式:选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 实现: 1.对策略对象定义一个公共接口。 2.编写策略类,该类实现了上面的公共接口。 3.在使用策略对象的类中保存一个对策略对象的引用。 4.在使用策略对象的类中,实现对策略对象的set和get方法或者使用构造方法完成赋值。
__author__ = 'Cq' class TravelStrategy(object): def set_sail(self): raise NotImplementedError class AirplaneStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m坐飞机去旅行...\033[0m") class TrainStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m坐火车去旅行...\033[0m") class CarStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m开轿车去旅行...\033[0m") class BicycleStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m骑自行车去旅行...\033[0m") class FootStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m徒步去旅行...\033[0m") class ShipStrategy(TravelStrategy): def set_sail(self): print("\033[32;1m作船去旅行...\033[0m") class TravelManager(object): def __init__(self, travel_strategy): self.travel_strategy = travel_strategy def set_strategy(self, travel_strategy): self.travel_strategy = travel_strategy def travel(self): return self.travel_strategy.set_sail() def main(): travel = TravelManager(AirplaneStrategy()) travel.travel() travel.set_strategy(TrainStrategy()) travel.travel() travel.set_strategy(ShipStrategy()) travel.travel() travel.set_strategy(CarStrategy()) travel.travel() travel.set_strategy(BicycleStrategy()) travel.travel() travel.set_strategy(FootStrategy()) travel.travel() if "__main__" == __name__: main()
1 坐飞机去旅行... 2 坐火车去旅行... 3 作船去旅行... 4 开轿车去旅行... 5 骑自行车去旅行... 6 徒步去旅行...
17.命令模式
一个类在进行工做时会调用本身或是其余类的方法,虽然调用结果会反映在对象的状态中,但并不会留下工做的历史记录
这时,若是咱们有一个类,用来表示“请进行这项工做”的“命令”就会方便不少。
每一项想作的工做就再也不是“方法的调用”这种动态处理了,而是一个表示命令的类的实例,既能够用“物”来表示。
只须要管理这些实例的集合便可,并且还能够随时再次执行过去的命令,或是将多个过去的命令整合为一个新命令并执行
Command模式可应用于
a)整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。
b)调用先后须要对调用参数进行某些处理。
c)调用先后须要进行某些额外处理,好比日志,缓存,记录历史操做等。
Command模式有以下效果:
a)将调用操做的对象和知道如何实现该操做的对象解耦。
b)Command是头等对象。他们能够像其余对象同样被操做和扩展。
c)你可将多个命令装配成一个符合命令。
d)增长新的Command很容易,由于这无需改变现有的类。
__author__ = 'Cq' class Command(object): def execute(self): raise NotImplementedError class MacroCommand(Command): def __init__(self): self.commands = [] def execute(self): for i in self.commands: i.execute() def appends(self, cmd): self.commands.append(cmd) print("命令添加成功") def undo(self): if len(self.commands): self.commands.pop() print("命令删除成功") def clear(self): while len(self.commands): self.commands.pop() print("全部命令清除成功") class RunCommand(Command): def execute(self): print("执行[跑]命令中...") class JumpCommand(Command): def execute(self): print("执行[跳]命令中...") class RollCommand(Command): def execute(self): print("执行[滚]命令中...") def main(): execs = MacroCommand() execs.appends(RunCommand()) execs.execute() print("\n") execs.appends(JumpCommand()) execs.appends(RollCommand()) execs.execute() print("\n") execs.undo() execs.execute() print("\n") execs.clear() execs.execute() if "__main__" == __name__: main()
1 命令添加成功 2 执行[跑]命令中... 3 4 5 命令添加成功 6 命令添加成功 7 执行[跑]命令中... 8 执行[跳]命令中... 9 执行[滚]命令中... 10 11 12 命令删除成功 13 执行[跑]命令中... 14 执行[跳]命令中... 15 16 17 全部命令清除成功
18.访问者模式
在数据结构中保存着许多元素,咱们会对这些元素进行“处理”。这时,“处理”代码放在哪里比较好呢?一般的作法是将它们放在表示数据结构的类中。
可是,若是“处理”有许多种?这种状况下,每当增长一种处理,咱们就不得不去修改表示数据结构的类。
在Visitor模式中,数据结构与处理被分离开来。咱们编写一个表示“访问者”的类来访问数据结构中的元素,并把对各元素的处理交给访问者类。
这样,当须要增长新的处理时,咱们只须要编写新的访问者,而后让数据结构能够接受访问者的访问便可。
__author__ = 'Cq' class Visitor(object): def visit(self, file_or_dir): raise NotImplementedError class Element(object): def accept(self, visitor): raise NotImplementedError class Entry(Element): def getName(self): raise NotImplementedError def getSize(self): raise NotImplementedError def add(self, entry): pass def __str__(self): return self.getName() + " (" + str(self.getSize()) + ")" class File(Entry): def __init__(self, name, size): self.name = name self.size = size def getName(self): return self.name def getSize(self): return self.size def accept(self, visitor): visitor.visit(self) class Directory(Entry): def __init__(self, name): self.name = name self.dirs = [] self.index = -1 def getName(self): return self.name def getSize(self): size = 0 for i in self.dirs: size += i.getSize() return size def add(self, entry): self.dirs.append(entry) return self def __iter__(self): return self def __next__(self): if len(self.dirs) - 1 == self.index: self.index = -1 raise StopIteration else: self.index += 1 return self.dirs[self.index] def accept(self, visitor): visitor.visit(self) class ListVisitor(Visitor): currentdir = "" def visit(self, file_or_dir): if isinstance(file_or_dir, File): print(self.currentdir + "/", file_or_dir, sep="") else: print(self.currentdir + "/", file_or_dir, sep="") savedir = self.currentdir self.currentdir += "/" + file_or_dir.getName() for ever_dir in file_or_dir: ever_dir.accept(self) self.currentdir = savedir def main(): print("Making root entries...") root_dir = Directory("root") bin_dir = Directory("bin") tmp_dir = Directory("tmp") usr_dir = Directory("usr") root_dir.add(bin_dir) root_dir.add(tmp_dir) root_dir.add(usr_dir) bin_dir.add(File("file1", 10000)) bin_dir.add(File("file2", 10000)) root_dir.accept(ListVisitor()) print("\n") print("Making root entries...") taobao_dir = Directory("taobao") jingdong_dir = Directory("jingdong") tianmao_dir = Directory("tianmao") usr_dir.add(taobao_dir) usr_dir.add(jingdong_dir) usr_dir.add(tianmao_dir) taobao_dir.add(File("file3.java", 100)) taobao_dir.add(File("file4.php", 200)) jingdong_dir.add(File("file5.go", 400)) jingdong_dir.add(File("file6.sh", 600)) tianmao_dir.add(File("file7.c", 700)) root_dir.accept(ListVisitor()) if "__main__" == __name__: main()
1 Making root entries... 2 /root (20000) 3 /root/bin (20000) 4 /root/bin/file1 (10000) 5 /root/bin/file2 (10000) 6 /root/tmp (0) 7 /root/usr (0) 8 9 10 Making root entries... 11 /root (22000) 12 /root/bin (20000) 13 /root/bin/file1 (10000) 14 /root/bin/file2 (10000) 15 /root/tmp (0) 16 /root/usr (2000) 17 /root/usr/taobao (300) 18 /root/usr/taobao/file3.java (100) 19 /root/usr/taobao/file4.php (200) 20 /root/usr/jingdong (1000) 21 /root/usr/jingdong/file5.go (400) 22 /root/usr/jingdong/file6.sh (600) 23 /root/usr/tianmao (700) 24 /root/usr/tianmao/file7.c (700)
19.仲裁者模式
Mediator的意思是“冲裁者”、“中介者”。一方面,当发生麻烦事情的时候,通知仲裁者;当发生涉及全体组员的事情时,也通知仲裁者。当仲裁者下达指示时,组员当即执行。
团队组员之间再也不互相共同并私自作出决定,而是发生任何事情都向仲裁者报告。另外一方面,仲裁者站在整个团队的角度上对组员上报的事情作出决定。这就是Mediator模式。
重要角色:
Mediator 仲裁者
Colleague 组员
__author__ = 'Cq' ''' 本例子使用博物馆经过门禁案例,描述仲裁者模式 工做人员想要进入博物馆首先要在大门口刷门禁卡才能进入, 其次想要进入楼宇内要在一楼门禁刷门禁卡,可是,必须再刷过大门口的门禁后,该门禁才能刷卡经过。 然后进入各个楼层的藏物展览厅内,要在展览厅门口刷门禁,可是,前提是大门口门禁刷过而且楼宇门禁也刷过,该门禁才能刷卡经过 可见个个门禁间有依赖关系,前一个门禁影响后一个门禁,若是咱们在门禁间单首创建关联函数,至少要维护n-1个关系 如今门禁数量只有3个,若是之后要扩展呢?n-1个关联函数都必需要重写,是否是很麻烦? 这个时候引用仲裁者模式尤其重要! ''' class Mediator(object): ''' 仲裁者抽象类 ''' def addColleagues(self, colleague): raise NotImplementedError def colleagueChange(self, colleague): raise NotImplementedError class Colleague(object): ''' 组员抽象类 ''' def setMediator(self, mediator): raise NotImplementedError def setColleagueAllowable(self, boolean): raise NotImplementedError class ColleagueGate(Colleague): ''' 组员:大门 ''' def __init__(self, mediator=None): self.mediator = mediator self.allowable = False def setMediator(self, mediator): self.mediator = mediator def setColleagueAllowable(self, boolean): self.allowable = boolean self.mediator.colleagueChange(self) return self.mediator.permit(self) class ColleagueEntrance(Colleague): ''' 组员:楼宇门 ''' def __init__(self, mediator=None): self.mediator = mediator self.allowable = False def setMediator(self, mediator): self.mediator = mediator def setColleagueAllowable(self, boolean): self.allowable = boolean self.mediator.colleagueChange(self) return self.mediator.permit(self) class ColleagueDoor(Colleague): ''' 组员:展览厅门 ''' def __init__(self, mediator=None): self.mediator = mediator self.allowable = False def setMediator(self, mediator): self.mediator = mediator def setColleagueAllowable(self, boolean): self.allowable = boolean self.mediator.colleagueChange(self) return self.mediator.permit(self) class MediatorEntrance(Mediator): ''' 仲裁者类 ''' def __init__(self): self.allows = {} def addColleagues(self, colleague): colleague.setMediator(self) self.allows[colleague.__class__] = [len(self.allows) + 1] self.allows[colleague.__class__].append(False) def colleagueChange(self, colleague): ''' 接收组员的变化信息,并处理 :param colleague: :return: ''' ''' :param colleague: :return: ''' self.allows[colleague.__class__][1] = colleague.allowable def permit(self, colleague): ''' 反馈给组员信息 :param colleague: :return: True or False ''' per = True for k in self.allows.values(): if k[0] < self.allows[colleague.__class__][0]: if not k[1]: per = False return per def restore(self): for i in self.allows.values(): i[1] = False def main(): med = MediatorEntrance() gate = ColleagueGate() entrance = ColleagueEntrance() door = ColleagueDoor() med.addColleagues(gate) med.addColleagues(entrance) med.addColleagues(door) print("工做者进入大门") print("\033[32;1m>>", gate.setColleagueAllowable(True), "\033[0m") print("工做者进入楼宇门") print("\033[32;1m>>", entrance.setColleagueAllowable(True), "\033[0m") print("工做者进入展览厅门") print("\033[32;1m>>", door.setColleagueAllowable(True), "\033[0m") # 还原门禁 med.restore() print("偷窃者翻过围墙进入庭院") print("偷窃者使用偷来的门禁刷楼宇门") print("\033[31;1m>>", entrance.setColleagueAllowable(True), "\033[0m") # 还原门禁 med.restore() print("偷窃者翻过围墙进入庭院") print("偷窃者爬入楼宇进入楼层走道") print("偷窃者使用偷来的门禁刷楼宇门") print("\033[31;1m>>", entrance.setColleagueAllowable(True), "\033[0m") if "__main__" == __name__: main()
1 工做者进入大门 2 >> True 3 工做者进入楼宇门 4 >> True 5 工做者进入展览厅门 6 >> True 7 偷窃者翻过围墙进入庭院 8 偷窃者使用偷来的门禁刷楼宇门 9 >> False 10 偷窃者翻过围墙进入庭院 11 偷窃者爬入楼宇进入楼层走道 12 偷窃者使用偷来的门禁刷楼宇门 13 >> False
20.忘备录模式
咱们在使用文本比编辑器编写文本时,若是不当心删除了某句话,能够经过撤销(undo)功能将文件恢复至以前的状态。有些文本编辑器甚至支持屡次撤销,可以恢复至好久以前的版本。
使用面向对象编程的方式实现撤销功能时,须要事先保存实例的相关状态信息。而后,在撤销是,还须要根据所保存的信息将实例恢复至原来的状态。
想要恢复实例,须要一个能够自由访问实例内部结构的权限。可是,若是稍有不注意,又可能会将依赖于实例内部结构的代码分散地编写在程序中的各个地方,致使程序变得难以维护。这种状况就叫做“破坏了封装性”。
经过引入表示实例状态的角色,能够在保存和恢复实例时有效地防止对象的封装性遭到破坏。
__author__ = 'Cq' import random class Memento(object): ''' 游戏角色存档类 ''' def __init__(self, money, killed, hp, gnum): self.money = money self.killed = killed self.hp = hp self.gnum = gnum def changeKilled(self, count): self.killed = count def changeHP(self, count): self.hp = count def changeMoney(self, count): self.money = count def changeGameNum(self, count): self.gnum = count class Gamer(object): ''' 游戏角色类 ''' def __init__(self, money, killed=0, hp=100, gnum=1): self.__money = money self.__killed = killed self.__hp = hp self.__gnum = gnum self.__memento = [] def getMoney(self): return self.__money def getKilled(self): return self.__killed def getHP(self): return self.__hp def getGameNum(self): return self.__gnum def through(self): self.__gnum += 1 money = random.randint(10, 100) killed = random.randint(20, 50) print("\033[32;1m经过关卡,金钱+%s\033[0m" % money) self.__money += money print("\033[32;1m经过关卡,消灭敌人%s\033[0m" % killed) self.__killed += killed def lossHP(self): _hp = random.randint(0, 20) print("损失生命值:%s" % _hp) self.__hp -= _hp self.isDie() def isDie(self): if self.__hp <= 0: self.gameOver() else: self.through() def gameOver(self): print("\033[31;1m人物死亡,通关失败\033[0m") self.__hp = 0 def startGame(self): if self.__hp == 0: print("游戏角色死亡,请从新开始游戏或者读取存档") self.restoreMemento() return else: res = random.randint(0, 10) if res <= 2: self.gameOver() else: self.lossHP() def createMemento(self): self.__memento.append(Memento(self.__money, self.__killed, self.__hp, self.__gnum)) def restoreMemento(self): print("读取存档...") self.__money = self.__memento[-1].money self.__killed = self.__memento[-1].killed self.__hp = self.__memento[-1].hp self.__gnum = self.__memento[-1].gnum def __str__(self): return "[游戏角色] 金钱数:%s 消灭敌人数:%s 已经过关卡:%s 当前血量:%s" % (self.__money, self.__killed, self.__gnum, self.__hp) def main(): print("建立游戏角色") role = Gamer(0) print("存档中...") m_list = [] m_list.append(role.createMemento()) print("开始游戏") for i in range(5): role.startGame() print(role) print("**************************************") if '__main__' == __name__: main()
1 建立游戏角色 2 存档中... 3 开始游戏 4 损失生命值:13 5 经过关卡,金钱+56 6 经过关卡,消灭敌人43 7 [游戏角色] 金钱数:56 消灭敌人数:43 已经过关卡:2 当前血量:87 8 ************************************** 9 损失生命值:3 10 经过关卡,金钱+23 11 经过关卡,消灭敌人23 12 [游戏角色] 金钱数:79 消灭敌人数:66 已经过关卡:3 当前血量:84 13 ************************************** 14 人物死亡,通关失败 15 [游戏角色] 金钱数:79 消灭敌人数:66 已经过关卡:3 当前血量:0 16 ************************************** 17 游戏角色死亡,请从新开始游戏或者读取存档 18 读取存档... 19 [游戏角色] 金钱数:0 消灭敌人数:0 已经过关卡:1 当前血量:100 20 ************************************** 21 损失生命值:4 22 经过关卡,金钱+47 23 经过关卡,消灭敌人25 24 [游戏角色] 金钱数:47 消灭敌人数:25 已经过关卡:2 当前血量:96 25 **************************************
21.状态模式
在State模式中,使用类来表示状态。State的意思就是“状态”。经过切换类来方便地改变对象的状态。
当须要增长新的状态时,修改代码也很方便,须要添加新的类就行了。
__author__ = 'Cq' ''' 该实例以银行金库报警系统为例子 有一个金库,金库与警报中心相连,金库里有警铃和正常通话用的电话,金库里有时钟(监视当前时间) 金库只能在白天使用,白天使用金库的话,会在报警中心留下记录,晚上使用会向报警中心发送紧急事态通知 任什么时候候均可以使用警铃向报警中心发送紧急事态通知 任什么时候候均可以使用电话,白天使用会呼叫报警中心,晚上使用只能向报警中心留言 ''' class State(object): ''' 白天或晚上的状态抽象类 ''' def __new__(cls, *args, **kwargs): ''' 因为状态只有一种,不须要不少想用的状态,这里使用单例模式的方法 只使用一个实例化对象 ''' if not hasattr(cls, '_instance'): cls._instance = super(State, cls).__new__(cls) return cls._instance def doClock(self, context, hour): raise NotImplementedError def doUse(self): raise NotImplementedError def doAlarm(self): raise NotImplementedError def doPhone(self): raise NotImplementedError class DayState(State): ''' 状态:白天 ''' def doClock(self, context, hour): if hour < 9 or 17 <= hour: context.changeState(NightState()) def doUse(self): print("\033[32;1m使用金库(白天)\033[0m") def doAlarm(self): print("\033[32;1m按下警铃(白天)\033[0m") def doPhone(self): print("\033[32;1m正常通话(白天)\033[0m") def __str__(self): return "[白天]" class NightState(State): ''' 状态:晚上 ''' def doClock(self, context, hour): if 9 <= hour and hour < 17: context.changeState(DayState()) def doUse(self): print("\033[31;1m紧急:晚上使用金库\033[0m") def doAlarm(self): print("\033[31;1m按下警铃(晚上)\033[0m") def doPhone(self): print("\033[31;1m晚上的通话录音\033[0m") def __str__(self): return "[晚上]" class Context(object): ''' 负责管理状态和联系报警中心的接口 ''' def setClock(self, hour): raise NotImplementedError def changeState(self, state): raise NotImplementedError def callSecurityCenter(self, msg): raise NotImplementedError def recordLog(self, msg): raise NotImplementedError class ContetApi(Context): ''' 实现Context接口 ''' def __init__(self): self.state = NightState() self.textScreen = [] def setClock(self, hour): if hour < 10: print("如今的时间是", "0"+str(hour)+":00") else: print("如今的时间是", str(hour)+":00") self.state.doClock(self, hour) def changeState(self, state): print("从", self.state, "状态变为了", state, "状态。", sep="") self.state = state def callSecurityCenter(self, msg): self.textScreen.append("call! "+msg+"\n") def recordLog(self, msg): self.textScreen.append("record ... "+msg+"\n") def main(): context = ContetApi() for hour in range(24): context.setClock(hour) if hour == 2 or hour == 23: print("-----------------------") context.state.doUse() context.callSecurityCenter("%sH 金库被抢了" % hour) context.state.doAlarm() context.callSecurityCenter("%sH 警报自动拉响" % hour) context.state.doPhone() context.recordLog('%sH 很差了金库被炸开了!呼叫支援' % hour) print("-----------------------") if hour == 12: print("-----------------------") context.state.doUse() context.callSecurityCenter("%sH 金库使用中" % hour) context.state.doAlarm() context.callSecurityCenter("%sH 警报被拉响" % hour) context.state.doPhone() context.recordLog('%sH 有人抢劫银行呼叫支援' % hour) print("-----------------------") print("今天的警报中心记录") print(context.textScreen) if "__main__" == __name__: main()
1 如今的时间是 00:00 2 如今的时间是 01:00 3 如今的时间是 02:00 4 ----------------------- 5 紧急:晚上使用金库 6 按下警铃(晚上) 7 晚上的通话录音 8 ----------------------- 9 如今的时间是 03:00 10 如今的时间是 04:00 11 如今的时间是 05:00 12 如今的时间是 06:00 13 如今的时间是 07:00 14 如今的时间是 08:00 15 如今的时间是 09:00 16 从[晚上]状态变为了[白天]状态。 17 如今的时间是 10:00 18 如今的时间是 11:00 19 如今的时间是 12:00 20 ----------------------- 21 使用金库(白天) 22 按下警铃(白天) 23 正常通话(白天) 24 ----------------------- 25 如今的时间是 13:00 26 如今的时间是 14:00 27 如今的时间是 15:00 28 如今的时间是 16:00 29 如今的时间是 17:00 30 从[白天]状态变为了[晚上]状态。 31 如今的时间是 18:00 32 如今的时间是 19:00 33 如今的时间是 20:00 34 如今的时间是 21:00 35 如今的时间是 22:00 36 如今的时间是 23:00 37 ----------------------- 38 紧急:晚上使用金库 39 按下警铃(晚上) 40 晚上的通话录音 41 ----------------------- 42 今天的警报中心记录 43 ['call! 2H 金库被抢了\n', 'call! 2H 警报自动拉响\n', 'record ... 2H 很差了金库被炸开了!呼叫支援\n', 'call! 12H 金库使用中\n', 'call! 12H 警报被拉响\n', 'record ... 12H 有人抢劫银行呼叫支援\n', 'call! 23H 金库被抢了\n', 'call! 23H 警报自动拉响\n', 'record ... 23H 很差了金库被炸开了!呼叫支援\n']
22.迭代器模式
Iterator模式用于在数据集合中按照顺序遍历集合。
使用该模式最重要的理由是,将遍历与实现分离开来,进而自定制遍历方法
__author__ = 'Cq' class Aggregate(object): ''' 表示集合的接口 ''' def iterator(self): raise NotImplementedError class Iterator(object): ''' 遍历集合的接口 ''' def hasNext(self): raise NotImplementedError def next(self): raise NotImplementedError class Book(object): ''' 表示书的类 ''' def __init__(self, name): self.name = name def getName(self): return self.name class BookShelf(Aggregate): ''' 表示书架的类,用于存放书 ''' def __init__(self, max_size): self.max = max_size self.books = [None for i in range(self.max)] self.last = 0 def getBookAt(self, index): return self.books[index] def appendBook(self, book): self.books[self.last] = book self.last += 1 def getLength(self): return self.last def iterator(self): return BookShelfIterator(self) class BookShelfIterator(Iterator): ''' 遍历书架的类 ''' def __init__(self, bookShelf): self.__bookShelf = bookShelf self.__index = 0 def hasNext(self): if self.__index < self.__bookShelf.getLength(): return True else: return False def next(self): book = self.__bookShelf.getBookAt(self.__index) self.__index += 1 return book def main(): # 实例化一个书架,大小为10本书 bookShelf = BookShelf(10) bookShelf.appendBook(Book("《C语言从研发到脱发》")) bookShelf.appendBook(Book("《C++从入门到放弃》")) bookShelf.appendBook(Book("《Java从跨平台到跨行业》")) bookShelf.appendBook(Book("《Ios开发从入门到下架》")) bookShelf.appendBook(Book("《Android开发大全--从开始到转行》")) bookShelf.appendBook(Book("《PHP由初学至搬砖》")) bookShelf.appendBook(Book("《黑客攻防:从入门到入狱》")) bookShelf.appendBook(Book("《MySql从删库到跑路》")) bookShelf.appendBook(Book("《服务器运维管理从网络异常到硬盘全红》")) bookShelf.appendBook(Book("《服务器运维管理从网维到网管》")) it = bookShelf.iterator() while it.hasNext(): book = it.next() print(book.getName()) if '__main__' == __name__: main()
1 《C语言从研发到脱发》 2 《C++从入门到放弃》 3 《Java从跨平台到跨行业》 4 《Ios开发从入门到下架》 5 《Android开发大全--从开始到转行》 6 《PHP由初学至搬砖》 7 《黑客攻防:从入门到入狱》 8 《MySql从删库到跑路》 9 《服务器运维管理从网络异常到硬盘全红》 10 《服务器运维管理从网维到网管》
23.解释器模式
在Interpreter模式中,程序要解决的问题会被用很是简单的“迷你语言”表述出来,即用“迷你语言”编写的“迷你程序”把具体的问题表述出来。 迷你程序是没法单独工做的,咱们还须要用编程语言编写一个负责“编译”的程序。 翻译程序会理解迷你语言,并解释和运行迷你程序,这段翻译程序也被称为解释器。 遥控汽车运动为例: go 为前行1米 right 为原地向右转弯90° left 为原地向左转弯90° 迷你语言程序示例 program go end 小车前行1米中止 program go right right go end 小车前行1米,而后右转两次,前行1米中止 轨迹为边长为1米的正方形 program repeat 4 go right end end 轨迹为锯齿状 program repeat 4 repeat 3 go right go left end end end 解释器中解释器须要解释的迷你语言语法 <program> ::= program <command list> <command list> ::= <command>* end <command> ::= <repeat command> | <primitive command> <repeat command> ::= repeat <number> <command list> <primitive command> ::= go | right | left
__author__ = 'Cq' ''' 经过编写一段迷你程序的解释器实现解释器模式 如下是命令解释: <program> ::= program <command list> <program>是程序定义字符 program关键字后面跟着的命令列表<command list> ::= 的左边表示定义的名字,右边表示定义的内容 <command list> ::= <command>* end <command list>是指重复0次以上<command>后,接着一个end关键字 '*'表示前面的内容循环0次以上 <command> ::= <repeat command> | <primitive command> <command>是指<repeat command>或<primitive command> <repeat command> ::= repeat <number><command list> <repeat command>是指repeat关键字后面跟着循环次数和循环命令列表 <command>中能够出现<command list>,反之也能够出现,这称为递归定义 <primitive command> 它指go或right或left <number> 即重复次数,天然数 ''' import sys import re class Node(object): ''' 表示语法树“节点”的类 ''' def parse(self, context): raise NotImplementedError class ProgramNode(Node): ''' 对应处理<program>的类 ''' def __init__(self): self.commandListNode = None def parse(self, context): context.skipToken("program") self.commandListNode = CommandListNode() self.commandListNode.parse(context) def __str__(self): return "[ program "+self.commandListNode.__str__()+"]" class CommandListNode(Node): ''' 对应处理<command list>的类 ''' def __init__(self): self.list1 = [] def parse(self, context): while True: if context.currentToken() == None: print("Missing 'end'") sys.exit(0) elif context.currentToken() == "end": context.skipToken("end") break else: commandNode = CommandNode() commandNode.parse(context) self.list1.append(commandNode) def __str__(self): string = "" for node in self.list1: string += node.node.__str__() return string class CommandNode(Node): ''' 对应处理<command>的类 ''' def __init__(self): self.node = None def parse(self, context): if context.currentToken() == "repeat": self.node = RepeatCommandNode() self.node.parse(context) else: self.node = PrimitiveCommandNode() self.node.parse(context) def __str__(self): return self.node class RepeatCommandNode(Node): ''' 对应处理<repeat command>的类 ''' def __init__(self): self.number = None self.commandListNode = None def parse(self, context): context.skipToken("repeat") self.number = context.currentNumber() context.nextToken() self.commandListNode = CommandListNode() self.commandListNode.parse(context) def __str__(self): return "[ repeat "+str(self.number)+" "+self.commandListNode.__str__()+"] " class PrimitiveCommandNode(Node): ''' 对应处理<primitive command>的类 ''' def __init__(self): self.name = None def parse(self, context): self.name = context.currentToken() context.skipToken(self.name) if self.name != "go" and self.name != "right" and self.name != "left": print(self.name, "is undefined") def __str__(self): return self.name+" " class Context(object): def __init__(self, text, index=0): self.__currentToken = None # 存放当前命令名例:program self.__tokenizer = text # 存放整条迷你命令例:program end self.index = index # 当前获取到第几条命令例:program end 若是当前获取到end,则index=2 self.nextToken() def nextToken(self): if self.hasMoreToken(self.__tokenizer): self.__currentToken = self.getNextToken(self.__tokenizer) else: self.__currentToken = None return self.__currentToken def hasMoreToken(self, tokenizer): res = False find_list = re.findall("(\w*?\s)", tokenizer) if self.index < len(find_list): res = True return res def getNextToken(self, tokenizer): find_list = re.findall("(\w*?\s)", tokenizer) res = find_list[self.index] temp = list(res) res = "".join(temp[0:-1]) self.index += 1 return res def currentToken(self): return self.__currentToken def skipToken(self, token): if token != self.__currentToken: print("Warning: "+token+" is expected,but ", self.__currentToken, " is found.") sys.exit(0) self.nextToken() def currentNumber(self): number = 0 try: number = int(self.__currentToken) except Exception as e: print("Warning: ", e) return number def main(): file = open("program.txt", 'r') for i in file.readlines(): print("text = ", i) node = ProgramNode() node.parse(Context(i)) print("node =", node) print("--------------------") file.close() if '__main__' == __name__: main()
1 text = program end 2 3 node = [ program ] 4 -------------------- 5 text = program go end 6 7 node = [ program go ] 8 -------------------- 9 text = program go right go right go right go right end 10 11 node = [ program go right go right go right go right ] 12 -------------------- 13 text = program repeat 4 go right end end 14 15 node = [ program [ repeat 4 go right ] ] 16 -------------------- 17 text = program repeat 4 repeat 3 go right go left end right end end 18 19 node = [ program [ repeat 4 [ repeat 3 go right go left ] right ] ] 20 --------------------
参考书籍:《图解设计模式》
参考博客:http://www.cnblogs.com/alex3714/articles/5760582.html