16_Python设计模式

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("33[31;1m[%s]无权审批,交给下一个审批者33[0m" % self.name)
            self._successor.handle(request)


# 处理器2
class RequestHandlerL2(BaseHandler):
    """第二级请求处理者"""
    name = "DeptManager"

    def handle(self, request):
        if request < 5000:
            print("审批者[%s],请求金额[%s],审批结果[审批通过]" % (self.name, request))
        else:
            print("33[31;1m[%s]无权审批,交给下一个审批者33[0m" % self.name)
            self._successor.handle(request)


# 处理器3
class RequestHandlerL3(BaseHandler):
    """第三级请求处理者"""
    name = "CEO"

    def handle(self, request):
        if request < 10000:
            print("审批者[%s],请求金额[%s],审批结果[审批通过]" % (self.name, request))
        else:
            print("33[31;1m[%s]要太多钱了,不批33[0m" % self.name)
            # self._successor.handle(request)


# 统一的接口
class RequestAPI:
    """统一的接口类"""

    # 创建处理器1,2,3的实例
    h1 = RequestHandlerL1()
    h2 = RequestHandlerL2()
    h3 = RequestHandlerL3()

    # 责任链: 处理器1--处理器2--处理器3
    h1.successor(h2)
    h2.successor(h3)

    def __init__(self, name, amount):
        self.name = name
        self.amount = amount

    # 统一处理API
    def handle(self):
        """统一请求接口"""
        # 在满足条件的情况下(>5000),会依次执行h1,h2,h3的handle
        self.h1.handle(self.amount)


if __name__ == "__main__":
    r1 = RequestAPI("echo", 30000)
    r1.handle()
    print(r1.__dict__)
"""执行结果
    [TeamLeader]无权审批,交给下一个审批者
    [DeptManager]无权审批,交给下一个审批者
    [CEO]要太多钱了,不批
    {'name': 'echo', 'amount': 30000}
"""

        3.示例2: 请假系统

class manager:
    """抽象经理类"""
    successor = None
    name = ''

    def __init__(self, name):
        self.name = name

    def setSuccessor(self, successor):
        self.successor = successor

    def handleRequest(self, request):
        pass


