Python之设计模式

Stella981
• 阅读 762

一、设计模式分类

a、创建型模式

  • 简单工厂模式

    一、内容 不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。

    二、角色

    工厂角色(Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) 三、优点

    隐藏了对象创建的实现细节 客户端不需要修改代码 四、缺点

    违反了单一职责原则,将创建逻辑集中到一个工厂类中 当添加新产品时,需要修改工厂类代码,违反了开放封闭原则

代码实例:

Python之设计模式 Python之设计模式

from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self):
        pass

class Alipay(Payment):
    def __init__(self,money):
        self.money = money

    def pay(self):
        print('支付宝支付了%s元'%self.money)

class Whatpay(Payment):
    def __init__(self, money):
        self.money = money

    def pay(self):
        print('微信支付了%s元' % self.money)


obj = Alipay(100)
obj.pay()

obj2 = Whatpay(200)
obj2.pay()

初始的

from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self, money):
        print('支付宝支付了%s元'%money)

class Applepay(Payment):
    def pay(self, money):
        print('微信支付了%s元' %money)

class Yuebao(Payment):
    def pay(self,money):
        print('余额宝支付了%s元' %money)


class PaymentFactory:
    '''工厂类:封装了对象创建的细节'''
    def create_payment(self,method):
        if method =='alipay':
            return Alipay()
        elif method =='applepay':
            return Applepay()
        elif method =='yuebao':
            return Yuebao()
        else:
            return NameError(method)

factory = PaymentFactory()
alipay=factory.create_payment('yuebao')
alipay.pay(100)
  • 工厂方法模式

    一、内容

    定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类

    二、角色

    抽象工厂角色(Creator) 具体工厂角色(Concrere Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) 工厂方法模式相比简单工厂模式将每个具体产品都对应一个具体工厂

    三、优点

    每个具体产品都对应一个具体工厂类,不需要修改工厂类代码 隐藏了对象创建的实现细节 四、缺点

    每增加一个具体产品类,就必须增加一个相应的具体工厂类 五、使用场景

    需要生产多种、大量复杂对象的时候 需要降低耦合度的时候 当系统的产品种类需要经常扩展的时候

    from abc import ABCMeta,abstractmethod class PaymentFactory(metaclass=ABCMeta): @abstractmethod def create_payment(self): pass class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): pass class Alipay(Payment): def pay(self, money): print('支付宝支付了%s元'%money) class Applepay(Payment): def pay(self, money): print('微信支付了%s元' %money) class AlipayFactory(PaymentFactory): def create_payment(self): return Alipay() class AppleFactory(PaymentFactory): def create_payment(self): return Applepay() apple = AppleFactory() apple.create_payment().pay(100)

    alipay = AlipayFactory() alipay.create_payment().pay(300)

    #输出

    微信支付了100元

    支付宝支付了300元

  • 抽象工厂模式

    一、内容

    定义一个工厂类接口,当工厂子类来创建一系列相关或相互依赖的对象

    例:生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。

    二、角色

    抽象工厂角色(Creator) 具体工厂角色(Concrete Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) 客户端(Client) 相比工厂方法模式,抽象工厂模式中的每个具体工厂都产生一套产品

    三、优点

    将客户端与类的具体实现相分离 每个工厂创建了一个完整的产品系列,使得易于交换产品系列 有利于产品的一致性(即产品之间的约束关系) 四、缺点

    难以支持新种类的(抽象)产品 五、使用场景

    系统要独立于产品的创建与组合时

    强调一系列相关的产品对象的设计以便进行联合使用时

    提供一个产品类库,想隐藏产品的具体实现时

    from abc import abstractmethod,ABCMeta

    #==============抽象产品============ class PhoneShell(metaclass=ABCMeta): '''手机壳''' @abstractmethod def show_shell(self): pass class CPU(metaclass=ABCMeta): '''CPU''' @abstractmethod def show_cpu(self): pass class OS(metaclass=ABCMeta): '''操作系统''' @abstractmethod def show_os(self): pass

    ===============抽象工厂==============

    class PhoneFactory(metaclass=ABCMeta): @abstractmethod def make_shell(self): '''制作手机壳''' pass @abstractmethod def make_cpu(self): '''制作cpu''' pass @abstractmethod def make_os(self): '''制作手机壳''' pass

    =================具体产品==============

    class SmallShell(PhoneShell): def show_shell(self): print('普通手机小手机壳') class BigShell(PhoneShell): def show_shell(self): print('普通手机大手机壳') class AppleShell(PhoneShell): def show_shell(self): print('苹果手机壳') class YingTeerCPU(CPU): def show_cpu(self): print('英特尔cpu') class MediaCPU(CPU): def show_cpu(self): print('联发科cpu') class AppleCPU(CPU): def show_cpu(self): print('苹果cpu') class Android(OS): def show_os(self): print('Android系统') class IOS(OS): def show_os(self): print('ios系统')

    ==============具体工厂================

    class MiFactory(PhoneFactory): def make_shell(self): return SmallShell() def make_cpu(self): return AppleCPU() def make_os(self): return Android() class HuaWeiactory(PhoneFactory): def make_shell(self): return BigShell() def make_cpu(self): return YingTeerCPU() def make_os(self): return Android()

    ===============使用===============

    class Phone: def init(self,cpu,os,shell): self.cpu = cpu self.os = os self.shell = shell def show_info(self): print('手机信息') self.cpu.show_cpu() self.os.show_os() self.shell.show_shell() def make_phone(factory): cpu = factory.make_cpu() os = factory.make_os() shell = factory.make_shell() return Phone(cpu,os,shell) p1 = make_phone(HuaWeiactory()) p1.show_info()

    p2 = make_phone(MiFactory()) p2.show_info()

  • 创建者模式

    一、内容

    将一个复杂对象的构建与它表示分离,使得同样的构建过程可以创建不同的表示

    二、角色

    抽象建造者 具体建造者 指挥者 产品 建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。

    三、优点

    隐藏了一个产品的内部结构和装配过程 将构造代码与表示代码分开 可以将构建过程进行更精细的控制 五、使用场景

    当创建复杂对象的算法(Director)应该独立于该对象的组成部分以及它们的装配方式(Builder)时 当构造过程允许被构造的对象有不同的表示时(不同Builder)

    import random from abc import abstractmethod, ABCMeta

    #------产品------

    class Player: def init(self, face=None, body=None, arm=None, leg=None): self.face = face self.arm = arm self.leg = leg self.body = body def str(self): return "%s, %s, %s, %s" % (self.face, self.arm, self.body, self.leg) #------建造者------

    class PlayerBuilder(metaclass=ABCMeta): @abstractmethod def build_face(self): pass @abstractmethod def build_arm(self): pass @abstractmethod def build_leg(self): pass @abstractmethod def build_body(self): pass @abstractmethod def get_player(self): pass class BeautifulWomanBuilder(PlayerBuilder): def init(self): self.player = Player() def build_face(self): self.player.face = "漂亮脸蛋" def build_arm(self): self.player.arm="细胳膊" def build_body(self): self.player.body="细腰" def build_leg(self): self.player.leg="长腿" def get_player(self): return self.player class RandomPlayerBuilder(PlayerBuilder): def init(self): self.player = Player() def build_face(self): self.player.face = random.choice(["瓜子脸","西瓜子脸"]) def build_arm(self): self.player.arm=random.choice(["长胳膊","短胳膊"]) def build_body(self): self.player.body=random.choice(["苗条","胖"]) def build_leg(self): self.player.leg=random.choice(["长腿","短腿"]) def get_player(self): return self.player class PlayerDirector: def init(self, builder): self.builder = builder # 控制组装顺序 def build_player(self): self.builder.build_body() self.builder.build_face() self.builder.build_arm() self.builder.build_leg() return self.builder.get_player() pd = PlayerDirector(RandomPlayerBuilder()) p = pd.build_player() print(p)

  • 原型模式

  • 单例模式

