Python常用的设计模式(代码实现)和应用场景

三种最基本的设计模式:

  1. 创建模式,提供实例化的方法,为适合的状况提供相应的对象创建方法。
  2. 结构化模式,通常用来处理实体之间的关系,使得这些实体能够更好地协同工作。
  3. 行为模式,用于在不同的实体建进行通信,为实体之间的通信提供更容易,更灵活的通信方法。

设计模式的六大原则

  1. 开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
  2. 里氏(Liskov)替换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
  3. 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
  4. 接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
  5. 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用。
  6. 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
创建型模式
  1. 单例模式
    单例模式(Singleton Pattern)目的是确保某一个类只有一个实例存在。
    实现单例有多种方法:装饰器,_new_, metaClass, import
    每一个python模块都是天生的单例模式
### 单例模式
class Singleton(object):
    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls)
        return cls._instance


ob_1 = Singleton()
ob_2 = Singleton()
print(id(ob_1), id(ob_2))
  1. 工厂模式
    当以下情形可以使用工厂模式:
    1.不知道用户想要创建什么样的对象
    2.当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间。
    工厂模式有很多种实现类型,下面只介绍一种工厂方法模式
### 工厂模式
class Person:
    def __init__(self):
        self.name = None
        self.gender = None
        
    def getName(self):
        return self.name

    def getGender(self):
        return self.gender


class Male(Person):
    def __init__(self, name):
        super().__init__()
        print(f'Mr.{name}')


class Female(Person):
    def __init__(self, name):
        super().__init__()
        print(f"Miss.{name}")


class PersonFactory:
    @staticmethod
    def getPerson(name, gender):
        if gender == "M":
            return Male(name)
        if gender == "F":
            return Female(name)


ob_1 = PersonFactory.getPerson("big", "M")
ob_2 = PersonFactory.getPerson("bigTwo", "F")
  1. 原型模式
    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    浅拷贝(Shallow Copy):指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝的对象和源对象只是名称相同,但是他们共用一个实体。
    深拷贝(deep copy):对对象实例中字段引用的对象也进行拷贝。
### 原型模式
import copy


class Book:
    def __init__(self, *args, **kwargs):
        self.__dict__.update(kwargs)

    def __str__(self):
        return str(sorted(self.__dict__.items()))


class ProtoType:
    def __init__(self):
        self.objects = dict()

    def register(self, nid, obj):
        self.objects[nid] = obj

    def unregister(self, nid):
        del self.objects[nid]

    def clone(self, nid, **attr):
        found = self.objects.get(nid)
        if not found:
            raise ValueError(f"{nid} No exist")
        obj = copy.deepcopy(found)
        obj.__dict__.update(attr)
        return obj


b_1 = Book("aaa", k="kkk", b="bbb")
prototype = ProtoType()
prototype.register("b_1", b_1)
b_2 = prototype.clone("b_1", e="eee", d="ddd")
print(b_1)
print(b_2)
print(id(b_1))
print(id(b_2))

  1. 建造者模式
    包括一个限定方法抽象类,多个实际建造者类,一个指挥者类
    以下情况适用:
    1.当创建复杂对象的算法(Director)应该独立于该对象的组成部分以及它们的装配方式(Builder)时
    2.当构造过程允许被构造的对象有不同的表示时(不同Builder)。
### 建造者模式
from abc import ABCMeta, abstractmethod

class Builder:
    _metaClass_ = ABCMeta

    @abstractmethod
    def draw_body(self):
        pass


class FatCreator(Builder):
    def __init__(self):
        ...

    def draw_body(self):
        print(f'画胖子')


class ThinCreator(Builder):
    def __init__(self):
        pass

    def draw_body(self):
        print(f'画瘦子')


class Director:
    def __init__(self, obj):
        self.obj = obj

    def draw(self):
        self.obj.draw_body()


fat = FatCreator()
Director(fat).draw()
结构型模式
  1. 适配器模式
    所谓适配器模式是指是一种接口适配技术,它可通过某个类来使用另一个接口与之不兼容的类,运用此模式,两个类的接口都无需改动。

适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。

### 适配器模式
class Target:
    def request(self):
        print("普通请求")


class Adaptee:
    def special_request(self):
        print("特殊请求")


class Adapter(Target):
    def __init__(self):
        self.adaptee = Adaptee()

    def request(self):
        self.adaptee.special_request()

target= Adapter()
target.request()
  1. 修饰器模式
    Python种经典的模式,用来拓展类的功能
### 装饰器模式
import functools


def memoize(fn):
    know = dict()
    @functools.wraps(fn)
    def memoizer(*args):
        if args not in know:
            know[args] = fn(*args)
        return know[args]
    return memoizer

@memoize
def nsum(n):
    """
    返回前那个数的和
    :param n:
    :return:
    """
    assert (n >= 0), 'n must be >= 0'
    return 0 if n == 0 else n + nsum(n-1)

