设计模式

一、单例模式

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

 

posted @ 2018-05-21 01:43  二十四桥明月夜33  阅读(387)  评论(0编辑  收藏  举报