总结创建型模式:

  依赖于继承的创建型模式:工厂方法模式

  依赖于组合的创建型模式:抽象工厂模式,创建者模式

二、什么是设计模式?

Python之设计模式

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样你就能一次又一次地使用该方案而不必做重复劳动。”

每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。

GoF(Gang of Four)

设计模式四个基本要素:模式名称、问题、解决方案、效果

三、设计模式七大原则

1、开放封闭原则:一个软件实体如类,模块和函数应该对扩展是开放的,对修改是关闭的。即软件实体应尽量在不修改原有代码的情况下进行扩展(装饰器)

2、里氏替换原则:重写父类里面的方法,逻辑可能不一样,但是返回的结果参数啥的要一样(所有引用基类的地方必须能透明的使用其子类的对象)

3、依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象,要针对接口编程,而不是针对实现编程。(接口类)

4、接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要实现的接口

5、迪米特法则:一个软件实体应当尽可能少的与其他实体发生相互作用

6、单一职责原则:一个类只负责一项职责(不要存在多于一个导致类变更的原因,即一个类只负责一项职责)

7、合同复用原则:多用组合少用继承

       一个类重用另一个类的代码有两种方式

  •  继承
  •  组合

a、下面来说一下接口隔离原则

Python之设计模式 Python之设计模式

#假如说现在有这样的动物类
from abc import abstractmethod,ABCMeta   #借助abc模块来实现接口
#接口类就是为了提供标准,约束后面的子类

# class Animal(metaclass=ABCMeta):
#     @abstractmethod
#     def walk(self):
#         pass
#
#     @abstractmethod
#     def fly(self):
#         pass
#
#     @abstractmethod
#     def swim(self):
#         pass
#
# class Frog(Animal):
#     '''像是这样定义一个青蛙类,由于接口类的方法都要被实现,而青蛙只会走,没不要要实现其他的方法
#     动物不同会的功能也会不同,所以这时候我们就可以选择用接口隔离原则
#     '''
#     def walk(self):
#         print('青蛙会走')
#
# obj = Frog()
# obj.walk()   #会报错


