Python设计模式

一.简单工厂模式

首先来看下工厂模式的原理图:

模式特点:工厂根据条件产生不同功能的类。

程序实例:四则运算计算器,根据用户的输入产生相应的运算类,用这个运算类处理具体的运算。

代码特点:C/C++中的switch...case...分支使用字典的方式代替。

     使用异常机制对除数为0的情况进行处理。

Python实现代码如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class Operation:
    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 = self.op1/self.op2
            return result
        except:
            print("error:divided by zero.")
            return 0

class OperationUndef(Operation):
    def GetResult(self):
        print("Undefine operation.")
        return 0

class OperationFactory:
    operation = {}
    operation["+"] = OperationAdd();
    operation["-"] = OperationSub();
    operation["*"] = OperationMul();
    operation["/"] = OperationDiv();
    def createOperation(self,ch):
        if ch in self.operation:
            op = self.operation[ch]
        else:
            op = OperationUndef()
        return op

if __name__ == "__main__":
    op = input("operator: ")
    opa = input("a: ")
    opb = input("b: ")
    factory = OperationFactory()
    cal = factory.createOperation(op)
    cal.op1 = int(opa)
    cal.op2 = int(opb)
    print(cal.GetResult())
简单工程模式

二.单例模式

原理图:

模式特点:保证类仅有一个实例,并提供一个访问它的全局访问点。

说明:     为了实现单例模式费了不少工夫,后来查到一篇博文对此有很详细的介绍,而且实现方式也很丰富,通过对代码的学习可以了解更多Python的用法。

我要问的是,Python真的需要单例模式吗?我指像其他编程语言中的单例模式。

答案是:不需要!

因为,Python有模块(module),最pythonic的单例典范。

模块在在一个应用程序中只有一份,它本身就是单例的,将你所需要的属性和方法,直接暴露在模块中变成模块的全局变量和方法即可!

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang
#-*- 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)
#3
#one和two完全相同,可以用id(), ==, is检测
print(id(one))
#29097904
print(id(two))
#29097904
print(one == two)
#True
print(one is two)
#True

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)
#3
print(id(one))
#28873680
print(id(two))
#28873712
print(one == two)
#False
print(one is two)
#False
#但是one和two具有相同的(同一个__dict__属性),见:
print(id(one.__dict__))
#30104000
print(id(two.__dict__))
#30104000

print('----------------------方法3--------------------------')
##通过类的静态字段构造类
class CP:
    __instance = None
    def __init__(self):
        self.ip = "1.1.1.1"
        self.port = 3306
        self.pwd = "123123"
        self.user = "xxx"
        self.conn_list = [1,2,3,4,5,6]
    @staticmethod
    def get_instance():
        if CP.__instance:
            return CP.__instance
        else:
            # 创建一个对象,并将对象赋值给静态字段__instance
            CP.__instance = CP() #执行init方且创建对象,并赋值给私有静态字段
            return CP.__instance #将赋值的返回给私有静态字段

obj1 = CP.get_instance() # 静态字段类调用
print(obj1)

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)
#3
print(id(one))
#29660784
print(id(two))
#29660784
print(one == two)
#True
print(one is two)
#True
one.x = 1
print(one.x)
#1
print(two.x)
#1
单例模式

三.策略模式 

原理图:

模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端。

程序实例:商场收银软件,需要根据不同的销售策略方式进行收费

代码特点:不同于同例1,这里使用字典是为了避免关键字不在字典导致bug的陷阱。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class CashSuper:
    def AcceptCash(self,money):
        return 0

class CashNormal(CashSuper):
    def AcceptCash(self,money):
        return money

class CashRebate(CashSuper):
    discount = 0
    def __init__(self,ds):
        self.discount = ds
    def AcceptCash(self,money):
        return money * self.discount

class CashReturn(CashSuper):
    total = 0;
    ret = 0;
    def __init__(self,t,r):
        self.total = t
        self.ret = r
    def AcceptCash(self,money):
        if (money>=self.total):
            return money - self.ret
        else:
            return money

class CashContext:
    def __init__(self,csuper):
        self.cs = csuper
    def GetResult(self,money):
        return self.cs.AcceptCash(money)

if __name__ == "__main__":
    money = input("money:")
    strategy = {}
    strategy['1'] = CashContext(CashNormal())
    strategy['2'] = CashContext(CashRebate(0.8))
    strategy['3'] = CashContext(CashReturn(300,100))
    ctype = input("type:[1]for normal,[2]for 80% discount [3]for 300 -100.")
    print()
    print(strategy.keys())
    if ctype in strategy.keys():
        cc = strategy[ctype]
    else:
        print("Undefine type.Use normal mode.")
        cc = strategy[1]
    print("you will pay:%d" %(cc.GetResult(int(money))))
策略模式

四.装饰模式

原理图:

模式特点:动态地为对象增加额外的职责

程序实例:展示一个人一件一件穿衣服的过程。

代码特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class Person:
    def __init__(self,tname):
        self.name = tname
    def Show(self):
       print("dressed %s" %(self.name))

class Finery(Person):
    componet = None
    def __init__(self):
        pass
    def Decorate(self,ct):
        self.componet = ct
    def Show(self):
        if(self.componet!=None):
            self.componet.Show()

class TShirts(Finery):
    def __init__(self):
        pass
    def Show(self):
        print("Big T-shirt ")
        self.componet.Show()

class BigTrouser(Finery):
    def __init__(self):
        pass
    def Show(self):
        print("Big Trouser ")
        self.componet.Show()

if __name__ == "__main__":
    p = Person("somebody")
    bt = BigTrouser()
    ts = TShirts()
    bt.Decorate(p)
    ts.Decorate(bt)
    ts.Show()
装饰模式

 四、代理模式

原理图:

模式特点:为其他对象提供一种代理以控制对这个对象的访问。

程序实例:同模式特点描述。

代码特点:无

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()
proxy

五、工厂方法模式

原理图:

模式特点:定义一个用于创建对象的接口,让子类决定实例化哪一个类。这使得一个类的实例化延迟到其子类。

程序实例:基类雷锋类,派生出学生类和志愿者类,由这两种子类完成“学雷锋”工作。子类的创建由雷锋工厂的对应的子类完成。

代码特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class LeiFeng:
    def Sweep(self):
        print("LeiFeng sweep")

class Student(LeiFeng):
    def Sweep(self):
        print("Student sweep")

class Volenter(LeiFeng):
    def Sweep(self):
        print("Volenter sweep")

class LeiFengFactory:
    def CreateLeiFeng(self):
        temp = LeiFeng()
        return temp

class StudentFactory(LeiFengFactory):
    def CreateLeiFeng(self):
        temp = Student()
        return temp

class VolenterFactory(LeiFengFactory):
    def CreateLeiFeng(self):
        temp = Volenter()
        return temp

if __name__ == "__main__":
    sf = StudentFactory()
    s=sf.CreateLeiFeng()
    s.Sweep()
    sdf = VolenterFactory()
    sd=sdf.CreateLeiFeng()
    sd.Sweep()
Factory

六、原型模式

模式特点:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

程序实例:从简历原型,生成新的简历

代码特点:简历类Resume提供的Clone()方法其实并不是真正的Clone,只是为已存在对象增加了一次引用。

     Python为对象提供的copy模块中的copy方法和deepcopy方法已经实现了原型模式,但由于例子的层次较浅,二者看不出区别。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

import copy
class WorkExp:
    place=""
    year=0

class Resume:
    name = ''
    age = 0
    def __init__(self,n):
        self.name = n
    def SetAge(self,a):
        self.age = a
    def SetWorkExp(self,p,y):
        self.place = p
        self.year = y
    def Display(self):
        print(self.age)
        print(self.place)
        print(self.year)
    def Clone(self):
    #实际不是“克隆”,只是返回了自身
        return self

if __name__ == "__main__":
    a = Resume("a")
    b = a.Clone()
    c = copy.copy(a)
    d = copy.deepcopy(a)
    a.SetAge(7)
    b.SetAge(12)
    c.SetAge(15)
    d.SetAge(18)
    a.SetWorkExp("PrimarySchool",1996)
    b.SetWorkExp("MidSchool",2001)
    c.SetWorkExp("HighSchool",2004)
    d.SetWorkExp("University",2007)
    a.Display()
    b.Display()
    c.Display()
    d.Display()
    print('a id is %s' %id(a))
    print('b id is %s' %id(b))
    print('c id is %s' %id(c))
    print('d id is %s' %id(d))
###运行结果
"""
12
MidSchool
2001
12
MidSchool
2001
15
HighSchool
2004
18
University
2007
a id is 4323180160
b id is 4323180160
c id is 4323180216
d id is 4323180384
"""
原型模式

七、模板方法模式

原理图:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class TestPaper:
    def TestQuestion1(self):
        print("Test1:A. B. C. D.")
        print("(%s)" %self.Answer1())

    def TestQuestion2(self):
        print("Test1:A. B. C. D.")
        print("(%s)" %self.Answer2())
    def Answer1(self):
        return ""
    def Answer2(self):
        return ""

class TestPaperA(TestPaper):
    def Answer1(self):
        return "B"
    def Answer2(self):
        return "C";

class TestPaperB(TestPaper):
    def Answer1(self):
        return "D"
    def Answer2(self):
        return "D";

if __name__ == "__main__":
    s1 = TestPaperA()
    s2 = TestPaperB()
    print("student 1")
    s1.TestQuestion1()
    s1.TestQuestion2()
    print("student 2")
    s2.TestQuestion1()
    s2.TestQuestion2()
