设计模式

Python设计模式 设计模式的定义:为了解决面向对象系统中重要和重复的设计封装在一起的一种代码实现框架,可以使得代码更加易于扩展和调用

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

六大原则:

1.开闭原则:一个软件实体,如类,模块和函数应该对扩展开发,对修改关闭.既软件实体应尽量在不修改原有代码的情况下进行扩展.
 
2.里氏替换原则:所有引用父类的方法必须能透明的使用其子类的对象

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

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

5.迪米特法则:一个软件实体应该尽可能的少与其他实体相互作用

6.单一直责原则:不要存在多个导致类变更的原因.即一个类只负责一项职责

接口

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

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

from abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):
    @abstractmethod#定义抽象方法的关键字
    def pay(self,money):
        pass

    # @abstractmethod
    # def pay(self,money):
    #     raise NotImplementedError

class AiliPay(Payment):
    #子类继承接口,必须实现接口中定义的抽象方法,否则不能实例化对象
    def pay(self,money):
        print('使用支付宝支付%s元'%money)

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

单例模式

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

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

优点:对唯一实例的受控访问,相当于全局变量,但是又可以防止此变量被篡改

class Singleton(object):
    #如果该类已经有了一个实例则直接返回,否则创建一个全局唯一的实例
    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,name):
        if name:
            self.name = name

a = MyClass('a')
print(a)
print(a.name)

b = MyClass('b')
print(b)
print(b.name)

print(a)
print(a.name)

工厂模式(celery)

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

角色:工厂角色,抽象产品角色,具体产品角色

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

缺点:违反了单一职责原则,将创建逻辑集中到一个工厂里面,当要添加新产品时,违背了开闭原则

from abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):
    #抽象产品角色
    @abstractmethod
    def pay(self,money):
        pass



class AiliPay(Payment):
    #具体产品角色
    def __init__(self,enable_yuebao=False):
        self.enable_yuebao = enable_yuebao

    def pay(self,money):
        if self.enable_yuebao:
            print('使用余额宝支付%s元'%money)
        else:
            print('使用支付宝支付%s元'%money)

class ApplePay(Payment):
    # 具体产品角色
    def pay(self,money):
        print('使用苹果支付支付%s元'%money)

class PaymentFactory:
    #工厂角色
    def create_payment(self,method):
        if method == 'alipay':
            return AiliPay()
        elif method == 'yuebao':
            return AiliPay(True)
        elif method == 'applepay':
            return ApplePay()
        else:
            return NameError

p = PaymentFactory()
f = p.create_payment('yuebao')
f.pay(100)

观察者模式

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

角色:抽象主题,具体主题(发布者),抽象观察者,具体观察者(订阅者)

适用场景:当一个抽象模型有两个方面,其中一个方面依赖于另一个方面.将两者封装在独立的对象中以使它们各自独立的改变和复用

当一个对象的改变需要同时改变其他对象,而且不知道具体有多少对象以待改变

当一个对象必须通知其他对象,而又不知道其他对象是谁,即这些对象之间是解耦的

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

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

from abc import ABCMeta, abstractmethod

#抽象主题
class Oberserver(metaclass=ABCMeta):
    @abstractmethod
    def update(self):
        pass

#具体主题
class Notice:
    def __init__(self):
        self.observers = []

    def attach(self,obs):
        self.observers.append(obs)

    def detach(self,obs):
        self.observers.remove(obs)

    def notify(self):
        for obj in self.observers:
            obj.update(self)

#抽象观察者
class ManagerNotice(Notice):
    def __init__(self,company_info=None):
        super().__init__()
        self.__company_info = company_info

    @property
    def company_info(self):
        return self.__company_info

    @company_info.setter
    def company_info(self,info):
        self.__company_info = info
        self.notify()

#具体观察者
class Manager(Oberserver):
    def __init__(self):
        self.company_info = None
    def update(self,noti):
        self.company_info = noti.company_info

#消息订阅-发送
notice = ManagerNotice()

alex=Manager()
tony=Manager()

notice.attach(alex)
notice.attach(tony)
notice.company_info="公司运行良好"
print(alex.company_info)
print(tony.company_info)

notice.company_info="公司将要上市"
print(alex.company_info)
print(tony.company_info)

notice.detach(tony)
notice.company_info="公司要破产了,赶快跑路"
print(alex.company_info)
print(tony.company_info)