# =====================改进-=================
class AnimalOnLand(metaclass=ABCMeta):
    '''在陆地上的动物'''
    @abstractmethod
    def walk(self):
        pass

class AnimalInSky(metaclass=ABCMeta):
    '''飞行动物'''
    @abstractmethod
    def fly(self):
        pass

class AnimalInWater(metaclass=ABCMeta):
    '''在水里的动物'''
    @abstractmethod
    def swim(self):
        pass

class Tiger(AnimalOnLand):
    def walk(self):
        print('老虎在地上')

class Frog(AnimalOnLand,AnimalInWater):
    def swim(self):
        print('青蛙会游')

    def walk(self):
        print('会跳')

obj = Tiger()
obj.walk()

obj = Frog()
obj.walk()
obj.swim()

接口隔离原则

b、继承和组合

Python之设计模式 Python之设计模式

# 合同复用原则:多用组合少用继承
class A:
    def test(self):
        return '你好啊'

class B(A):  #继承
    def test(self):
        return 123

class C:
    def __init__(self):
        self.a = A()   #组合
        self.a.test()

    def test(self): 
        return 789

print(B().test())

print(C().a)
print(C().a.test())
print(C().test())

继承和组合示例

四、行为型模式:

  • 解释器模式

  • 责任链模式

    一、内容

    使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求

    直到有一个对象处理它为止

    二、角色

    抽象处理者 具体处理者 客户端 例:请假部门批准:项目主管----》部门经理----》总经理

    三、优点

    降低耦合度:一个对象无需知道是其他哪一个对象处理其请求 四、缺点

    请求不保证被接收:链的末端没有处理或者链配置错误 五、适用场景

    有多个对象可以处理一个请求,哪个对象处理由时间运行时决定 在不明确接受者的情况下,向多个对象中的一个提交一个请求

Python之设计模式 Python之设计模式

from abc import ABCMeta, abstractmethod
#
class Handler(metaclass=ABCMeta):
    @abstractmethod
    def handle_leave(self, day):
        pass


class GeneralManagerHandler(Handler):
    def handle_leave(self, day):
        if day < 10:
            print("总经理批准%d天假"%day)
        else:
            print("呵呵")


class DepartmentManagerHandler(Handler):
    def __init__(self):
        self.successor = GeneralManagerHandler()  #责任链的后面的一个人
    def handle_leave(self, day):
        if day < 7:
            print("部门经理批准%d天假"%day)
        else:
            print("部门经理无权准假")
            self.successor.handle_leave(day)


class ProjectDirectorHandler(Handler):
    def __init__(self):
        self.successor = DepartmentManagerHandler()
    def handle_leave(self, day):
        if day < 3:
            print("项目主管批准%d天假")
        else:
            print("项目主管无权准假")
            self.successor.handle_leave(day)


day = 4
h = ProjectDirectorHandler()
h.handle_leave(day)

请假示例

Python之设计模式 Python之设计模式

#--高级例子--模仿js事件处理
# JavaScript中假如有三个嵌套的div,每个div绑定一个事件,就像冒泡一样,先找里面的,
# 如果里面有就是里面的事件,如果里面没有就找上一层的。以此类推
from abc import ABCMeta, abstractmethod
class Handler(metaclass=ABCMeta):
    @abstractmethod
    def add_event(self, func):
        pass

    @abstractmethod
    def handle(self):
        pass


class BodyHandler(Handler):
    def __init__(self):
        self.func = None

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            print("已到最后一级,无法处理")


class ElementHandler(Handler):
    def __init__(self, successor):
        self.func = None
        self.successor = successor

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            return self.successor.handle()


# 客户端
# <body><div><a>

body = {'type': 'body', 'name': 'body', 'children': [], 'father': None}

div = {'type': 'div', 'name': 'div', 'children': [], 'father': body}

a = {'type': 'a', 'name': 'a', 'children': [], 'father': div}

body['children'].append(div)
div['children'].append(a)

body['event_handler'] = BodyHandler()
div['event_handler'] = ElementHandler(div['father']['event_handler'])
a['event_handler'] = ElementHandler(a['father']['event_handler'])


def attach_event(element, func):
    element['event_handler'].add_event(func)

#test

def func_div():
    print("这是给div的函数")

def func_a():
    print("这是给a的函数")

def func_body():
    print("这是给body的函数")

# attach_event(div, func_div)
attach_event(a, func_a)
# attach_event(body, func_body)
a['event_handler'].handle()

模仿js事件处理

  • 命令模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 访问者模式
  • 模板方法模式

五、结构性模式:

  • 适配器模式
  • 桥模式
  • 组合模式
  • 装饰模式
  • 外观模式
  • 享元模式
  • 代理模式
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这