幾種常見的設計模式之 python 實現

轉載借鑑於 五嶽

http://www.cnblogs.com/wuyuegb2312/archive/2013/04/09/3008320.html

一、單例模式 -  四種方式

# coding=utf-8
# 單例模式(四種方法)

#-*- encoding=utf-8 -*-
print '----------------------方法1--------------------------'
#方法1,實現__new__方法
#並在將一個類的實例綁定到類變量_instance上,
#如果cls._instance爲None說明該類還沒有實例化過,實例化該類,並返回
#如果cls._instance不爲None,直接返回cls._instance
class Singleton(object):
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance

class MyClass(Singleton):
    a = 1

one = MyClass()
two = MyClass()
two.a = 3
print one.a
print id(one)
print id(two)
print one == two
print one is two


print '----------------------方法2--------------------------'
#   方法2,共享屬性;所謂單例就是所有引用(實例、對象)擁有相同的狀態(屬性)和行爲(方法)
#   同一個類的所有實例天然擁有相同的行爲(方法),
#   只需要保證同一個類的所有實例具有相同的狀態(屬性)即可
#   所有實例共享屬性的最簡單最直接的方法就是__dict__屬性指向(引用)同一個字典(dict)
#   可參看:http://code.activestate.com/recipes/66531/
class Borg(object):
    _state = {}
    def __new__(cls, *args, **kw):
        ob = super(Borg, cls).__new__(cls, *args, **kw)
        ob.__dict__ = cls._state
        return ob

class MyClass2(Borg):
    a = 1

one = MyClass2()
two = MyClass2()

#one和two是兩個不同的對象,id, ==, is對比結果可看出
two.a = 3
print one.a
print id(one)
print id(two)
print one == two
print one is two
print id(one.__dict__)
print id(two.__dict__)


print '----------------------方法3--------------------------'
#   方法3:本質上是方法1的升級(或者說高級)版
#   使用__metaclass__(元類)的高級python用法
class Singleton2(type):
    def __init__(cls, name, bases, dict):
        super(Singleton2, cls).__init__(name, bases, dict)
        cls._instance = None
    def __call__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = super(Singleton2, cls).__call__(*args, **kw)
        return cls._instance

class MyClass3(object):
    __metaclass__ = Singleton2

one = MyClass3()
two = MyClass3()

two.a = 3
print one.a
print id(one)
print id(two)
print one == two
print one is two


print '----------------------方法4--------------------------'
#   方法4:也是方法1的升級(高級)版本,
#   使用裝飾器(decorator),
#   這是一種更pythonic,更elegant的方法,
#   單例類本身根本不知道自己是單例的,因爲他本身(自己的代碼)並不是單例的
def singleton(cls, *args, **kw):
    instances = {}
    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return _singleton

@singleton
class MyClass4(object):
    a = 1
    def __init__(self, x=0):
        self.x = x


one = MyClass4()
two = MyClass4()

two.a = 3
print one.a
print id(one)
print id(two)
print one == two
print one is two
one.x = 1
print one.x
print two.x


二、代理模式

# coding:utf-8

'''
代理模式

模式特點:爲其他對象提供一種代理以控制對這個對象的訪問。

程序實例:同模式特點描述。

'''

class Interface :
    def Request(self):
        return 0

class RealSubject(Interface):
    def Request(self):
        print "Real request."

class Proxy(Interface):
    def Request(self):
        self.real = RealSubject()
        self.real.Request()

if __name__ == "__main__":
    p = Proxy()
    p.Request()

三、觀察者模式

# coding:utf-8

'''
觀察者模式

模式特點:定義了一種一對多的關係,讓多個觀察對象同時監聽一個主題對象,當主題對象狀態發生變化時會通知所有觀察者。

程序實例:公司裏有兩種上班時趁老闆不在時偷懶的員工:看NBA的和看股票行情的,並且事先讓老闆祕書當老闆出現時通知他們繼續做手頭上的工作。

程序特點:無

'''
# 抽象類
class Observer:
    def __init__(self,strname,strsub):
        self.name = strname
        self.sub = strsub
    def Update(self):
        pass


# 具體類
class StockObserver(Observer):
    #no need to rewrite __init__()
    def Update(self):
        print "%s:%s,stop watching Stock and go on work!" %(self.name,self.sub.action)


# 具體類
class NBAObserver(Observer):
    def Update(self):
        print "%s:%s,stop watching NBA and go on work!" %(self.name,self.sub.action)

# 相當於消息更新接口
class SecretaryBase:
    def __init__(self):
        self.observers = []
    def Attach(self,new_observer):
        pass

    def Notify(self):
        pass

# 具體接口
class Secretary(SecretaryBase):
    def Attach(self,new_observer):
        self.observers.append(new_observer)

    def Notify(self):
        for p in self.observers:
            p.Update()

if __name__ == "__main__":
    p = Secretary()
    s1 = StockObserver("observer1",p)
    s2 = NBAObserver("observer2",p)
    p.Attach(s1)
    p.Attach(s2)
    p.action = "warning: BOSS is coming! "
    p.Notify()

四、適配器模式

# coding:utf-8

'''
適配器模式

模式特點:將一個類的接口轉換成爲客戶希望的另外一個接口。

程序實例:用戶通過適配器使用一個類的方法。

代碼特點:無

所謂適配器模式是指是一種接口適配技術,它可通過某個類來使用另一個接口與之不兼容的類,運用此模式,兩個類的接口都無需改動。
適配器模式主要應用於希望複用一些現存的類,但是接口又與複用環境要求不一致的情況,比如在需要對早期代碼複用一些功能等應用上很有實際價值。
其中Target是用戶期望的標準類,而Adaptee是我們需要匹配的類,二者通過Adapter匹配起來。
'''

