zoukankan      html  css  js  c++  java
  • 设计模式

    一、单例模式

    python中的模块是最天然的单例模式

    单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

    单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。

    单例模式分3种:懒汉式单例、饿汉式单例、登记式单例。

    单例模式有以下3个特点:

    1. 只能有一个实例。

    2. 必须自行创建这个实例。

    3. 必须给其他对象提供这一实例。

    python中的单例

    1.1  使用new方法

    class SingleTon(object):
    
        def __new__(cls, *args, **kwargs):
            if not hasattr(cls, '_instance'):
                cls._instance = super(SingleTon, cls).__new__(cls, *args, **kwargs)
    
            return cls._instance
    
    
    class MyCls(SingleTon):
        a = 1
    
    
    a = MyCls()
    b = MyCls()
    print(id(a), id(b))

    1.2  共享属性

    创建实例时把所有实例的__dict__指向同一字典,这样他们具有相同的属性和方法

    class SingleTon(object):
        _state = {}
        def __new__(cls, *args, **kwargs):
            obj = super(SingleTon, cls).__new__(cls, *args, **kwargs)
            obj.__dict__ = cls._state
            return obj
    
    class MyCls(SingleTon):
        a=1

    1.3  装饰器版本

    def singleTon(cls,*args,**kwargs):
        instance={}
        def inner():
            if cls not in instance:
                instance[cls]=cls(*args,**kwargs)
            return instance[cls]
        return inner
    
    @singleTon
    class Mycls(object):
        pass
    a=Mycls()
    b=Mycls()
    print(a is b)

    二、工厂模式

    工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。

    使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地方(new处)修改了。为系统结构提供灵活的动态扩展机制,减少了耦合。

    # 由于python没有抽象类,接口这个概念,要实现抽象类或者接口需要通过abc模块来实现
    from abc import abstractclassmethod, ABCMeta
    
    
    class Animal(object):
        __metaclass__ = ABCMeta
    
        @abstractclassmethod
        def detail(self):
            pass
    
    
    class Human(Animal):
        def detail(self):
            print('这是人类')
    
    
    class Dog(Animal):
        def detail(self):
            print('这是狗')
    
    
    class SimpleFactory(object):
        @staticmethod
        def createHuman():
            return Human()
    
        @staticmethod
        def createDog():
            return Dog()
    
    
    SimpleFactory.createDog().detail()
    SimpleFactory.createHuman().detail()

    三、注册模式

    注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

    # 注册模式
    regObj = {}
    
    
    class Register(object):
        def set(self, cls):
            regObj[cls] = cls
    
        def get(self, cls):
            return regObj[cls]
    
        def unset(self, cls):
            regObj.pop(cls)

    四、策略模式

    策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择需要的算法并使用。

    策略模式指的是程序中涉及决策控制的一种模式。策略模式功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性思想。

    策略模式的三个角色:

    1. 抽象策略角色

    2. 具体策略角色

    3. 环境角色(对抽象策略角色的引用)

    实现步骤:
    1. 定义抽象角色类(定义好各个实现的共同抽象方法)

    2. 定义具体策略类(具体实现父类的共同方法)

    3. 定义环境角色类(私有化申明抽象角色变量,重载构造方法,执行抽象方法)

    就在编程领域之外,有许多例子是关于策略模式的。例如:

    如果我需要在早晨从家里出发去上班,我可以有几个策略考虑:我可以乘坐地铁,乘坐公交车,走路或其它的途径。每个策略可以得到相同的结果,但是使用了不同的资源。

    策略模式的代码实例:

    # 策略模式
    # 由于python没有抽象类,接口这个概念,要实现抽象类或者接口需要通过abc模块来实现
    from abc import abstractclassmethod, ABCMeta
    # 我们定义一个聚会的抽象类,然后再唱歌、吃饭策略
    class Gather(object):
        __metaclass__=ABCMeta
        @abstractclassmethod
        def haveFun(self):
            pass
    
    class Sing(Gather):
        def haveFun(self):
            print('唱歌')
    
    class Eat(Gather):
        def haveFun(self):
            print('吃饭')
    
    class Strategy(object):
        @staticmethod
        def selectWay(flag):
            if flag:
                return Sing()
            else:
                return Eat()
    
    Strategy.selectWay(True).haveFun()

    五、观察者模式

    1. 观察者模式(Observer),当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。

    2. 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。

    3. 观察者模式实现了低耦合,非侵入式的通知与更新机制。 定义一个事件触发抽象类。

    # 观察者模式
    class Observer(object):
        def __init__(self):
            self._observers = []
    
        # 添加观察者
        def attach(self, obs):
            if obs not in self._observers:
                self._observers.append(obs)
    
        # 取消添加观察者
        def detach(self, obs):
            if obs in self._observers:
                self._observers.remove(obs)
    
        # 通知观察者数据变化
        def notify(self, modifier=None):
            for obs in self._observers:
                if modifier != obs:
                    obs.update(self)
    
    
    class Data(Observer):
        def __init__(self, name=''):
            super(Data, self).__init__()
            self.name = name
            self._data = 0
    
        @property
        def data(self):
            return self._data
    
        @data.setter
        def data(self, value):
            self._data = value
            self.notify()
    
    
    # 这里有2个被观察者,也就是依赖的对象,每次Data有改变,这2个view都会变动
    class HexViewer(object):
        def update(self, subject):
            print('HexViewer: Subject %s has data 0x%x' % (subject.name, subject.data))
    
    
    class DecimalViewer(object):
        def update(self, subject):
            print('DecimalViewer: Subject %s has data %d' % (subject.name, subject.data))
    
    if __name__ == '__main__':
        data1 = Data('Data 1')
        data2 = Data('Data 2')
        view1 = DecimalViewer()
        view2 = HexViewer()
        data1.attach(view1)
        data1.attach(view2)
        data2.attach(view2)
        data2.attach(view1)
    
        print ("Setting Data 1 = 10")
        data1.data = 10
        print ("Setting Data 2 = 15")
        data2.data = 15
        print ("Setting Data 1 = 3")
        data1.data = 3
        print ("Setting Data 2 = 5")
        data2.data = 5
        print ("Update data1's view2 Because view1 is be filtered")
        data1.notify(modifier=view1)
        print ("Detach HexViewer from data1 and data2.")
        data1.detach(view2)
        data2.detach(view2)
        print ("Setting Data 1 = 10")
        data1.data = 10
        print ("Setting Data 2 = 15")
        data2.data = 15
  • 相关阅读:
    锚的应用
    有关于MP3音频文件的编码解码资料吗
    自定义web.config配置节 (转)
    HTC 文件
    Asp.Net音频文件上传和播放
    dotnet下用c#编写下载器
    自动滚屏代码
    agsXMPP分析:agsXMPP Namespace
    Socket网络编程学习笔记(1)
    (♂)程序打包工具setup2go使用教程
  • 原文地址:https://www.cnblogs.com/qflyue/p/9065396.html
Copyright © 2011-2022 走看看