@memoize
def fibonacci(n):
    """
    返回斐波那契数列的第n个数
    :param n:
    :return:
    """
    assert n >= 0 and isinstance(n, int), 'n must be int and >= 0'
    return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2)


from timeit import Timer
measure = [{'exec': 'fibonacci(100)', 'import': 'fibonacci', 'func': fibonacci},
            {'exec': 'nsum(10)', 'import': 'nsum', 'func': nsum}]
for m in measure:
    t = Timer(f'{m["exec"]}', f'from __main__ import {m["import"]}')
    print('name: {} \ndoc: {} \nexecuting: {} \n time:{}'.format(m['func'].__name__, m['func'].__doc__, m['exec'], t.timeit()))                                                                                            
  1. 享元模式
    运用共享技术有效地支持大量细粒度的对象。
    内部状态:享元对象中不会随环境改变而改变的共享部分。比如围棋棋子的颜色。
    外部状态:随环境改变而改变、不可以共享的状态就是外部状态。比如围棋棋子的位置。

应用场景:程序中使用了大量的对象,如果删除对象的外部状态,可以用相对较少的共享对象取代很多组对象,就可以考虑使用享元模式。

### 享元模式
class Tree(object):
    obj_pool = {}
     
    def __new__(cls, tree_type):
        if tree_type not in cls.obj_pool:
            obj = object.__new__(cls)
            cls.obj_pool[tree_type] = obj
            obj.tree_type = tree_type
        return cls.obj_pool[tree_type]

    def render(self, age):
        print(f'{self.tree_type}: age: {age}')

    # obj_list = []

    # def __init__(self, tree_type):
    #     self.tree_type = tree_type
        # self.get_obj()

    # @classmethod
    # def get_obj(cls):
    #     cls.obj_list.append(cls.__new__(cls))

from random import randint
for _ in range(10):
    a = "apple"
    t1 = Tree(a)
    t1.render(randint(10, 50))
for _ in range(5):
    t2 = Tree("cherry")
    t2.render(randint(10, 50))

for _ in range(3):
    t3 = Tree("peach")
    t3.render(randint(10, 50))
 
 print(len(Tree.obj_pool))
  1. 外观模式
    外观模式又叫做门面模式。在面向对象程序设计中,解耦是一种推崇的理念。但事实上由于某些系统中过于复杂,从而增加了客户端与子系统之间的耦合度。例如:在家观看多媒体影院时,更希望按下一个按钮就能实现影碟机,电视,音响的协同工作,而不是说每个机器都要操作一遍。这种情况下可以采用外观模式,即引入一个类对子系统进行包装,让客户端与其进行交互。

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

from enum import Enum
from abc import ABCMeta, abstractmethod

State = Enum('State', 'new running sleeping restart zombie')


class User:
    pass


class Process:
    pass


class File:
    pass


class Server(metaclass=ABCMeta):
    @abstractmethod
    def __init__(self):
        pass

    def __str__(self):
        return self.name

    @abstractmethod
    def boot(self):
        pass

    @abstractmethod
    def kill(self, restart=True):
        pass


class FileServer(Server):
    def __init__(self):
        '''初始化文件服务进程要求的操作'''
        self.name = 'FileServer'
        self.state = State.new

    def boot(self):
        print('booting the {}'.format(self))
        '''启动文件服务进程要求的操作'''
        self.state = State.running

    def kill(self, restart=True):
        print('Killing {}'.format(self))
        '''终止文件服务进程要求的操作'''
        self.state = State.restart if restart else State.zombie

    def create_file(self, user, name, permissions):
        '''检查访问权限的有效性、用户权限等'''
        print("trying to create the file '{}' for user '{}' with permissions{}".format(name, user, permissions))


class ProcessServer(Server):
    def __init__(self):
        '''初始化进程服务进程要求的操作'''
        self.name = 'ProcessServer'
        self.state = State.new

    def boot(self):
        print('booting the {}'.format(self))
        '''启动进程服务进程要求的操作'''
        self.state = State.running

    def kill(self, restart=True):
        print('Killing {}'.format(self))
        '''终止进程服务进程要求的操作'''
        self.state = State.restart if restart else State.zombie

    def create_process(self, user, name):
        '''检查用户权限和生成PID等'''
        print("trying to create the process '{}' for user '{}'".format(name, user))


class WindowServer:
    pass


class NetworkServer:
    pass


class OperatingSystem:
    '''外观'''

    def __init__(self):
        self.fs = FileServer()
        self.ps = ProcessServer()

    def start(self):
        [i.boot() for i in (self.fs, self.ps)]

    def create_file(self, user, name, permissions):
        return self.fs.create_file(user, name, permissions)

    def create_process(self, user, name):
        return self.ps.create_process(user, name)


def main():
    os = OperatingSystem()
    os.start()
    os.create_file('foo', 'hello', '-rw-r-r')
    os.create_process('bar', 'ls /tmp')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值