# 期望輸出類
class Target(object):
    def request(self):
        print 'Target request'


# 被適配類
class Adaptee(object):
    def specialRequest(self):
        print 'Adaptee specialRequest'


# 適配器
class Adpater(object):
    def __init__(self, adpatee):
        self.adpatee = adpatee

    def request(self):
        self.adpatee.specialRequest()


if __name__ == '__main__':
    objects = []
    a = Target()
    b = Adaptee()

    objects.append(a)
    objects.append(Adpater(b))  # 適配接口

    for obj in objects:
        obj.request()           # 調用相同接口

'''
輸出:
C:\Python27\python.exe E:/codepy/designMode/adapterMode.py
Target request
Adaptee specialRequest

調用了相同的接口,但是卻實現了特殊類的輸出,即被適配的類通過通用接口也可以輸出
'''

五、簡單工廠模式

# coding:utf-8

'''
簡單工廠模式

模式特點:工廠根據條件產生不同功能的類。
         只生產單一類別的東西
程序實例:四則運算計算器,根據用戶的輸入產生相應的運算類,用這個運算類處理具體的運算。

'''
class Operation(object):
    def GetResult(self):
        pass


# '+'操作符
class OperationAdd(Operation):
    def GetResult(self):
        return self.op1 + self.op2


# '-'操作符
class OperationSub(Operation):
    def GetResult(self):
        return self.op1 - self.op2


# '*'操作符
class OperationMul(Operation):
    def GetResult(self):
        return self.op1 + self.op2


# '/'操作符
class OperationDiv(Operation):
    def GetResult(self):
        try:
            # 浮點除法
            result = float(self.op1)/self.op2
            return result
        except:
            print "Error: divided by 0."
            return

# 未定義運算符
class OperationUnknown(Operation):
    def GetResult(self):
        return "this is an unknown operation"


class OperationFactory(object):
    ops = {}
    ops['+'] = OperationAdd()
    ops['-'] = OperationSub()
    ops['*'] = OperationMul()
    ops['/'] = OperationDiv()

    def CreateOp(self, ch):
        if ch in self.ops:
            op = self.ops[ch]
        else:
            op = OperationUnknown()
        return op

# 測試
if __name__ == '__main__':

    op1 = input("a: ")
    op = raw_input("Operation: ")
    op2 = input("b: ")

    factory = OperationFactory()
    cal = factory.CreateOp(op)
    cal.op1 = op1
    cal.op2 = op2

    print cal.GetResult()



六、抽象工廠模式

# coding:utf-8

'''
抽象工廠模式

模式特點:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們的類。

程序實例:提供對不同的數據庫訪問的支持。

     IUser和IDepartment是兩種不同的抽象產品,它們都有mysql 和redis這兩種不同的實現;
         IFactory是產生IUser和IDepartment的抽象工廠,
         根據具體實現(mysqlFactory和redisFactory)產生對應的具體的對象(mysqlUser與mysqlDepartment或者redisUser與redisDepartment)。

抽象工廠與簡單工程的區別:
    簡單工廠 :用來生產同一等級結構中的任意產品。(對於增加新的產品,無能爲力)
    工廠方法 :用來生產同一等級結構中的固定產品。(支持增加任意產品)   
    抽象工廠 :用來生產不同產品族的全部產品。(對於增加新的產品,無能爲力;支持增加產品族) 
      
'''

# 抽象產品
class IUser:
    def GetUser(self):
        pass
    def InsertUser(self):
        pass

# 抽象產品
class IDepartment:
    def GetDepartment(self):
        pass
    def InsertDepartment(self):
        pass

# 實現
class mysqlUser(IUser):
    def GetUser(self):
        print "mysql GetUser"
    def InsertUser(self):
        print "mysql InsertUser"

# 實現
class mysqlDepartment(IDepartment):
    def GetDepartment(self):
        print "mysql GetDepartment"
    def InsertDepartment(self):
        print "mysql InsertDepartment"

# 實現
class redisUser(IUser):
    def GetUser(self):
        print "redis GetUser"
    def InsertUser(self):
        print "redis InsertUser"

# 實現
class redisDepartment(IDepartment):
    def GetDepartment(self):
        print "redis GetDepartment"
    def InsertDepartment(self):
        print "redis InsertDepartment"

# 抽象工廠
class IFactory:
    def CreateUser(self):
        pass
    def CreateDepartment(self):
        pass

# 具體工廠
class mysqlFactory(IFactory):
    def CreateUser(self):
        temp = mysqlUser()
        return temp
    def CreateDepartment(self):
        temp = mysqlDepartment()
        return temp

# 具體工廠
class redisFactory(IFactory):
    def CreateUser(self):
        temp = redisUser()
        return temp
    def CreateDepartment(self):
        temp = redisDepartment()
        return temp

if __name__ == "__main__":
    factory = redisFactory()
    user = factory.CreateUser()
    depart = factory.CreateDepartment()
    user.GetUser()
    depart.GetDepartment()


七、生產者-消費者模式 (採用協程實現)來自廖大:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000


import time

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        time.sleep(1)
        r = '200 OK'

def produce(c):
    c.next()
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

if __name__=='__main__':
    c = consumer()
    produce(c)

結果:

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章