zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    20.12.21 leetcode316
    20.12.18 leetcode389
    NOIP2017退役记
    DNA序列 LOJ NOIP模拟赛 D1T1 字符串哈希
    解药还是毒药 codevs2594 状态压缩 BFS
    换教室 vijos2005 NOIP2016 D1T3 期望DP 图论最短路(雾)
    都市大飙车 UESTC 1652 概率DP
    添加括号 vijos1038 动态规划 区间DP
    一道神奇的并查集
    还有一道神奇的暴力(正解是要旋转坐标轴的)
  • 原文地址:https://www.cnblogs.com/jasonwang-2016/p/5987660.html
Copyright © 2011-2022 走看看