Templte

八、外观模式

原理图:

模式特点:为一组调用提供一致的接口。

程序实例:接口将几种调用分别组合成为两组,用户通过接口调用其中的一组。

代码特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang
class SubSystemOne:
    def MethodOne(self):
        print("SubSysOne")

class SubSystemTwo:
    def MethodTwo(self):
        print("SubSysTwo")

class SubSystemThree:
    def MethodThree(self):
        print("SubSysThree")

class SubSystemFour:
    def MethodFour(self):
        print("SubSysFour")


class Facade:
    def __init__(self):
        self.one = SubSystemOne()
        self.two = SubSystemTwo()
        self.three = SubSystemThree()
        self.four = SubSystemFour()
    def MethodA(self):
        print("MethodA")
        self.one.MethodOne()
        self.two.MethodTwo()
        self.four.MethodFour()
    def MethodB(self):
        print("MethodB")
        self.two.MethodTwo()
        self.three.MethodThree()

if __name__ == "__main__":
    facade = Facade()
    facade.MethodA()
    facade.MethodB()
Foreign_interface

九、建造者模式

模式特点:将一个复杂对象的构建(Director)与它的表示(Builder)分离,使得同样的构建过程可以创建不同的表示(ConcreteBuilder)。

程序实例:“画”出一个四肢健全(头身手腿)的小人

代码特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class Person:
    def CreateHead(self):
        pass
    def CreateHand(self):
        pass
    def CreateBody(self):
        pass
    def CreateFoot(self):
        pass

class ThinPerson(Person):
    def CreateHead(self):
        print("thin head")
    def CreateHand(self):
        print("thin hand")
    def CreateBody(self):
        print("thin body")
    def CreateFoot(self):
        print("thin foot")

class ThickPerson(Person):
    def CreateHead(self):
        print("thick head")
    def CreateHand(self):
        print("thick hand")
    def CreateBody(self):
        print("thick body")
    def CreateFoot(self):
        print("thick foot")

class Director:
    def __init__(self,temp):
        self.p = temp
    def Create(self):
        self.p.CreateHead()
        self.p.CreateBody()
        self.p.CreateHand()
        self.p.CreateFoot()

if __name__ == "__main__":
    p = ThickPerson()
    d = Director(p)
    d.Create()
Build_style

十、观察者模式

模式特点:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,当主题对象状态发生变化时会通知所有观察者。

程序实例:公司里有两种上班时趁老板不在时偷懒的员工:看NBA的和看股票行情的,并且事先让老板秘书当老板出现时通知他们继续做手头上的工作。

程序特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

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("xh",p)
    s2 = NBAObserver("wyt",p)
    p.Attach(s1);
    p.Attach(s2);
    p.action = "WARNING:BOSS ";
    p.Notify()
observer_mode

 十一、抽象工厂模式

原理图:

模式特点:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类。

程序实例:提供对不同的数据库访问的支持。

     IUser和IDepartment是两种不同的抽象产品,它们都有Access和SQL Server这两种不同的实现;IFactory是产生IUser和IDepartment的抽象工厂,根据具体实现(AccessFactory和SqlFactory)产生对应的具体的对象(CAccessUser与CAccessDepartment,或者CSqlUser与CSqlDepartment)。

代码特点:无

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#  Author: Jason Wang

class IUser:
    def GetUser(self):
        pass
    def InsertUser(self):
        pass

class IDepartment:
    def GetDepartment(self):
        pass
    def InsertDepartment(self):
        pass

class CAccessUser(IUser):
    def GetUser(self):
        print("Access GetUser")
    def InsertUser(self):
        print("Access InsertUser")


class CAccessDepartment(IDepartment):
    def GetDepartment(self):
        print("Access GetDepartment")
    def InsertDepartment(self):
        print("Access InsertDepartment")

class CSqlUser(IUser):
    def GetUser(self):
        print("Sql GetUser")
    def InsertUser(self):
        print("Sql InsertUser")


class CSqlDepartment(IDepartment):
    def GetDepartment(self):
        print("Sql GetDepartment")
    def InsertDepartment(self):
        print("Sql InsertDepartment")

class IFactory:
    def CreateUser(self):
        pass
    def CreateDepartment(self):
        pass

class AccessFactory(IFactory):
    def CreateUser(self):
        temp=CAccessUser()
        return temp
    def CreateDepartment(self):
        temp = CAccessDepartment()
        return temp

class SqlFactory(IFactory):
    def CreateUser(self):
        temp = CSqlUser()
        return temp
    def CreateDepartment(self):
        temp = CSqlDepartment()
        return temp

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


##
"""
Sql GetUser
Sql GetDepartment
"""
abstract
原文地址:https://www.cnblogs.com/jasonwang-2016/p/5987660.html