您的位置:首页 > 编程语言 > Python开发

几种常见的设计模式之 python 实现

2017-08-18 08:58 627 查看
转载借鉴于 五岳

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

'''
简单工厂
4000
模式

模式特点:工厂根据条件产生不同功能的类。
只生产单一类别的东西
程序实例:四则运算计算器,根据用户的输入产生相应的运算类,用这个运算类处理具体的运算。

'''
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息