1.设计模式概述
1.设计模式代表了一种最佳的实践,是被开发人员长期总结,用来解决某一类问题的思路方法,这些方法保证了代码的效率也易于理解
2.设计模式类型:根据23种设计模式可以分为三大类
创建型模式(Creational Patterns):
简单工厂模式,工厂模式,抽象工厂模式,原型模式,建造者模式,单例模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象
这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活
结构型模式(Structural Patterns):
装饰器模式,适配器模式,门面模式,组合模式,享元模式,桥梁模式,代理模式
这些设计模式关注类和对象的组合,继承的概念被用来组合接口和定义组合对象获得新功能的方式
行为型模式(Behavioral Patterns):
策略模式,责任链模式,命令模式,中介者模式,模板模式,迭代器模式,
访问者模式,观察者模式,解释器模式,备忘录模式,状态模式
这些设计模式特别关注对象之间的通信
3.设计模式的六大原则
1.开闭原则(Open Close Principle)
这个原则的意思是: 对扩展开放,对修改关闭,在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果
即: 是为了使程序的扩展性好,易于维护和升级,想要达到这样的效果,我们需要使用接口和抽象类
2.里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一,里氏代换原则中说任何基类可以出现的地方,子类一定可以出现
LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用
而派生类也能够在基类的基础上增加新的行为,里氏代换原则是对开闭原则的补充
实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范
3.依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容: 针对接口编程,依赖于抽象而不依赖于具体
4.接口隔离原则(Interface Segregation Principle)
这个原则的意思是: 使用多个隔离的接口,比使用单个接口要好
另外一个意思是: 降低类之间的耦合度,其实设计模式就是从大型软件架构出发,便于升级和维护的软件设计思想它强调降低依赖,降低耦合
5.迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指: 一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立
6.合成复用原则(Composite Reuse Principle)
合成复用原则是指: 尽量使用合成/聚合的方式,而不是使用继承
4.Python设计模式参考自如下链接
https://yq.aliyun.com/topic/122
https://www.cnblogs.com/alex3714/articles/5760582.html
2.创建型模式
1.简单工厂模式(Simple Factory Pattern)
1.概述: 省去了将工厂实例化的过程,用一个简单的工厂类,来统一的提供给用户调用,根据用户提供的信息返回创建的实例
2.简单工厂模式流程图: https://www.processon.com/view/link/5f155e85e401fd2e0defe767
3.示例1:图形绘制
class Shape: """抽象形状类""" def draw(self): raise NotImplementedError class Circle(Shape): """圆形类""" def draw(self): print("画圆形") class Rectangle(Shape): """四边形类""" def draw(self): print("画四边形") class ShapeFactory: """简单工厂类""" @classmethod def create(cls, shape): if shape == 'Circle': return Circle() elif shape == 'Rectangle': return Rectangle() else: return None if __name__ == '__main__': # 创建一个简单工厂实例 fac = ShapeFactory() # 使用工厂实例创建Circle对象 obj = fac.create('Circle') # 调用对象中的draw方法 obj.draw() # 画圆形
4.示例2: 快餐点餐系统
class Burger: """抽象汉堡类""" name = "" price = 0.0 def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class cheeseBurger(Burger): """起司汉堡类""" def __init__(self): self.name = "cheese burger" self.price = 10.0 class spicyChickenBurger(Burger): """辣鸡肉汉堡类""" def __init__(self): self.name = "spicy chicken burger" self.price = 15.0 class Snack: """抽象小吃基类""" name = "" price = 0.0 type = "SNACK" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class chips(Snack): """零碎类""" def __init__(self): self.name = "chips" self.price = 6.0 class chickenWings(Snack): """鸡翅类""" def __init__(self): self.name = "chicken wings" self.price = 12.0 class Beverage: """抽象饮料类""" name = "" price = 0.0 type = "BEVERAGE" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class coke(Beverage): """可乐类""" def __init__(self): self.name = "coke" self.price = 4.0 class milk(Beverage): """牛奶类""" def __init__(self): self.name = "milk" self.price = 5.0 class simpleFoodFactory(): """抽象简单工厂类""" @classmethod def createFood(cls, foodClass): print("Simple factory produce a instance.") foodIns = foodClass() return foodIns class burgerFactory(simpleFoodFactory): """汉堡工厂类""" def __init__(self): self.type = "BURGER" class snackFactory(simpleFoodFactory): """小吃工厂类""" def __init__(self): self.type = "SNACK" class beverageFactory(simpleFoodFactory): """饮料工厂类""" def __init__(self): self.type = "BEVERAGE" if __name__ == "__main__": # 工厂实例化 # burger_factory = burgerFactory() # snack_factorry = snackFactory() # beverage_factory = beverageFactory() # 实例调用 # cheese_burger = burger_factory.createFood(cheeseBurger) # print(cheese_burger.getName(), cheese_burger.getPrice()) # chicken_wings = snack_factorry.createFood(chickenWings) # print(chicken_wings.getName(), chicken_wings.getPrice()) # coke_drink = beverage_factory.createFood(coke) # print(coke_drink.getName(), coke_drink.getPrice()) # 省去了将工厂实例化的过程 spicy_chicken_burger = simpleFoodFactory.createFood(spicyChickenBurger) print(spicy_chicken_burger.getName(), spicy_chicken_burger.getPrice()) """执行结果 Simple factory produce a instance. spicy chicken burger 15.0 """
2.工厂模式(Factory Pattern)
1.概述: 定义一个用于创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化延迟到其子类,工厂在使用前必须实例化
2.工厂模式流程图: https://www.processon.com/view/link/5f1533aa07912906d9ae82d0
3.示例1:图形绘制
# 形状基类,所有形状子类继承于该类 class Shape: """抽象形状类""" def getShape(self): return self.shape_name def draw(self): raise NotImplementedError class Circle(Shape): """圆形类""" def __init__(self): self.shape_name = "Circle" def draw(self): print("画圆形") class Rectangle(Shape): """四边形类""" def __init__(self): self.shape_name = "Retangle" def draw(self): print("画四边形") # 形状工厂的基类,所有形状工厂继承于该类 class ShapeFactory: """抽象形状工厂类""" def create(self): """把要创建的工厂对象装配进来""" raise NotImplementedError class CircleFactory(ShapeFactory): """圆形工厂类""" def create(self): return Circle() class RectangleFactory(ShapeFactory): """四边形工厂类""" def create(self): return Rectangle() # 创建一个圆形工厂实例 cf = CircleFactory() # 使用圆形工厂产生圆形对象 obj = cf.create() # 调用圆形对象的shape_name print(obj.getShape()) # Circle # 调用圆形对象的draw方法 obj.draw() # 画圆形 # 创建一个四边形工厂实例 rf = RectangleFactory() obj2 = rf.create() print(obj2.getShape()) # Retangle obj2.draw() # 画四边形
4.示例2: 快餐点餐系统
class Burger: """抽象汉堡类""" name = "" price = 0.0 def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class cheeseBurger(Burger): """起司汉堡类""" def __init__(self): self.name = "cheese burger" self.price = 10.0 class spicyChickenBurger(Burger): """辣鸡肉汉堡类""" def __init__(self): self.name = "spicy chicken burger" self.price = 15.0 class Snack: """抽象小吃类""" name = "" price = 0.0 type = "SNACK" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class chips(Snack): """零碎类""" def __init__(self): self.name = "chips" self.price = 6.0 class chickenWings(Snack): """鸡翅类""" def __init__(self): self.name = "chicken wings" self.price = 12.0 class Beverage: """抽象饮料基类""" name = "" price = 0.0 type = "BEVERAGE" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class coke(Beverage): """可乐类""" def __init__(self): self.name = "coke" self.price = 4.0 class milk(Beverage): """牛奶类""" def __init__(self): self.name = "milk" self.price = 5.0 class foodFactory: """抽象工厂基类""" type = "" def createFood(self, foodClass): print(self.type, " factory produce a instance.") foodIns = foodClass() return foodIns class burgerFactory(foodFactory): """汉堡工厂类""" def __init__(self): self.type = "BURGER" class snackFactory(foodFactory): """小吃工厂类""" def __init__(self): self.type = "SNACK" class beverageFactory(foodFactory): """饮料工厂类""" def __init__(self): self.type = "BEVERAGE" if __name__ == "__main__": # 工厂实例化 burger_factory = burgerFactory() snack_factorry = snackFactory() beverage_factory = beverageFactory() # 实例调用 cheese_burger = burger_factory.createFood(cheeseBurger) print(cheese_burger.getName(), cheese_burger.getPrice()) chicken_wings = snack_factorry.createFood(chickenWings) print(chicken_wings.getName(), chicken_wings.getPrice()) coke_drink = beverage_factory.createFood(coke) print(coke_drink.getName(), coke_drink.getPrice()) """执行结果 BURGER factory produce a instance. cheese burger 10.0 SNACK factory produce a instance. chicken wings 12.0 BEVERAGE factory produce a instance. coke 4.0 """
3.抽象工厂模式(Abstract Factory Pattern)
1.概述: 一个配置类是对具体工厂的一层抽象,完成与各类产品的基类关联
2.抽象工厂模式流程图: https://www.processon.com/view/link/5f1552386376895d7fbab22a
3.示例: 组装电脑
class AbstractFactory: """抽象工厂类(配置类)""" computer_name = '' def createCpu(self): pass def createMainboard(self): pass class IntelFactory(AbstractFactory): """Intel配置类(CPU和主板都使用Intel的配置)""" computer_name = 'Intel I7-series computer ' def createCpu(self): return IntelCpu('I7-6500') def createMainboard(self): return IntelMainBoard('Intel-6000') class AmdFactory(AbstractFactory): """Amd配置类(CPU和主板都使用Amd的配置)""" computer_name = 'Amd 4 computer ' def createCpu(self): return AmdCpu('amd444') def createMainboard(self): return AmdMainBoard('AMD-4000') class AbstractCpu: """抽象CPU类""" series_name = '' instructions = '' arch = '' class IntelCpu(AbstractCpu): """Intel的CPU类""" def __init__(self, series): self.series_name = series class AmdCpu(AbstractCpu): """Amd的CPU类""" def __init__(self, series): self.series_name = series class AbstractMainboard: """抽象主板类""" series_name = '' class IntelMainBoard(AbstractMainboard): """Intel主板类""" def __init__(self, series): self.series_name = series class AmdMainBoard(AbstractMainboard): """Amd主板类""" def __init__(self, series): self.series_name = series class ComputerEngineer: """抽象配置工程师类""" # 使用配置工厂类来创建电脑 def makeComputer(self, computer_obj): self.prepareHardwares(computer_obj) # 准备硬件 def prepareHardwares(self, computer_obj): # 创建配置清单中的CPU self.cpu = computer_obj.createCpu() # 创建配置清单中的主板 self.mainboard = computer_obj.createMainboard() info = """ ------- computer [%s] info: cpu: %s mainboard: %s -------- End -------- """ % (computer_obj.computer_name, self.cpu.series_name, self.mainboard.series_name) print(info) if __name__ == "__main__": # 实例化一个配置工程师实例 engineer = ComputerEngineer() # 实例化Intel配置对象 computer_factory = IntelFactory() # 按Intel配置配一台电脑 engineer.makeComputer(computer_factory) # 实例化AMD配置对象 computer_factory2 = AmdFactory() # 按AMD配置配一台电脑 engineer.makeComputer(computer_factory2) """执行结果 ------- computer [Intel I7-series computer ] info: cpu: I7-6500 mainboard: Intel-6000 -------- End -------- ------- computer [Amd 4 computer ] info: cpu: amd444 mainboard: AMD-4000 -------- End -------- """
4.原型模式(Prototype Pattern)
1.概述: 用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象,即浅拷贝和深拷贝的运用
2.原型模式流程图: https://www.processon.com/view/link/5f15bb795653bb7fd2449bf2
3.示例: 图层
from copy import copy from copy import deepcopy class simpleLayer: """图层类""" background = [0, 0, 0, 0] content = "blank" def getContent(self): return self.content def getBackgroud(self): return self.background def paint(self, painting): self.content = painting def setParent(self, p): self.background[3] = p def fillBackground(self, back): self.background = back def clone(self): return copy(self) def deep_clone(self): return deepcopy(self) if __name__ == "__main__": dog_layer = simpleLayer() dog_layer.paint("Dog") dog_layer.fillBackground([0, 0, 255, 0]) print("Background:", dog_layer.getBackgroud()) print("Painting:", dog_layer.getContent()) another_dog_layer = dog_layer.clone() # 浅拷贝 print("Background:", another_dog_layer.getBackgroud()) print("Painting:", another_dog_layer.getContent()) """执行结果 Background: [0, 0, 255, 0] Painting: Dog Background: [0, 0, 255, 0] Painting: Dog """
5.建造者模式(Builder Pattern)
1.概述: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,其作用就是将构建和表示分离,以达到解耦的作用
2.建造者模式流程图: https://www.processon.com/view/link/5f1561366376895d7fbb000d
3.示例1: 创造人类
class Person: """抽象产品类(最终产出的东西)""" def __init__(self): self.head = "" self.body = "" self.arm = "" self.leg = "" def getPersonInfo(self): print("Head:" + self.head + " " + "Body:" + self.body + " " + "Arm:" + self.arm + " " + "Leg:" + self.leg) class PersonBuilder: """抽象建造者类""" def BuildHead(self): pass def BuildBody(self): pass def BuildArm(self): pass def BuildLeg(self): pass class PersonFatBuilder(PersonBuilder): """胖子建造者子类""" type = '胖子' def __init__(self): self.person = Person() def BuildHead(self): self.person.head = "构建%s的头" % self.type def BuildBody(self): self.person.body = "构建%s的身体" % self.type def BuildArm(self): self.person.arm = "构建%s的手" % self.type def BuildLeg(self): self.person.leg = "构建%s的腿" % self.type def getPerson(self): return self.person class PersonThinBuilder(PersonBuilder): """瘦子建造者子类""" type = '瘦子' def __init__(self): self.person = Person() def BuildHead(self): self.person.head = "构建%s的头" % self.type def BuildBody(self): self.person.body = "构建%s的身体" % self.type def BuildArm(self): self.person.arm = "构建%s的手" % self.type def BuildLeg(self): self.person.leg = "构建%s的腿" % self.type def getPerson(self): return self.person class PersonDirector: """使用建造者的类(指挥官)""" def __init__(self, pb): self.pb = pb # 调用建造者里的各部位方法来创建一个人 def CreatePereson(self): self.pb.BuildHead() self.pb.BuildBody() self.pb.BuildArm() self.pb.BuildLeg() return self.pb.getPerson() def clientUI(): # 瘦子建造者实例 pb = PersonThinBuilder() # 指挥官类(使用瘦子创建者) pd = PersonDirector(pb) # 创建一个瘦子 created_thin_person = pd.CreatePereson() created_thin_person.getPersonInfo() # 胖子建造者实例 pb = PersonFatBuilder() # 指挥官类(使用胖子创建者) pd = PersonDirector(pb) # 创建一个胖子 created_fat_person = pd.CreatePereson() created_fat_person.getPersonInfo() if __name__ == '__main__': clientUI() """执行结果 Head:构建瘦子的头 Body:构建瘦子的身体 Arm:构建瘦子的手 Leg:构建瘦子的腿 Head:构建胖子的头 Body:构建胖子的身体 Arm:构建胖子的手 Leg:构建胖子的腿 """
4.示例2: 快餐点餐系统
class Burger: """抽象汉堡类""" name = "" price = 0.0 def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class cheeseBurger(Burger): """起司汉堡类""" def __init__(self): self.name = "cheese burger" self.price = 10.0 class spicyChickenBurger(Burger): """辣鸡汉堡类""" def __init__(self): self.name = "spicy chicken burger" self.price = 15.0 class Snack: """抽象小吃类""" name = "" price = 0.0 type = "SNACK" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class chips(Snack): """零碎类""" def __init__(self): self.name = "chips" self.price = 6.0 class chickenWings(Snack): """鸡翅类""" def __init__(self): self.name = "chicken wings" self.price = 12.0 class Beverage: """抽象饮料类""" name = "" price = 0.0 type = "BEVERAGE" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class coke(Beverage): """可乐类""" def __init__(self): self.name = "coke" self.price = 4.0 class milk(Beverage): """牛奶类""" def __init__(self): self.name = "milk" self.price = 5.0 class order: """订单类""" burger = "" snack = "" beverage = "" def __init__(self, orderBuilder): # orderBuilder就是建造者模式中所谓的建造者 self.burger = orderBuilder.bBurger self.snack = orderBuilder.bSnack self.beverage = orderBuilder.bBeverage def show(self): print("Burger:%s" % self.burger.getName()) print("Snack:%s" % self.snack.getName()) print("Beverage:%s" % self.beverage.getName()) class orderBuilder: """建造者类""" bBurger = "" bSnack = "" bBeverage = "" def addBurger(self, xBurger): self.bBurger = xBurger def addSnack(self, xSnack): self.bSnack = xSnack def addBeverage(self, xBeverage): self.bBeverage = xBeverage def build(self): return order(self) if __name__ == "__main__": # 实现订单生成 order_builder = orderBuilder() order_builder.addBurger(spicyChickenBurger()) order_builder.addSnack(chips()) order_builder.addBeverage(milk()) order_1 = order_builder.build() order_1.show() """执行结果 Burger:spicy chicken burger Snack:chips Beverage:milk """
6.单例模式(Singleton Pattern)
1.概述: 保证一个类仅有一个实例可以节省比较多的内存空间,并提供一个访问它的全局访问点可以更好地进行数据同步控制,避免多重占用
2.实现单例-自定义类方法实现
class Foo: instance = None def __init__(self): pass @classmethod def get_instance(cls): if cls.instance: return cls.instance else: cls.instance = cls() return cls.instance def process(self): print("process") if __name__ == '__main__': obj1 = Foo.get_instance() obj2 = Foo.get_instance() print(id(obj1), id(obj2)) # 4411389776 4411389776
3.实现单例-类的构造方法 __new__ 实现
import threading import time # 这里使用方法__new__来实现单例模式 class Singleton: # 抽象单例 def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): orig = super(Singleton, cls) cls._instance = orig.__new__(cls, *args, **kwargs) return cls._instance # 总线 class Bus(Singleton): lock = threading.RLock() def sendData(self, data): self.lock.acquire() time.sleep(3) print("Sending Signal Data...", data) self.lock.release() # 线程对象,为更加说明单例的含义,这里将Bus对象实例化写在了run里 class VisitEntity(threading.Thread): my_bus = "" name = "" def getName(self): return self.name def setName(self, name): self.name = name def run(self): self.my_bus = Bus() self.my_bus.sendData(self.name) if __name__ == "__main__": for i in range(3): print("Entity %d begin to run..." % i) my_entity = VisitEntity() my_entity.setName("Entity_" + str(i)) my_entity.start() """执行结果 Entity 0 begin to run... Entity 1 begin to run... Entity 2 begin to run... Sending Signal Data... Entity_0 Sending Signal Data... Entity_1 Sending Signal Data... Entity_2 """
4.实现单例-基于模块导入机制实现
# 1.原理剖析: 模块只被导入一次,当我们在导入一个模块时,python会编译生成一个pyc文件,这个文件会在模块的第一次导入时生成 # 当pyc存在的时候,例如第二次导入模块,则不会在运行模块中的代码,而是直接使用内存中的pyc,利用这一特性,可以构建单例模型 # 2.在mysingleton模块中,定义了MySingleton类,并获取了一个实例对象 class MySingleton: def foo(self): print("foo...") my_singleton = MySingleton() # 3.在另一个模块中,对mysingleton模块进行导入 # 第一次导入my_singleton from mysingleton import my_singleton # 第二次导入my_singleton from mysingleton import my_singleton as my_singleton_2 print(id(my_singleton)) # 4537674448 print(id(my_singleton_2)) # 4537674448
5.实现单例-装饰器实现
# 实现构建单例对象的装饰器 def singleton(cls, *args, **kwargs): # 一个用于存放单例对象的字典,以类为key,单例对象为value instances = {} def get_instance(*args, **kwargs): # 如果这个类没有创建过对象,则创建对象,作为value存放在字典中 if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance @singleton class Test: def __init__(self, name): self.name = name def get_name(self): return self.name if __name__ == '__main__': t1 = Test("leo1") t2 = Test("leo2") print(t1.get_name()) # leo1 print(t2.get_name()) # leo1 print(id(t1) == id(t2)) # True
3.结构型模式
1.装饰器模式(Decorator Pattern)
1.概述: 动态地给一个对象添加一些额外的职责,在增加功能方面,装饰器模式比生成子类更为灵活
2.示例: 快餐点餐系统
class Beverage: """抽象饮料类""" name = "" price = 0.0 type = "BEVERAGE" def getPrice(self): return self.price def setPrice(self, price): self.price = price def getName(self): return self.name class coke(Beverage): """可乐类""" def __init__(self): self.name = "coke" self.price = 4.0 class milk(Beverage): """牛奶类""" def __init__(self): self.name = "milk" self.price = 5.0 class drinkDecorator: """抽象装饰器类""" def getName(self): pass def getPrice(self): pass class iceDecorator(drinkDecorator): """加冰装饰器类""" def __init__(self, beverage): self.beverage = beverage def getName(self): return self.beverage.getName() + " +ice" def getPrice(self): return self.beverage.getPrice() + 0.3 class sugarDecorator(drinkDecorator): """加糖装饰器类""" def __init__(self, beverage): self.beverage = beverage def getName(self): return self.beverage.getName() + " +sugar" def getPrice(self): return self.beverage.getPrice() + 0.5 if __name__ == "__main__": coke_cola = coke() print("Name:%s" % coke_cola.getName()) print("Price:%s" % coke_cola.getPrice()) # 可乐加冰 ice_coke = iceDecorator(coke_cola) print("Name:%s" % ice_coke.getName()) print("Price:%s" % ice_coke.getPrice()) # 可乐加糖 sugar_coke = sugarDecorator(coke_cola) print("Name:%s" % sugar_coke.getName()) print("Price:%s" % sugar_coke.getPrice()) """执行结果 Name:coke Price:4.0 Name:coke +ice Price:4.3 Name:coke +sugar Price:4.5 """
2.适配器模式(Adapter Pattern)
1.概述: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
2.应用场景: 希望复用一些现存的类,但是接口又与复用环境要求不一致
3.适配器模式流程图: https://www.processon.com/view/link/5f16e1bae0b34d54dac066d2
4.示例1: 球场球员兼容
def printInfo(info): print(info) class Player: """抽象球员基类""" name = '' def __init__(self, name): self.name = name def Attack(self, name): pass def Defense(self): pass class Forwards(Player): """前锋类""" def __init__(self, name): Player.__init__(self, name) def Attack(self): printInfo("前锋%s 进攻" % self.name) def Defense(self, name): printInfo("前锋%s 防守" % self.name) class Center(Player): """中锋类""" def __init__(self, name): Player.__init__(self, name) def Attack(self): printInfo("中锋%s 进攻" % self.name) def Defense(self): printInfo("中锋%s 防守" % self.name) class Guards(Player): """后卫类""" def __init__(self, name): Player.__init__(self, name) def Attack(self): printInfo("后卫%s 进攻" % self.name) def Defense(self): printInfo("后卫%s 防守" % self.name) class ForeignCenter(Player): """待适配类(外籍中锋)""" name = '' def __init__(self, name): Player.__init__(self, name) # 不同的成员方法,需要适配成Attack方法 def ForeignAttack(self): printInfo("外籍中锋%s 进攻" % self.name) # 不同的成员方法,需要适配成Defense方法 def ForeignDefense(self): printInfo("外籍中锋%s 防守" % self.name) class Translator(Player): """翻译类(适配类)""" foreignCenter = None # 将需要适配的类对象作为属性 def __init__(self, name): self.foreignCenter = ForeignCenter(name) # 将需要适配的类成员方法翻译成适配后的成员方法 def Attack(self): self.foreignCenter.ForeignAttack() def Defense(self): self.foreignCenter.ForeignDefense() def clientUI(): b = Forwards('巴蒂尔') m = Guards('姚明') # 直接使用适配类 ym = Translator('麦克格雷迪') b.Attack() m.Defense() ym.Attack() ym.Defense() return if __name__ == '__main__': clientUI() """执行结果 前锋巴蒂尔 进攻 后卫姚明 防守 外籍中锋麦克格雷迪 进攻 外籍中锋麦克格雷迪 防守 """
5.示例2: 外包人员系统兼容
class ACpnStaff: """抽象A公司工作人员类""" name = "" id = "" phone = "" def __init__(self, id): self.id = id def getName(self): print("A protocol getName method...id:%s" % self.id) return self.name def setName(self, name): print("A protocol setName method...id:%s" % self.id) self.name = name def getPhone(self): print("A protocol getPhone method...id:%s" % self.id) return self.phone def setPhone(self, phone): print("A protocol setPhone method...id:%s" % self.id) self.phone = phone class BCpnStaff: """抽象B公司工作人员类""" name = "" id = "" telephone = "" def __init__(self, id): self.id = id def get_name(self): print("B protocol get_name method...id:%s" % self.id) return self.name def set_name(self, name): print("B protocol set_name method...id:%s" % self.id) self.name = name def get_telephone(self): print("B protocol get_telephone method...id:%s" % self.id) return self.telephone def set_telephone(self, telephone): print("B protocol get_name method...id:%s" % self.id) self.telephone = telephone class CpnStaffAdapter: """适配器类: 实现将B公司人员接口封装,而对外接口形式与A公司人员接口一致""" b_cpn = "" def __init__(self, id): self.b_cpn = BCpnStaff(id) def getName(self): return self.b_cpn.get_name() def getPhone(self): return self.b_cpn.get_telephone() def setName(self, name): self.b_cpn.set_name(name) def setPhone(self, phone): self.b_cpn.set_telephone(phone) if __name__ == "__main__": acpn_staff = ACpnStaff("123") acpn_staff.setName("X-A") acpn_staff.setPhone("10012345678") print("A Staff Name:%s" % acpn_staff.getName()) print("A Staff Phone:%s" % acpn_staff.getPhone()) bcpn_staff = CpnStaffAdapter("456") bcpn_staff.setName("Y-B") bcpn_staff.setPhone("99987654321") print("B Staff Name:%s" % bcpn_staff.getName()) print("B Staff Phone:%s" % bcpn_staff.getPhone()) """执行结果 A protocol setName method...id:123 A protocol setPhone method...id:123 A protocol getName method...id:123 A Staff Name:X-A A protocol getPhone method...id:123 A Staff Phone:10012345678 B protocol set_name method...id:456 B protocol get_name method...id:456 B protocol get_name method...id:456 B Staff Name:Y-B B protocol get_telephone method...id:456 B Staff Phone:99987654321 """
3.门面模式(Facade Pattern)
1.概述: 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,门面模式提供一个高层次的接口,使得子系统更易于使用
2.示例1: 股票交易
def printInfo(info): print(info) class Stock: """股票交易所类""" name = '股票1' def buy(self): printInfo('买 ' + self.name) def sell(self): printInfo('卖 ' + self.name) class ETF: """基金交易所类""" name = '指数型基金' def buy(self): printInfo('买 ' + self.name) def sell(self): printInfo('卖 ' + self.name) class Future: """期货交易所类""" name = '期货' def buy(self): printInfo('买 ' + self.name) def sell(self): printInfo('卖 ' + self.name) class NationDebt: """国债交易所类""" name = '国债' def buy(self): printInfo('买 ' + self.name) def sell(self): printInfo('卖 ' + self.name) class Option: """权证叫死类""" name = '权证' def buy(self): printInfo('买 ' + self.name) def sell(self): printInfo('卖 ' + 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 clientUI(): myFund = Fund() myFund.buyFund() myFund.sellFund() return if __name__ == '__main__': clientUI() """执行结果 买 股票1 买 指数型基金 买 国债 买 期货 买 权证 卖 股票1 卖 指数型基金 卖 期货 卖 国债 卖 权证 """
3.示例2 火警报警器
class AlarmSensor: """报警器类""" def run(self): print("Alarm Ring...") class WaterSprinker: """喷水器类""" def run(self): print("Spray Water...") class EmergencyDialer: """拨号器类""" def run(self): print("Dial 119...") class EmergencyFacade: """门面类:统一对象,提供接口""" def __init__(self): self.alarm_sensor = AlarmSensor() self.water_sprinker = WaterSprinker() self.emergency_dialer = EmergencyDialer() def runAll(self): self.alarm_sensor.run() self.water_sprinker.run() self.emergency_dialer.run() if __name__ == "__main__": emergency_facade = EmergencyFacade() emergency_facade.runAll() """执行结果 Alarm Ring... Spray Water... Dial 119... """
4.组合模式(Composite Pattern)
1.概述: 将对象组合成树形结构以表示部分和整体的层次结构,使得用户对单个对象和组合对象的使用具有一致性
2.示例1: 店面组织结构
class Store: """抽象店面类""" # 添加店面 def add(self, store): pass # 删除店面 def remove(self, store): pass def pay_by_card(self): pass class BranchStore(Store): """分店类""" def __init__(self, name): self.name = name self.my_store_list = [] def pay_by_card(self): print("店面[%s]的积分已累加进该会员卡" % self.name) for s in self.my_store_list: s.pay_by_card() # 添加店面 def add(self, store): self.my_store_list.append(store) # 删除店面 def remove(self, store): self.my_store_list.remove(store) class JoinStore(Store): """加盟店""" def __init__(self, name): self.name = name def pay_by_card(self): print("店面[%s]的积分已累加进该会员卡" % self.name) def add(self, store): print("无添加子店权限") def remove(self, store): print("无删除子店权限") if __name__ == "__main__": store = BranchStore("朝阳总店") branch = BranchStore("海滨分店") join_branch = JoinStore("昌平加盟1店") join_branch2 = JoinStore("昌平加盟2店") branch.add(join_branch) branch.add(join_branch2) store.add(branch) store.pay_by_card() print(store.my_store_list) """执行结果 店面[朝阳总店]的积分已累加进该会员卡 店面[海滨分店]的积分已累加进该会员卡 店面[昌平加盟1店]的积分已累加进该会员卡 店面[昌平加盟2店]的积分已累加进该会员卡 [<__main__.BranchStore object at 0x10be2aad0>] """
3.示例2: 公司结构组织
class Company: """抽象公司类""" name = '' def __init__(self, name): self.name = name def add(self, company): pass def remove(self, company): pass def display(self, depth): pass def listDuty(self): pass class ConcreteCompany(Company): """总公司类""" childrenCompany = None def __init__(self, name): Company.__init__(self, name) self.childrenCompany = [] def add(self, company): self.childrenCompany.append(company) def remove(self, company): self.childrenCompany.remove(company) def display(self, depth): print('-' * depth + self.name) for component in self.childrenCompany: component.display(depth + 1) def listDuty(self): for component in self.childrenCompany: component.listDuty() class HRDepartment(Company): """人事部门类""" def __init__(self, name): Company.__init__(self, name) def display(self, depth): print('-' * depth + self.name) def listDuty(self): # 履行职责 print('%s Enrolling & Transfering management.' % self.name) class FinanceDepartment(Company): """财务部门类""" def __init__(self, name): Company.__init__(self, name) def display(self, depth): print("-" * depth + self.name) def listDuty(self): # 履行职责 print('%s Finance Management.' % self.name) class RdDepartment(Company): """研发部门类""" def __init__(self, name): Company.__init__(self, name) def display(self, depth): print("-" * depth + self.name) def listDuty(self): print("%s Research & Development." % self.name) if __name__ == "__main__": # 总公司下设东边的分公司一个,东边的分公司下设东北公司和东南公司,显示公司层级,并罗列这些的公司中各部门的职责 root = ConcreteCompany('HeadQuarter') root.add(HRDepartment('HQ HR')) root.add(FinanceDepartment('HQ Finance')) root.add(RdDepartment("HQ R&D")) comp = ConcreteCompany('East Branch') comp.add(HRDepartment('East.Br HR')) comp.add(FinanceDepartment('East.Br Finance')) comp.add(RdDepartment("East.Br R&D")) root.add(comp) comp1 = ConcreteCompany('Northast Branch') comp1.add(HRDepartment('Northeast.Br HR')) comp1.add(FinanceDepartment('Northeast.Br Finance')) comp1.add(RdDepartment("Northeast.Br R&D")) comp.add(comp1) comp2 = ConcreteCompany('Southeast Branch') comp2.add(HRDepartment('Southeast.Br HR')) comp2.add(FinanceDepartment('Southeast.Br Finance')) comp2.add(RdDepartment("Southeast.Br R&D")) comp.add(comp2) root.display(1) root.listDuty() """执行结果 -HeadQuarter --HQ HR --HQ Finance --HQ R&D --East Branch ---East.Br HR ---East.Br Finance ---East.Br R&D ---Northast Branch ----Northeast.Br HR ----Northeast.Br Finance ----Northeast.Br R&D ---Southeast Branch ----Southeast.Br HR ----Southeast.Br Finance ----Southeast.Br R&D HQ HR Enrolling & Transfering management. HQ Finance Finance Management. HQ R&D Research & Development. East.Br HR Enrolling & Transfering management. East.Br Finance Finance Management. East.Br R&D Research & Development. Northeast.Br HR Enrolling & Transfering management. Northeast.Br Finance Finance Management. Northeast.Br R&D Research & Development. Southeast.Br HR Enrolling & Transfering management. Southeast.Br Finance Finance Management. Southeast.Br R&D Research & Development. """
5.享元模式(Flyweight Pattern)
1.概述: 使用共享对象支持大量细粒度对象,大量细粒度的对象的支持共享,可能会涉及这些对象的两类信息: 内部状态信息和外部状态信息
即使用一个字典保存所有对象,在产生对象时,将其类+参数作为键,键相同的对象,只会产生一份,有点像单例
键不同则会产生新的对象,相当于相同属性的对象,直接共享使用,节省存储空间
2.示例1: 精卵工厂
class FlyweightBase: """抽象基地类""" _instances = dict() def __init__(self, *args, **kwargs): # 继承的子类必须初始化 raise NotImplementedError def __new__(cls, *args, **kwargs): # 类+参数作为键,如果已经存在,则返回存在的值(对象),如果不存在,则产生一个新实例并返回 return cls._instances.setdefault( (cls, args, tuple(kwargs.items())), super(FlyweightBase, cls).__new__(cls) ) def test_data(self): pass class Spam(FlyweightBase): """精子类""" def __init__(self, a, b): self.a = a self.b = b def test_data(self): print("精子准备好了", self.a, self.b) class Egg(FlyweightBase): """卵类""" def __init__(self, x, y): self.x = x self.y = y def test_data(self): print("卵子准备好了", self.x, self.y) # 由于spam1和spam2都是产生自Spam类,而且参数都是1, 'abc',所以键是一样的,spam1事先被创建并存于_instance中,spam2就不会被创建了 spam1 = Spam(1, 'abc') spam2 = Spam(1, 'abc') # spam3的参数不一样,所以被创建实例,保存在_instance中 spam3 = Spam(3, 'DEF') # egg1的类是Egg,所以也被创建实例,保存在_instance中 egg1 = Egg(1, 'abc') # spam1和spam2是同一个实例 print(id(spam1), id(spam2)) spam2.test_data() egg1.test_data() print(egg1._instances) print(egg1._instances.keys()) """执行结果 4445952976 4445952976 精子准备好了 1 abc 卵子准备好了 1 abc {(<class '__main__.Spam'>, (1, 'abc'), ()): <__main__.Spam object at 0x108ffdbd0>, (<class '__main__.Spam'>, (3, 'DEF'), ()): <__main__.Spam object at 0x108ffdc50>, (<class '__main__.Egg'>, (1, 'abc'), ()): <__main__.Egg object at 0x108ffdc90>} dict_keys([(<class '__main__.Spam'>, (1, 'abc'), ()), (<class '__main__.Spam'>, (3, 'DEF'), ()), (<class '__main__.Egg'>, (1, 'abc'), ())]) """
3.示例2: 网上咖啡选购平台
class Coffee: """咖啡类""" name = '' price = 0 def __init__(self, name): self.name = name # 在实际业务中,咖啡价格应该是由配置表进行配置,或者调用接口获取等方式得到 # 此处为说明享元模式,将咖啡价格定为名称长度,只是一种简化 self.price = len(name) def show(self): print("Coffee Name:%s Price:%s" % (self.name, self.price)) class Customer: """顾客类""" coffee_factory = "" name = "" def __init__(self, name, coffee_factory): self.name = name self.coffee_factory = coffee_factory def order(self, coffee_name): print("%s ordered a cup of coffee:%s" % (self.name, coffee_name)) return self.coffee_factory.getCoffee(coffee_name) class CoffeeFactory: """咖啡工厂类""" coffee_dict = {} def getCoffee(self, name): if self.coffee_dict.__contains__(name) == False: # 判断键是否存在于字典中 self.coffee_dict[name] = Coffee(name) return self.coffee_dict[name] def getCoffeeCount(self): return len(self.coffee_dict) if __name__ == "__main__": coffee_factory = CoffeeFactory() customer_1 = Customer("A Client", coffee_factory) customer_2 = Customer("B Client", coffee_factory) customer_3 = Customer("C Client", coffee_factory) c1_capp = customer_1.order("cappuccino") c1_capp.show() c2_mocha = customer_2.order("mocha") c2_mocha.show() c3_capp = customer_3.order("cappuccino") c3_capp.show() print("Num of Coffee Instance:%s" % coffee_factory.getCoffeeCount()) """执行结果 A Client ordered a cup of coffee:cappuccino Coffee Name:cappuccino Price:10 B Client ordered a cup of coffee:mocha Coffee Name:mocha Price:5 C Client ordered a cup of coffee:cappuccino Coffee Name:cappuccino Price:10 Num of Coffee Instance:2 """
6.桥梁模式(Bridge Pattern)
1.概述: 将抽象与实现解耦(此处的抽象和实现,并非抽象类和实现类的那种关系,而是一种角色的关系),可以使其独立变化
2.示例1: 车辆行驶
class AbstractRoad: """公路基类""" car = None class AbstractCar: """车辆基类""" def run(self): pass class Street(AbstractRoad): """市区街道类""" def run(self): self.car.run() print("在市区街道上行驶") class SpeedWay(AbstractRoad): """高速公路类""" def run(self): self.car.run() print("在高速公路上行驶") class Car(AbstractCar): """小汽车类""" def run(self): print("小汽车在") class Bus(AbstractCar): """公共汽车类""" def run(self): print("公共汽车在") if __name__ == "__main__": # 小汽车在高速上行驶 road1 = SpeedWay() road1.car = Car() road1.run() # 公交车在高速上行驶 road2 = SpeedWay() road2.car = Bus() road2.run() """执行结果 小汽车在 在高速公路上行驶 公共汽车在 在高速公路上行驶 """
3.示例2: 画笔与形状
class Shape: """抽象形状类""" name = "" param = "" def __init__(self, *param): pass def getName(self): return self.name def getParam(self): return self.name, self.param class Pen: """抽象画笔类""" shape = "" type = "" def __init__(self, shape): self.shape = shape def draw(self): pass class Rectangle(Shape): """矩形类""" def __init__(self, long, width): self.name = "Rectangle" self.param = "Long:%s Width:%s" % (long, width) print("Create a rectangle:%s" % self.param) class Circle(Shape): """圆形类""" def __init__(self, radius): self.name = "Circle" self.param = "Radius:%s" % radius print("Create a circle:%s" % self.param) class NormalPen(Pen): """普通画笔类""" def __init__(self, shape): Pen.__init__(self, shape) self.type = "Normal Line" def draw(self): print("DRAWING %s:%s----PARAMS:%s" % (self.type, self.shape.getName(), self.shape.getParam())) class BrushPen(Pen): """画刷类""" def __init__(self, shape): Pen.__init__(self, shape) self.type = "Brush Line" def draw(self): print("DRAWING %s:%s----PARAMS:%s" % (self.type, self.shape.getName(), self.shape.getParam())) if __name__ == "__main__": normal_pen = NormalPen(Rectangle("20cm", "10cm")) brush_pen = BrushPen(Circle("15cm")) normal_pen.draw() brush_pen.draw() """执行结果 Create a rectangle:Long:20cm Width:10cm Create a circle:Radius:15cm DRAWING Normal Line:Rectangle----PARAMS:('Rectangle', 'Long:20cm Width:10cm') DRAWING Brush Line:Circle----PARAMS:('Circle', 'Radius:15cm') """
7.代理模式(Proxy Pattern)
1.概述: 为某对象提供一个代理,以控制对其的访问和控制,在使用过程中应尽量对抽象主题类进行代理,不要对加过修饰和方法的子类代理
2.示例1: 寄件代理
class sender_base: """寄件者基类""" def __init__(self): pass def send_something(self, something): pass class send_class(sender_base): """寄件者子类""" def __init__(self, receiver): self.receiver = receiver def send_something(self, something): print("SEND " + something + ' TO ' + self.receiver.name) class agent_class(sender_base): """代理类""" # 告诉代理接受者是谁 def __init__(self, receiver): self.send_obj = send_class(receiver) # 代理直接调用发送者的send_something方法发送东西给接受者 def send_something(self, something): self.send_obj.send_something(something) class receive_class: """接受者类""" def __init__(self, someone): self.name = someone if '__main__' == __name__: receiver = receive_class('Leo') agent = agent_class(receiver) agent.send_something('Cake') print(receiver.__class__) print(agent.__class__) """执行结果 SEND Cake TO Leo <class '__main__.receive_class'> <class '__main__.agent_class'> """
3.示例2: 网络服务器配置白名单
# 该服务器接受如下格式数据,addr代表地址,content代表接收的信息内容 info_struct = dict() info_struct["addr"] = 10000 info_struct["content"] = "" class Server: """网络服务器类""" content = "" def recv(self, info): pass def send(self, info): pass def show(self): pass class infoServer(Server): """收发功能类""" def recv(self, info): self.content = info return "recv OK!" def send(self, info): pass def show(self): print("SHOW:%s" % self.content) class serverProxy: """代理基类""" pass class infoServerProxy(serverProxy): """Server的直接接口代理类""" server = "" def __init__(self, server): self.server = server def recv(self, info): return self.server.recv(info) def show(self): self.server.show() class whiteInfoServerProxy(infoServerProxy): """实现服务器的白名单访问类""" white_list = [] def recv(self, info): try: assert type(info) == dict except: return "info structure is not correct" addr = info.get("addr", 0) if not addr in self.white_list: return "Your address is not in the white list." else: content = info.get("content", "") return self.server.recv(content) def addWhite(self, addr): self.white_list.append(addr) def rmvWhite(self, addr): self.white_list.remove(addr) def clearWhite(self): self.white_list = [] if __name__ == "__main__": info_struct = dict() info_struct["addr"] = 10010 info_struct["content"] = "Hello World!" info_server = infoServer() info_server_proxy = whiteInfoServerProxy(info_server) print(info_server_proxy.recv(info_struct)) info_server_proxy.show() info_server_proxy.addWhite(10010) print(info_server_proxy.recv(info_struct)) info_server_proxy.show() """执行结果 Your address is not in the white list. SHOW: recv OK! SHOW:Hello World! """
4.行为型模式
1.策略模式(Strategy Pattern)
1.概述: 定义一组算法,将每个算法都封装起来,并使他们之间可互换,算法策略比较经常地需要被替换时,可以使用策略模式
2.示例1: 出行方式选择
class TravelStrategy: """出行策略类""" def travelAlgorithm(self): pass class AirplaneStrategy(TravelStrategy): """飞机策略类""" def travelAlgorithm(self): print("坐飞机出行....") class TrainStrategy(TravelStrategy): """高铁策略类""" def travelAlgorithm(self): print("坐高铁出行....") class CarStrategy(TravelStrategy): """自驾策略类""" def travelAlgorithm(self): print("自驾出行....") class BicycleStrategy(TravelStrategy): """骑车策略类""" def travelAlgorithm(self): print("骑车出行....") class TravelInterface: """旅行类""" 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.travelAlgorithm() # 坐飞机 travel = TravelInterface(AirplaneStrategy()) travel.travel() # 改开车 travel.set_strategy(TrainStrategy()) travel.travel() """执行结果 坐飞机出行.... 坐高铁出行.... """
3.示例2: 客户消息通知
class customer: """客户类""" customer_name = "" snd_way = "" info = "" phone = "" email = "" def setPhone(self, phone): self.phone = phone def setEmail(self, mail): self.email = mail def getPhone(self): return self.phone def getEmail(self): return self.email def setInfo(self, info): self.info = info def setName(self, name): self.customer_name = name def setBrdWay(self, snd_way): self.snd_way = snd_way def sndMsg(self): self.snd_way.send(self.info) class msgSender: """抽象通知方式类""" dst_code = "" def setCode(self, code): self.dst_code = code def send(self, info): pass class emailSender(msgSender): """邮件通知类""" def send(self, info): print("EMAIL_ADDRESS:%s EMAIL:%s" % (self.dst_code, info)) class textSender(msgSender): """短信通知类""" def send(self, info): print("TEXT_CODE:%s EMAIL:%s" % (self.dst_code, info)) if __name__ == "__main__": customer_x = customer() customer_x.setName("CUSTOMER_X") customer_x.setPhone("10023456789") customer_x.setEmail("customer_x@xmail.com") customer_x.setInfo("Welcome to our new party!") text_sender = textSender() text_sender.setCode(customer_x.getPhone()) customer_x.setBrdWay(text_sender) customer_x.sndMsg() mail_sender = emailSender() mail_sender.setCode(customer_x.getEmail()) customer_x.setBrdWay(mail_sender) customer_x.sndMsg() """执行结果 TEXT_CODE:10023456789 EMAIL:Welcome to our new party! EMAIL_ADDRESS:customer_x@xmail.com EMAIL:Welcome to our new party! """
2.责任链模式(Chain of Responsibility Pattern)
1.概述: 使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系
2.示例1: 统一处理接口
# 处理器基类,其中包含下一个处理器 class BaseHandler: """处理基类""" def successor(self, successor): # 与下一个责任者关联 self._successor = successor # 处理器1 class RequestHandlerL1(BaseHandler): """第一级请求处理者""" name = "TeamLeader" def handle(self, request): if request < 500: print("审批者[%s],请求金额[%s],审批结果[审批通过]" % (self.name, request)) else: print("