设计模式: 对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。 每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。 设计模式分类: 1.创建型模式: 工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式。 2.结构型模式: 适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式。 3.行为型模式: 编辑器模式、责任链模式、命令模式、迭代器模式、中介模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式。 面向对象的三大特征: 封装、继承、多态。 接口: 若干抽象方法的集合。 接口作用: 限制实现接口的类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现。 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class Alipay(Payment): def pay(self, money): print("支付宝支付{}元".format(money)) class Wechatpay(Payment): def pay(self, money): print("微信支付{}元".format(money)) if __name__ == '__main__': alipay = Alipay() alipay.pay(20) wechatpay = Wechatpay() wechatpay.pay(100) 面向对象设计SOLID原则: 1.开放封闭原则: 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。 2.里氏替换原则: 所有引用父类的地方必须能透明地使用其子类的对象。 3.依赖倒置原则: 高层模板不应该依赖低层模板,二者应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。要针对接口编程而不是针对实现编程。 4.接口隔离原则: 使用多个专门的接口,而不是单一的总接口,即客户端不应该依赖那些不需要的接口。 5.单一职责原则: 不要存在多于一个导致类变更的原因。即一个类只负责一项职责。 from abc import ABCMeta, abstractmethod class LandAnimal(metaclass=ABCMeta): @abstractmethod def walk(self): pass class WaterAnimal(metaclass=ABCMeta): @abstractmethod def swim(self): pass class SkyAnimal(metaclass=ABCMeta): @abstractmethod def fly(self): pass class Tiger(LandAnimal): def walk(self): print("老虎行走") class Frog(LandAnimal, WaterAnimal): def walk(self): print("青蛙跳跃") def swim(self): print("青蛙游泳") if __name__ == '__main__': tiger = Tiger() tiger.walk() frog = Frog() frog.walk() frog.swim() 简单工厂模式 概念:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例 角色:工厂角色、抽象产品角色、具体产品角色 优点:1.隐藏了对象创建的实现细节 2.客户不需要修改代码 缺点:1.违反了单一职责原理,将创建逻辑几种到一个工厂类里 2.当添加新产品时,需要修改工厂类代码,违反了开闭原则 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class Alipay(Payment): def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): if self.use_huabei: print("花呗支付{}元".format(money)) else: print("支付宝余额支付{}元".format(money)) class Wechat(Payment): def pay(self, money): print("微信支付{}元".format(money)) class PaymentFactory: def create_payment(self, method): if method == "alipay": return Alipay() elif method == "huabeipay": return Alipay(use_huabei=True) elif method == "wechatpay": return Wechat() else: return TypeError("No such payment name {}".format(method)) if __name__ == '__main__': pf = PaymentFactory() p1 = pf.create_payment("huabeipay") p1.pay(100) p2 = pf.create_payment("wechatpay") p2.pay(200) p3 = pf.create_payment("alipay") p3.pay(300) 工厂方法模式 概念:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类 角色:抽象工厂角色、具体工厂角色、抽象产品角色、具体产品角色 优点:1.每一个具体产品都对应一个具体工厂类,不需要修改工厂类代码 2.隐藏了对象创建的实现细节 缺点:每增加一个具体产品类,就必须增加一个相应的具体工厂类 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class Alipay(Payment): def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): if self.use_huabei: print("花呗支付{}元".format(money)) else: print("支付宝余额支付{}元".format(money)) class WechatPay(Payment): def pay(self, money): print("微信支付{}元".format(money)) class BankPay(Payment): def pay(self, money): print("银行卡支付{}元".format(money)) class PaymentFactory(metaclass=ABCMeta): @abstractmethod def create_payment(self): pass class AlipayFactory(PaymentFactory): def create_payment(self): return Alipay() class HuabeiPayFactory(PaymentFactory): def create_payment(self): return Alipay(use_huabei=True) class WechatPayFactory(PaymentFactory): def create_payment(self): return WechatPay() class BankPayFactory(PaymentFactory): def create_payment(self): return BankPay() if __name__ == '__main__': AF = AlipayFactory() ap = AF.create_payment() ap.pay(100) HF = HuabeiPayFactory() hp = HF.create_payment() hp.pay(200) WF = WechatPayFactory() wp = WF.create_payment() wp.pay(300) BF = BankPayFactory() bp = BF.create_payment() bp.pay(400) 抽象工厂模式 概念:定义一个工厂类接口,让工厂类来创建一系列相关或相互依赖的对象 相比工厂方法模式,抽象工厂模式中的每一个具体工厂都生产一套产品 优点:1.将客户端与类的具体实现相分离 2.每一个工厂创建了一个完整的产品系列,使得易于交换产品系列 3.有利于产品的一致性,即产品之间的约束关系 缺点:难以支持新种类的抽象产品 from abc import ABCMeta, abstractmethod class PhoneShell(metaclass=ABCMeta): @abstractmethod def show_shell(self): pass class CPU(metaclass=ABCMeta): @abstractmethod def show_cpu(self): pass class OS(metaclass=ABCMeta): @abstractmethod def show_os(self): pass class PhoneFactory(metaclass=ABCMeta): @abstractmethod def make_shell(self): pass @abstractmethod def make_cpu(self): pass @abstractmethod def make_os(self): pass class AndroidShell(PhoneShell): def show_shell(self): print("安卓手机壳") class AppleShell(PhoneShell): def show_shell(self): print("苹果手机壳") class SnapDragon(CPU): def show_cpu(self): print("晓龙CPU") class MediaTekCPU(CPU): def show_cpu(self): print("联发科CPU") class AppleCPU(CPU): def show_cpu(self): print("苹果CPU") class AndroidOS(OS): def show_os(self): print("安卓系统") class IOS(OS): def show_os(self): print("ios系统") class XiaoMiFactory(PhoneFactory): def make_cpu(self): return SnapDragon() def make_os(self): return AndroidOS() def make_shell(self): return AndroidShell() class HuaweiFactory(PhoneFactory): def make_cpu(self): return MediaTekCPU() def make_os(self): return AndroidOS() def make_shell(self): return AndroidShell() class IPhoneFactory(PhoneFactory): def make_cpu(self): return AppleCPU() def make_os(self): return IOS() def make_shell(self): return AppleShell() class Phone: def __init__(self, cpu, os, shell): self.cpu = cpu self.os = os self.shell = shell def Manufacture(self): self.cpu.show_cpu() self.os.show_os() self.shell.show_shell() def make_phone(factory): cpu = factory.make_cpu() os = factory.make_os() shell = factory.make_shell() return Phone(cpu, os, shell) if __name__ == '__main__': xiaomi = make_phone(XiaoMiFactory()) xiaomi.Manufacture() huawei = make_phone(HuaweiFactory()) huawei.Manufacture() iphone = make_phone(IPhoneFactory()) iphone.Manufacture() 建造者模式 概念:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别时建造者模式看重一步步构造一个复杂对象,而抽象工厂模式看重于多个系列的产品对象 角色:抽象建造者、具体建造者、指挥者、产品 优点:1.隐藏了一个产品的内部结构和装配过程 2.将构造代码与表示代码分开 3.可以对构造过程进行更精细的控制 from abc import ABCMeta, abstractmethod class Player: def __init__(self, face=None, body=None, arm=None, leg=None): self.face = face self.body = body self.arm = arm self.leg = leg def __str__(self): return "{}, {}, {}, {}".format(self.face, self.body, self.arm, self.leg) class PlayerBuilder(metaclass=ABCMeta): @abstractmethod def build_face(self): pass @abstractmethod def build_body(self): pass @abstractmethod def build_arm(self): pass @abstractmethod def build_leg(self): pass class SexyGirl(PlayerBuilder): def __init__(self): self.player = Player() def build_face(self): self.player.face = "sexygirl脸蛋" def build_body(self): self.player.body = "sexygirl身体" def build_arm(self): self.player.arm = "sexygirl手臂" def build_leg(self): self.player.leg = "sexygirl腿部" class Monster(PlayerBuilder): def __init__(self): self.player = Player() def build_face(self): self.player.face = "Monster脸蛋" def build_body(self): self.player.body = "Monster身体" def build_arm(self): self.player.arm = "Monster手臂" def build_leg(self): self.player.leg = "Monster腿部" class PlayerDirector: def build_player(self, builder): builder.build_body() builder.build_face() builder.build_arm() builder.build_leg() return builder.player if __name__ == '__main__': gbuilder = SexyGirl() gdirector = PlayerDirector() gplayer = gdirector.build_player(gbuilder) print(gplayer) mbuilder = Monster() mdirector = PlayerDirector() mplayer = mdirector.build_player(mbuilder) print(mplayer) 单例模式 概念:保证一个类只有一个实例,并提供一个访问它的全局访问点(日志系统、数据库连接池)。 角色:单例 优点:1.对唯一实例的受控访问 2.单例相当于全局变量,但防止了命名空间被污染。 from abc import ABCMeta, abstractmethod class Singleton: def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance class MyClass(Singleton): def __init__(self, arg): self.arg = arg if __name__ == '__main__': a = MyClass(10) b = MyClass(20) print(a.arg, id(a)) print(b.arg, id(b)) 适配器模式 概念:将一个类的接口装换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 实现方式:类适配器(使用多继承)和对象适配器(使用组合) 角色:目标接口、待适配的类、适配器 适用场景:1.想使用一个已经存在的类,而它的接口不符合你的要求。 2.(对象适配器)想使用一些已经存在的子类,但不可能对每一个进行子类化以匹配它们的接口。适配器模式可以适配它的父类接口。 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class AlipayPay(Payment): @abstractmethod def pay(self, money): print("支付宝支付{}元".format(money)) class WechatPay(Payment): @abstractmethod def pay(self, money): print("微信支付{}元".format(money) class BankPay: @abstractmethod def cost(self, money): print("银联支付{}元".format(money)) class ApplePay: @abstractmethod def cost(self, money): print("苹果支付{}元".format(money)) class ClassAdapterPay(Payment, BankPay): // 类适配器 def pay(self, money): self.cost(money) class ObjectAdapterPay(Payment): // 对象适配器 def __init__(self, payment): self.payment = payment def pay(self, money): self.payment.cost(money) if __name__ == '__main__': CAPay = ClassAdapterPay() // 类适配器 CAPay.pay(199) OAPay = ObjectAdapterPay(ApplePay()) // 对象适配器 OAPay.pay(100) 桥模式 概念:将一个事物的两个维度分离,使其都可以独立地变化 角色:抽象、细化抽象、实现者、具体实现者 应用场景:当事物有两个维度上的表现,两个维度都可以扩展时 优点:1.抽象和实现相分离 2.优秀的扩展能力 from abc import ABCMeta, abstractmethod class Shape(metaclass=ABCMeta): def __init__(self, color): self.color = color @abstractmethod def draw(self): pass class Color(metaclass=ABCMeta): @abstractmethod def paint(self, shape): pass class Rectangle(Shape): name = "长方形" def draw(self): self.color.paint(self) class Circle(Shape): name = "圆形" def draw(self): self.color.paint(self) class Red(Color): def paint(self, shape): print("红色的{}".format(shape.name)) class Blue(Color): def paint(self, shape): print("蓝色的{}".format(shape.name)) if __name__ == '__main__': red_rectangle = Rectangle(Red()) red_rectangle.draw() blue_circle = Circle(Blue()) blue_circle.draw() 组合模式 概念:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个和组合对象的使用具有一致性 角色:抽象组件、叶子组件、复合组件、客户端 适用场景:1.表示对象的"部分-整体"层次结构,用户统一地使用组合结构中的所有对象 2.希望用户忽略组合对象和单个对象的不同,用户统一地使用组合结构中的所有对象 优点:1.定义了包含基本对象和组合对象的类层次结构 2.简化客户端代码,即客户端可以一致使用组合对象和单个对象 3.更容易增加新类型的组件 from abc import ABCMeta, abstractmethod class Graphic(metaclass=ABCMeta): @abstractmethod def draw(self): pass class Point(Graphic): def __init__(self, x, y): self.x = x self.y = y def __str__(self): return "点({}, {})".format(self.x, self.y) def draw(self): print(str(self)) class Line(Graphic): def __init__(self, p1, p2): self.p1 = p1 self.p2 = p2 def __str__(self): return "线段[{}, {}]".format(self.p1, self.p2) def draw(self): print(str(self)) class Picture(Graphic): def __init__(self, graphic): self.graph = list() for g in graphic: self.add(g) def add(self, g): self.graph.append(g) def draw(self): print("start-----复合图形------start") for g in self.graph: g.draw() print("end-------复合图形--------end") if __name__ == '__main__': p1 = Point(2, 3) p2 = Point(8, 5) l1 = Line(Point(1, 8), Point(5, 3)) l2 = Line(Point(2, 6), Point(9, 9)) pic1 = Picture([p1, p2, l1]) pic1.draw() pic2 = Picture([p2, l1, l2]) pic2.draw() combine = Picture([pic1, pic2]) combine.draw() 外观模式 概念:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口是的这一子系统更容易使用 角色:外观、子系统类 优点:1.减少系统相互依赖 2.提高了灵活性 3.提高了安全性 class CPU: def run(self): print("CPU开始运行") def stop(self): print("CPU停止运行") class Disk: def run(self): print("磁盘开始运行") def stop(self): print("磁盘停止运行") class Memory: def run(self): print("内存开始运行") def stop(self): print("内存停止运行") class Computer: def __init__(self): self.cpu = CPU() self.disk = Disk() self.memory = Memory() def run(self): self.cpu.run() self.disk.run() self.memory.run() def stop(self): self.cpu.stop() self.disk.stop() self.memory.stop() if __name__ == '__main__': computer = Computer() computer.run() computer.stop() 代理模式 概念:为其他对象提供一种代理以控制对这个对象的访问 应用场景:1.远程代理:为远程的对象提供代理 2.虚代理:根据需要创建很大的对象 3.保护代理:控制对原始对象的访问,用于对象有不同访问对象权限时 角色:抽象代理、实体、代理 优点:1.远程代理:可以隐藏对象位于远程地址空间的事实 2.虚代理:可以进行优化,例如根据要求创建对象 3.保护对象:允许在访问一个对象时有一些附加的业务处理 from abc import ABCMeta, abstractmethod class Subject(metaclass=ABCMeta): @abstractmethod def get_content(self): pass @abstractmethod def set_content(self, content): pass class RealProxy(Subject): def __init__(self, filename): self.filename = filename f = open(self.filename, "r") print("读取文件内容") self.content = f.read() f.close() def get_content(self): return self.content def set_content(self, content): f = open(self.filename, "w") f.write(content) f.close() class VirtualProxy(Subject): def __init__(self, filename): self.filename = filename self.subject = None def get_content(self): if not self.subject: self.subject = RealProxy(self.filename) return self.subject.get_content() def set_content(self, content): if not self.subject: self.subject = RealProxy(self.filename) return self.subject.set_content(content) class ProtectProxy(Subject): def __init__(self, filename): self.subject = RealProxy(filename) def get_content(self): return self.subject.get_content() def set_content(self, content): raise PermissionError("无写入权限") if __name__ == '__main__': real_proxy = RealProxy("test.txt") real_content = real_proxy.get_content() print(real_content) real_proxy.set_content("please...") virtual_proxy = VirtualProxy("test.txt") virtual_content = virtual_proxy.get_content() print(virtual_content) protect_proxy = ProtectProxy("test.txt") print(protect_proxy.get_content()) protect_proxy.set_content("i love it") 责任链模式 概念:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 角色:抽象处理者、具体处理者、客户端 适用场景:1.有多个对象可以处理一个请求,那个对象处理由运行时决定 2.在不明确接收者的情况下,向多个对象中的一个提交一个请求 优点:一个对象无需知道是其他哪一个对象处理其请求 from abc import ABCMeta, abstractmethod class Handler(metaclass=ABCMeta): @abstractmethod def handle_leave(self, day): pass class GeneralManager(Handler): def handle_leave(self, day): if day <= 10: print("总经理准假{}天".format(day)) else: print("请假太长安排辞退") class DepartmentManager(Handler): def __init__(self): self.next_leader = GeneralManager() def handle_leave(self, day): if day <= 5: print("部门经理准假{}天".format(day)) else: print("部门经理职权不足") self.next_leader.handle_leave(day) class ProjectDirector(Handler): def __init__(self): self.next_leader = DepartmentManager() def handle_leave(self, day): if day <= 3: print("项目主管准假{}天".format(day)) else: print("项目主管职权不足") self.next_leader.handle_leave(day) if __name__ == '__main__': manager = ProjectDirector() manager.handle_leave(6) 观察者模式 概念:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,观察者模式又称"发布-订阅"模式 角色:抽象主题、具体主题(发布者)、抽象观察者、具体观察者(订阅者) 适用场景:1.当一个抽象模型有两方面,其中一方面依赖于另一个方面,将这两者封装在独立对象中以使它们可以各自独立地改变和复用 2.当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变 3.当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,你不希望这些对象时紧密耦合的 优点:1.目标和观察者之间的抽象耦合最小 2.支持广播通信 from abc import ABCMeta, abstractmethod class Observer(metaclass=ABCMeta): @abstractmethod def update(self, notice): pass class Notice: def __init__(self): self.observers = [] def attach(self, observer): self.observers.append(observer) def detach(self, observer): self.observers.remove(observer) def notify(self): for observer in self.observers: observer.update(self) class StaffNotice(Notice): def __init__(self, notice_info): super().__init__() self.__notice_info = notice_info @property def notice_info(self): return self.__notice_info @notice_info.setter def notice_info(self, info): self.__notice_info = info self.notify() # 关键推送 class StaffObserver(Observer): def __init__(self): self.notice_info = None def update(self, notice): self.notice_info = notice.notice_info if __name__ == '__main__': staff_notice = StaffNotice('初始化推送消息') staff_observer01 = StaffObserver() staff_observer02 = StaffObserver() staff_notice.attach(staff_observer01) staff_notice.attach(staff_observer02) print(staff_observer01.notice_info) print(staff_observer02.notice_info) staff_notice.notice_info = '假期放假通知!' print(staff_observer01.notice_info) print(staff_observer02.notice_info) staff_notice.detach(staff_observer02) staff_notice.notice_info = '明天开会!' print(staff_observer01.notice_info) print(staff_observer02.notice_info) 策略模式 概念:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于它的客户而变化 角色:抽象策略、具体策略、上下文 优点:1.定义了一系列可重用的算法于行为 2.消除了一些条件语句 3.可以提供相同行为的不同实现 缺点:客户必须了解不同的策略 from abc import ABCMeta, abstractmethod class Strategy(metaclass=ABCMeta): @abstractmethod def execute(self, data): pass class FastStrategy(Strategy): def execute(self, data): print("快速策略处理{}".format(data)) class ExactStrategy(Strategy): def execute(self, data): print("准确模式处理{}".format(data)) class Context: def __init__(self, strategy, data): self.data = data self.strategy = strategy def set_strategy(self, strategy): self.strategy = strategy def do_strategy(self): self.strategy.execute(self.data) if __name__ == '__main__': data = "#####" fast = FastStrategy() exact = ExactStrategy() context = Context(exact, data) context.do_strategy() context.set_strategy(fast) context.do_strategy() 模板方法模式 概念:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 角色:抽象类(1.定义抽象的原子操作2.实现一个模板方法作为算法的骨架)、具体类(实现原子操作) 适用场景:1.一次性实现一个算法的不变的部分 2.各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复 3.控制子类扩展 from abc import ABCMeta, abstractmethod import time class Window(metaclass=ABCMeta): @abstractmethod def start(self): pass @abstractmethod def repaint(self): pass @abstractmethod def stop(self): pass def run(self): self.start() while True: try: self.repaint() time.sleep(1) except KeyboardInterrupt: break self.stop() class MyWindow(Window): def __init__(self, msg): self.msg =msg def start(self): print("窗口开始运行") def repaint(self): print(self.msg) def stop(self): print("窗口结束运行") if __name__ == '__main__': MyWindow("running...").run()