class lineManager(manager):
    """直属经理类"""

    def handleRequest(self, request):
        if request.requestType == 'DaysOff' and request.number <= 3:
            print('%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number))
        else:
            print('%s:%s Num:%d Accepted CONTINUE' % (self.name, request.requestContent, request.number))
            if self.successor != None:
                self.successor.handleRequest(request)


class departmentManager(manager):
    """部门经理类"""

    def handleRequest(self, request):
        if request.requestType == 'DaysOff' and request.number <= 7:
            print('%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number))
        else:
            print('%s:%s Num:%d Accepted CONTINUE' % (self.name, request.requestContent, request.number))
            if self.successor != None:
                self.successor.handleRequest(request)


class generalManager(manager):
    """总经理类"""

    def handleRequest(self, request):
        if request.requestType == 'DaysOff':
            print('%s:%s Num:%d Accepted OVER' % (self.name, request.requestContent, request.number))


class request:
    """假期请求类"""
    requestType = ''
    requestContent = ''
    number = 0


if __name__ == "__main__":
    line_manager = lineManager('LINE MANAGER')
    department_manager = departmentManager('DEPARTMENT MANAGER')
    general_manager = generalManager('GENERAL MANAGER')

    line_manager.setSuccessor(department_manager)
    department_manager.setSuccessor(general_manager)

    req = request()
    req.requestType = 'DaysOff'
    req.requestContent = 'Ask 1 day off'
    req.number = 1
    line_manager.handleRequest(req)

    req.requestType = 'DaysOff'
    req.requestContent = 'Ask 5 days off'
    req.number = 5
    line_manager.handleRequest(req)

    req.requestType = 'DaysOff'
    req.requestContent = 'Ask 10 days off'
    req.number = 10
    line_manager.handleRequest(req)
"""执行结果
    LINE MANAGER:Ask 1 day off Num:1 Accepted OVER
    LINE MANAGER:Ask 5 days off Num:5 Accepted CONTINUE
    DEPARTMENT MANAGER:Ask 5 days off Num:5 Accepted OVER
    LINE MANAGER:Ask 10 days off Num:10 Accepted CONTINUE
    DEPARTMENT MANAGER:Ask 10 days off Num:10 Accepted CONTINUE
    GENERAL MANAGER:Ask 10 days off Num:10 Accepted OVER
"""

3.命令模式(Command Pattern)

        1.概述: 将一个请求封装成一个对象,从而可以使用不同的请求将客户端参数化,对请求排队或者记录请求日志可提供命令的撤销,恢复功能

        2.示例: 饭店点餐系统

class backSys:
    """抽象后台系统类"""

    def cook(self, dish):
        pass


class mainFoodSys(backSys):
    """主食子系统类"""

    def cook(self, dish):
        print("MAINFOOD:Cook %s" % dish)


class coolDishSys(backSys):
    """凉菜子系统类"""

    def cook(self, dish):
        print("COOLDISH:Cook %s" % dish)


class hotDishSys(backSys):
    """热菜子系统类"""

    def cook(self, dish):
        print("HOTDISH:Cook %s" % dish)


class waiterSys:
    """前台系统类"""

    menu_map = dict()
    commandList = []

    def setOrder(self, command):
        print("WAITER:Add dish")
        self.commandList.append(command)

    def cancelOrder(self, command):
        print("WAITER:Cancel order...")
        self.commandList.remove(command)

    def notify(self):
        print("WAITER:Nofify...")
        for command in self.commandList:
            command.execute()


# 命令类构建: 前台系统中的notify接口直接调用命令中的execute接口执行命令
class Command:
    """抽象命令类"""

    receiver = None

    def __init__(self, receiver):
        self.receiver = receiver

    def execute(self):
        pass


class foodCommand(Command):
    """食物命令类"""
    dish = ""

    def __init__(self, receiver, dish):
        self.receiver = receiver
        self.dish = dish

    def execute(self):
        self.receiver.cook(self.dish)


class mainFoodCommand(foodCommand):
    """主食命令类"""
    pass


class coolDishCommand(foodCommand):
    """凉菜命令类"""
    pass


class hotDishCommand(foodCommand):
    """热菜命令类"""
    pass


class menuAll:
    """菜单类"""
    menu_map = dict()

    def loadMenu(self):  # 加载菜单,这里直接写死
        self.menu_map["hot"] = ["Yu-Shiang Shredded Pork", "Sauteed Tofu, Home Style", "Sauteed Snow Peas"]
        self.menu_map["cool"] = ["Cucumber", "Preserved egg"]
        self.menu_map["main"] = ["Rice", "Pie"]

    def isHot(self, dish):
        if dish in self.menu_map["hot"]:
            return True
        return False

    def isCool(self, dish):
        if dish in self.menu_map["cool"]:
            return True
        return False

    def isMain(self, dish):
        if dish in self.menu_map["main"]:
            return True
        return False


if __name__ == "__main__":
    dish_list = ["Yu-Shiang Shredded Pork", "Sauteed Tofu, Home Style", "Cucumber", "Rice"]  # 顾客点的菜
    waiter_sys = waiterSys()
    main_food_sys = mainFoodSys()
    cool_dish_sys = coolDishSys()
    hot_dish_sys = hotDishSys()
    menu = menuAll()
    menu.loadMenu()
    for dish in dish_list:
        if menu.isCool(dish):
            cmd = coolDishCommand(cool_dish_sys, dish)
        elif menu.isHot(dish):
            cmd = hotDishCommand(hot_dish_sys, dish)
        elif menu.isMain(dish):
            cmd = mainFoodCommand(main_food_sys, dish)
        else:
            continue
        waiter_sys.setOrder(cmd)
    waiter_sys.notify()
"""执行结果
    WAITER:Add dish
    WAITER:Add dish
    WAITER:Add dish
    WAITER:Add dish
    WAITER:Nofify...
    HOTDISH:Cook Yu-Shiang Shredded Pork
    HOTDISH:Cook Sauteed Tofu, Home Style
    COOLDISH:Cook Cucumber
    MAINFOOD:Cook Rice
"""

4.中介者模式(Mediator Pattern)

        1.概述: 用一个中介对象封装一系列的对象交互,中介者使各对象不需要显式地互相作用,从而使其耦合松散

        2.示例: 仓储管理系统

class colleague:
    """抽象同事类"""
    mediator = None

    def __init__(self, mediator):
        self.mediator = mediator


class purchaseColleague(colleague):
    """采购同事类"""

    def buyStuff(self, num):
        print("PURCHASE:Bought %s" % num)
        self.mediator.execute("buy", num)

    def getNotice(self, content):
        print("PURCHASE:Get Notice--%s" % content)


class warehouseColleague(colleague):
    """仓库同事类"""
    total = 0
    threshold = 100

    def setThreshold(self, threshold):
        self.threshold = threshold

    def isEnough(self):
        if self.total < self.threshold:
            print("WAREHOUSE:Warning...Stock is low... ")
            self.mediator.execute("warning", self.total)
            return False
        else:
            return True

    def inc(self, num):
        self.total += num
        print("WAREHOUSE:Increase %s" % num)
        self.mediator.execute("increase", num)
        self.isEnough()

    def dec(self, num):
        if num > self.total:
            print("WAREHOUSE:Error...Stock is not enough")
        else:
            self.total -= num
            print("WAREHOUSE:Decrease %s" % num)
            self.mediator.execute("decrease", num)
        self.isEnough()


class salesColleague(colleague):
    """销售同事类"""

    def sellStuff(self, num):
        print("SALES:Sell %s" % num)
        self.mediator.execute("sell", num)

    def getNotice(self, content):
        print("SALES:Get Notice--%s" % content)


class abstractMediator:
    """中介者基类"""
    purchase = ""
    sales = ""
    warehouse = ""

    def setPurchase(self, purchase):
        self.purchase = purchase

    def setWarehouse(self, warehouse):
        self.warehouse = warehouse

    def setSales(self, sales):
        self.sales = sales

    def execute(self, content, num):
        pass


# KA直接协调各个同事的工作
class stockMediator(abstractMediator):
    """KA中介者类"""

    def execute(self, content, num):
        print("MEDIATOR:Get Info--%s" % content)
        if content == "buy":
            self.warehouse.inc(num)
            self.sales.getNotice("Bought %s" % num)
        elif content == "increase":
            self.sales.getNotice("Inc %s" % num)
            self.purchase.getNotice("Inc %s" % num)
        elif content == "decrease":
            self.sales.getNotice("Dec %s" % num)
            self.purchase.getNotice("Dec %s" % num)
        elif content == "warning":
            self.sales.getNotice("Stock is low.%s Left." % num)
            self.purchase.getNotice("Stock is low. Please Buy More!!! %s Left" % num)
        elif content == "sell":
            self.warehouse.dec(num)
            self.purchase.getNotice("Sold %s" % num)
        else:
            pass


if __name__ == "__main__":
    mobile_mediator = stockMediator()  # 先配置
    mobile_purchase = purchaseColleague(mobile_mediator)
    mobile_warehouse = warehouseColleague(mobile_mediator)
    mobile_sales = salesColleague(mobile_mediator)
    mobile_mediator.setPurchase(mobile_purchase)
    mobile_mediator.setWarehouse(mobile_warehouse)
    mobile_mediator.setSales(mobile_sales)

    mobile_warehouse.setThreshold(200)  # 设置仓储阈值为200
    mobile_purchase.buyStuff(300)  # 先采购300
    mobile_sales.sellStuff(120)  # 再卖出120
"""执行结果
    PURCHASE:Bought 300
    MEDIATOR:Get Info--buy
    WAREHOUSE:Increase 300
    MEDIATOR:Get Info--increase
    SALES:Get Notice--Inc 300
    PURCHASE:Get Notice--Inc 300
    SALES:Get Notice--Bought 300
    SALES:Sell 120
    MEDIATOR:Get Info--sell
    WAREHOUSE:Decrease 120
    MEDIATOR:Get Info--decrease
    SALES:Get Notice--Dec 120
    PURCHASE:Get Notice--Dec 120
    WAREHOUSE:Warning...Stock is low...
    MEDIATOR:Get Info--warning
    SALES:Get Notice--Stock is low.180 Left.
    PURCHASE:Get Notice--Stock is low. Please Buy More!!! 180 Left
    PURCHASE:Get Notice--Sold 120
"""

5.模板模式(Template Pattern)

        1.概述: 定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重新定义该算法的某些特定的步骤

        2.示例1: 注册登录

# 注册基类,定义所有注册都需要的步骤
class Register:
    """用户注册接口类"""

    def register(self):
        pass

    def login(self):
        pass

    def auth(self):
        self.register()
        self.login()


# QQ登录的具体实现
class RegisterByQQ(Register):
    """qq注册类"""

    def register(self):
        print("---用qq注册-----")

    def login(self):
        print('----用qq登录-----')


# WeiChat登录的具体实现
class RegisterByWeiChat(Register):
    """微信注册类"""

    def register(self):
        print("---用微信注册-----")

    def login(self):
        print('----用微信登录-----')


if __name__ == "__main__":
    register1 = RegisterByQQ()
    register1.login()

    register2 = RegisterByWeiChat()
    register2.login()
"""执行结果
    ----用qq登录-----
    ----用微信登录-----
"""

        3.示例2: 股票查询客户端

class StockQueryDevice:
    """股票查询类"""

    stock_code = "0"
    stock_price = 0.0

    def login(self, usr, pwd):
        pass

    def setCode(self, code):
        self.stock_code = code

    def queryPrice(self):
        pass

    def showPrice(self):
        pass

    # 实现封装登录,设置代码,查询,展示的步骤
    def operateQuery(self, usr, pwd, code):
        self.login(usr, pwd)
        self.setCode(code)
        self.queryPrice()
        self.showPrice()
        return True

    # 登录
    def login(self, usr, pwd):
        pass

    # 设置股票代码
    def setCode(self, code):
        self.stock_code = code

    # 查询
    def queryPrice(self):
        pass

    # 展示
    def showPrice(self):
        pass


class WebAStockQueryDevice(StockQueryDevice):
    """WebA查询类"""

    def login(self, usr, pwd):
        if usr == "myStockA" and pwd == "myPwdA":
            print("Web A:Login OK... user:%s pwd:%s" % (usr, pwd))
            return True
        else:
            print("Web A:Login ERROR... user:%s pwd:%s" % (usr, pwd))
            return False

    def queryPrice(self):
        print("Web A Querying...code:%s " % self.stock_code)
        self.stock_price = 20.00

    def showPrice(self):
        print("Web A Stock Price...code:%s price:%s" % (self.stock_code, self.stock_price))


class WebBStockQueryDevice(StockQueryDevice):
    """WebB查询类"""

    def login(self, usr, pwd):
        if usr == "myStockB" and pwd == "myPwdB":
            print("Web B:Login OK... user:%s pwd:%s" % (usr, pwd))
            return True
        else:
            print("Web B:Login ERROR... user:%s pwd:%s" % (usr, pwd))
            return False

    def queryPrice(self):
        print("Web B Querying...code:%s " % self.stock_code)
        self.stock_price = 30.00

    def showPrice(self):
        print("Web B Stock Price...code:%s price:%s" % (self.stock_code, self.stock_price))


def operateQuery(self, usr, pwd, code):
    """登录判断"""
    if not self.login(usr, pwd):
        return False
    self.setCode(code)
    self.queryPrice()
    self.showPrice()
    return True


if __name__ == "__main__":
    # 在网站A上查询股票
    web_a_query_dev = WebAStockQueryDevice()
    web_a_query_dev.operateQuery("myStockA", "myPwdA", "12345")
"""执行结果
    Web A:Login OK... user:myStockA pwd:myPwdA
    Web A Querying...code:12345 
    Web A Stock Price...code:12345 price:20.0
"""

6.迭代器模式(Iterator Pattern)

        1.概述: 它提供一种方法,访问一个容器对象中各个元素,而又不需要暴露对象的内部细节

        2.示例1: 可迭代对象

if __name__ == "__main__":
    lst = ["hello Alice", "hello Bob", "hello Eve"]
    lst_iter = iter(lst)
    print(lst_iter)
    print(next(lst_iter))
    print(next(lst_iter))
    print(lst_iter.__next__())
    print(lst_iter.__next__())
"""执行结果
    <list_iterator object at 0x10acd8890>
    hello Alice
    hello Bob
    hello Eve
    Traceback (most recent call last):
      File "/Users/tangxuecheng/Desktop/python3/demo/demo1.py", line 8, in <module>
        print(lst_iter.__next__())
    StopIteration
"""

        3.示例2: 自定义迭代器类

class MyIter:
    """自定义迭代器类"""

    def __init__(self, n):
        self.index = 0
        self.n = n

    def __iter__(self):
        # return MyIter(self.n)  # 次写法可以让迭代器重复迭代
        return self  # 此写法迭代器只能迭代一次

    def __next__(self):
        if self.index < self.n:
            value = self.index ** 2
            self.index += 1
            return value
        else:
            raise StopIteration()


if __name__ == "__main__":
    x_square = MyIter(10)
    for x in x_square:
        print(x, end=" ")
"""执行结果
    0 1 4 9 16 25 36 49 64 81
"""

7.访问者模式(Visitor Pattern)

        1.概述: 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义于作用于这些元素的新操作

        2.示例: 药房业务系统

class Medicine:
    """药品基类"""
    name = ""
    price = 0.0

    def __init__(self, name, price):
        self.name = name
        self.price = price

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def getPrice(self):
        return self.price

    def setPrice(self, price):
        self.price = price

    def accept(self, visitor):
        pass


class Antibiotic(Medicine):
    """抗生素类"""

    def accept(self, visitor):
        visitor.visit(self)


class Coldrex(Medicine):
    """感冒药类"""

    def accept(self, visitor):
        visitor.visit(self)


class Visitor:
    """工作人员基类"""
    name = ""

    def setName(self, name):
        self.name = name

    def visit(self, medicine):
        pass


class Charger(Visitor):
    """划价员类"""

    def visit(self, medicine):
        print("CHARGE: %s lists the Medicine %s. Price:%s " % (self.name, medicine.getName(), medicine.getPrice()))


class Pharmacy(Visitor):
    """药房管理员类"""

    def visit(self, medicine):
        print("PHARMACY:%s offers the Medicine %s. Price:%s" % (self.name, medicine.getName(), medicine.getPrice()))


class ObjectStructure:
    pass


class Prescription(ObjectStructure):
    """药方类"""
    medicines = []

    def addMedicine(self, medicine):
        self.medicines.append(medicine)

    def rmvMedicine(self, medicine):
        self.medicines.append(medicine)

    def visit(self, visitor):
        for medc in self.medicines:
            medc.accept(visitor)


if __name__ == "__main__":
    yinqiao_pill = Coldrex("Yinqiao Pill", 2.0)
    penicillin = Antibiotic("Penicillin", 3.0)
    doctor_prsrp = Prescription()
    doctor_prsrp.addMedicine(yinqiao_pill)
    doctor_prsrp.addMedicine(penicillin)
    charger = Charger()
    charger.setName("Doctor Strange")
    pharmacy = Pharmacy()
    pharmacy.setName("Doctor Wei")
    doctor_prsrp.visit(charger)
    doctor_prsrp.visit(pharmacy)
"""执行结果
    CHARGE: Doctor Strange lists the Medicine Yinqiao Pill. Price:2.0
    CHARGE: Doctor Strange lists the Medicine Penicillin. Price:3.0
    PHARMACY:Doctor Wei offers the Medicine Yinqiao Pill. Price:2.0
    PHARMACY:Doctor Wei offers the Medicine Penicillin. Price:3.0
"""

8.观察者模式(Observer Pattern)

        1.概述: 定义对象间一种一对多的依赖关系,使得当该对象状态改变时,所有依赖于它的对象都会得到通知,并被自动更新

        2.示例1: 粉丝推广

class ObserverBase:
    """观察者基类,类似于大V账户"""

    def __init__(self):
        self._observerd_list = []  # 粉丝列表

    def attach(self, observe_subject):
        """添加要观察的对象,添加粉丝"""
        if observe_subject not in self._observerd_list:
            self._observerd_list.append(observe_subject)
            print("[%s]已经将[%s]加入观察队列..." % (self.name, observe_subject))

    def detach(self, observe_subject):
        """解除观察关系,删除粉丝"""
        try:
            self._observerd_list.remove(observe_subject)
            print("不再观察[%s]" % observe_subject)
        except ValueError:
            pass

    def notify(self):
        """通知所有被观察者,通知粉丝"""
        # 粉丝.by_notified(self)
        for fun_obj in self._observerd_list:
            fun_obj.by_notified(self)


class Observer(ObserverBase):
    """观察者类,实际的大V"""

    def __init__(self, name):
        super(Observer, self).__init__()
        self.name = name
        self._msg = ''

    @property
    def msg(self):
        """当前状况"""
        return self._msg

    @msg.setter
    def msg(self, content):
        """当msg这个属性被设置的时候,执行的方法"""
        self._msg = content
        self.notify()


class FenViewer:
    """粉丝类"""

    def __init__(self, name):
        self.name = name

    def by_notified(self, big_v_object):
        print("粉丝[%s]:收到[%s]消息[%s] " % (self.name, big_v_object.name, big_v_object.msg))


if __name__ == "__main__":
    big_v_1 = Observer("大V_1")
    big_v_2 = Observer("大V_2")

    fen_a = FenViewer("粉丝A")
    fen_b = FenViewer("粉丝B")

    big_v_1.attach(fen_a)
    big_v_1.attach(fen_b)

    big_v_2.attach(fen_b)

    big_v_1.msg = "33[32;1m官宣...33[0m"
    big_v_2.msg = "33[31;1m广告推荐~~~33[0m"
"""执行结果
    [大V_1]已经将[<__main__.FenViewer object at 0x10ee6fc50>]加入观察队列...
    [大V_1]已经将[<__main__.FenViewer object at 0x10ee6fc90>]加入观察队列...
    [大V_2]已经将[<__main__.FenViewer object at 0x10ee6fc90>]加入观察队列...
    粉丝[粉丝A]:收到[大V_1]消息[官宣...]
    粉丝[粉丝B]:收到[大V_1]消息[官宣...]
    粉丝[粉丝B]:收到[大V_2]消息[广告推荐~~~]
"""

        3.示例2: 火警报警器

# 三个类提取共性,泛化出观察者类,并构造被观察者
class Observer:
    """抽象共性类"""

    def update(self):
        pass


class AlarmSensor(Observer):
    """报警器类"""

    def update(self, action):
        print("Alarm Got: %s" % action)
        self.runAlarm()

    def runAlarm(self):
        print("Alarm Ring...")


class WaterSprinker(Observer):
    """喷水器类"""

    def update(self, action):
        print("Sprinker Got: %s" % action)
        self.runSprinker()

    def runSprinker(self):
        print("Spray Water...")


class EmergencyDialer(Observer):
    """拨号器类"""

    def update(self, action):
        print("Dialer Got: %s" % action)
        self.runDialer()

    def runDialer(self):
        print("Dial 119...")


class Observed:
    """观察者类"""
    observers = []
    action = ""

    def addObserver(self, observer):
        self.observers.append(observer)

    def notifyAll(self):
        for obs in self.observers:
            obs.update(self.action)


class smokeSensor(Observed):
    """烟雾传感器类"""

    def setAction(self, action):
        self.action = action

    def isFire(self):
        return True


if __name__ == "__main__":
    alarm = AlarmSensor()
    sprinker = WaterSprinker()
    dialer = EmergencyDialer()

    smoke_sensor = smokeSensor()
    smoke_sensor.addObserver(alarm)
    smoke_sensor.addObserver(sprinker)
    smoke_sensor.addObserver(dialer)

    if smoke_sensor.isFire():
        smoke_sensor.setAction("On Fire!")
        smoke_sensor.notifyAll()
"""执行结果
    Alarm Got: On Fire!
    Alarm Ring...
    Sprinker Got: On Fire!
    Spray Water...
    Dialer Got: On Fire!
    Dial 119...
"""

9.解释器模式(Interpreter Pattern)

        1.概述: 给定一种语言,定义它的文法表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子

        2.示例: 模拟吉他

class PlayContext():
    """乐谱类"""
    play_text = None


class Expression():
    """解释器表达式类"""

    def interpret(self, context):
        """转译乐谱"""
        if len(context.play_text) == 0:
            return
        else:
            play_segs = context.play_text.split(" ")
            for play_seg in play_segs:
                pos = 0
                for ele in play_seg:
                    if ele.isalpha():
                        pos += 1
                        continue
                    break
                play_chord = play_seg[0:pos]
                play_value = play_seg[pos:]
                self.execute(play_chord, play_value)

    def execute(self, play_key, play_value):
        """演奏乐谱"""
        pass


class NormGuitar(Expression):
    """吉他类"""

    def execute(self, key, value):
        """覆盖父类的演奏乐谱方法"""
        print("Normal Guitar Playing--Chord:%s Play Tune:%s" % (key, value))


if __name__ == "__main__":
    context = PlayContext()
    context.play_text = "C53231323 Em43231323 F43231323 G63231323"
    guitar = NormGuitar()
    guitar.interpret(context)
"""执行结果
    Normal Guitar Playing--Chord:C Play Tune:53231323
    Normal Guitar Playing--Chord:Em Play Tune:43231323
    Normal Guitar Playing--Chord:F Play Tune:43231323
    Normal Guitar Playing--Chord:G Play Tune:63231323
"""

10.备忘录模式(Memento Pattern)

        1.概述: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以将该对象恢复到原来保存的状态

        2.示例: 游戏进度保存

import random


# 实现保存进度
class Memento:
    """备忘录类"""
    vitality = 0
    attack = 0
    defense = 0

    def __init__(self, vitality, attack, defense):
        self.vitality = vitality
        self.attack = attack
        self.defense = defense

# 定义基本的生命值,攻击值,防御值以及实现角色状态控制的方法
class GameCharacter:
    """整体控制类"""
    vitality = 0
    attack = 0
    defense = 0

    def displayState(self):
        print('Current Values:')
        print('Life:%d' % self.vitality)
        print('Attack:%d' % self.attack)
        print('Defence:%d' % self.defense)

    def initState(self, vitality, attack, defense):
        self.vitality = vitality
        self.attack = attack
        self.defense = defense

    def saveState(self):
        return Memento(self.vitality, self.attack, self.defense)

    def recoverState(self, memento):
        self.vitality = memento.vitality
        self.attack = memento.attack
        self.defense = memento.defense


# 实现具体的战斗接口
class FightCharactor(GameCharacter):
    """战斗类"""

    def fight(self):
        self.vitality -= random.randint(1, 10)


if __name__ == "__main__":
    game_chrctr = FightCharactor()
    game_chrctr.initState(100, 79, 60)
    game_chrctr.displayState()
    memento = game_chrctr.saveState()
    game_chrctr.fight()
    game_chrctr.displayState()
    game_chrctr.recoverState(memento)
    game_chrctr.displayState()
"""执行结果
    Current Values:
    Life:100
    Attack:79
    Defence:60
    Current Values:
    Life:94
    Attack:79
    Defence:60
    Current Values:
    Life:100
    Attack:79
    Defence:60
"""

11.状态模式(State Pattern)

        1.概述: 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类

        2.示例: 电梯控制器

class LiftState:
    """抽象电梯状态基类"""

    def open(self):
        pass

    def close(self):
        pass

    def run(self):
        pass

    def stop(self):
        pass


class OpenState(LiftState):
    """开放状态类"""

    def open(self):
        print("OPEN:The door is opened...")
        return self

    def close(self):
        print("OPEN:The door start to close...")
        print("OPEN:The door is closed")
        return StopState()

    def run(self):
        print("OPEN:Run Forbidden.")
        return self

    def stop(self):
        print("OPEN:Stop Forbidden.")
        return self


class RunState(LiftState):
    """运行状态类"""

    def open(self):
        print("RUN:Open Forbidden.")
        return self

    def close(self):
        print("RUN:Close Forbidden.")
        return self

    def run(self):
        print("RUN:The lift is running...")
        return self

    def stop(self):
        print("RUN:The lift start to stop...")
        print("RUN:The lift stopped...")
        return StopState()


class StopState(LiftState):
    """停止状态类"""

    def open(self):
        print("STOP:The door is opening...")
        print("STOP:The door is opened...")
        return OpenState()

    def close(self):
        print("STOP:Close Forbidden")
        return self

    def run(self):
        print("STOP:The lift start to run...")
        return RunState()

    def stop(self):
        print("STOP:The lift is stopped.")
        return self


class Context:
    """上下文调度状态记录类"""
    lift_state = ""

    def getState(self):
        return self.lift_state

    def setState(self, lift_state):
        self.lift_state = lift_state

    def open(self):
        self.setState(self.lift_state.open())

    def close(self):
        self.setState(self.lift_state.close())

    def run(self):
        self.setState(self.lift_state.run())

    def stop(self):
        self.setState(self.lift_state.stop())


if __name__ == "__main__":
    ctx = Context()
    ctx.setState(StopState())
    ctx.open()
    ctx.run()
    ctx.close()
    ctx.run()
    ctx.stop()
"""执行结果
    STOP:The door is opening...
    STOP:The door is opened...
    OPEN:Run Forbidden.
    OPEN:The door start to close...
    OPEN:The door is closed
    STOP:The lift start to run...
    RUN:The lift start to stop...
    RUN:The lift stopped...
"""
原文地址:https://www.cnblogs.com/tangxuecheng/p/13636296.html