Python三种常用的程序设计模式

一、 创建型的设计模式

1、 工厂模式(Factory):解决对象创建问题
2、 构造模式(Builder): 控制解决复杂对象的创建问题
3、 原型模式(Prototype): 通过原型的克隆去创建新的实例
4、 单例模式(Brog/Singleton): 一个类只能创建同一个对象
5、 对象池模式(Pool): 预先分配同一个类型的一组实例
6、 惰性计算模式(Lazy Evaluation): 延迟计算(Python的property)

  • 工厂模式

解决对象创建的问题, 解耦对象的创建和使用, 包括工厂方法和抽象工厂

# 工厂方法的一个例子
klass_dict = {}
def register(type):
	def deco(cls):
			if cls not in klass_dict.values():
				klass_dict[type] = cls
	return deco

@register('Dog')
class Dog:
    def speak(self):
        print("WangWang!")
 
@register('Cat')
class Cat:
    def speak(self):
        print("MiaoMiao!")
 
def animal(speak_type):
    klass = klass_dict.get('speak_type')
    return klass
  • 构造模式

核心: 将一个过程需要自定义的部分进行细化分类即可。
用来控制复杂对象的构造, 创建。 比如买电脑, 工厂模式直接给你电脑, 而构造模式可以允许你自定义你的电脑的配置, 组装后返回给你。

import attr

@attr.s
class Computer(obj):
	# 电脑类, 只有个机箱序列号, 其他None
	serial_num = attr.ib()
	memory = attr.ib(default=None)
	hdd = attr.ib(default=None)
	gpu = attr.ib(default=None)
	
	def __repr__(self):
		info = ("内存: {}GB:".format(self.memory),
				"硬盘:{}GB".format(self.hdd),
				"显卡: {}".format(self.gpu))
		return '\n'.join(info)

@attr.s
class ComputerBuilder(obj):
	# 装机人员类, 接收一个机箱壳子
	computer = attr.ib(default=Computer())
	
	def configure_memory(self. amount):
		self.computer.memory = amount
	def configure_hdd(self, amonut):
		self.computer.hdd = amout
	def configure_gpu(self, gpu_model):
		self.computer.gpu = gpu_model

@attr.s
class HardwareEngineer(obj):
	builder = attr.ib(None)	# 装机人员
	def construct_computer(self, memory, hdd, gpu):
		# 组装电脑
		self.builder = ComputerBuilder()
		[step for step in (self.builder.configure_memory(memory),
						   self.builder.configure_hdd(hdd),
						   self.builder.configure_gpu(gpu)])
	@property
	def computer(self):
		# 组装完成, 到电脑城提电脑
		return self.builder.computer

# 创建一个造机工厂
engineer = HardwarEngineer()
engineer.construct_computer(hdd=1024, memory=32, gpu='GeForce GTX TITAN Plus'
my_computer = enginner.computer
print my_computer
  • 原型模式

通过克隆原型来创建新的实例, 可以使用相同的原型, 通过修改部分属性来创建心得实例。
用途: 对于一些创建实例开销比较高的地方可以使用原型模式, 也叫Copy忍者卡卡西模式。

  • 单例模式

一个类创建出来的对象是同一个, 例如:Python模块就是单例的, 无论导入调用多少次都是同一个对象。

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

class B(Singleton):
	pass

b = B()
c = B()
id(b) == id(c)  # True

二、结构型设计模式

1、 装饰器模式(Decorater): 无需子类化扩展对象功能
2、 代理模式(Proxy): 把一个对象的操作代理到另一个对象
3、 适配器模式(Adapter): 通过一个间接层适配统一接口
4、 外观模式(Facade): 简化复杂对象的访问问题
5、 享元模式(Flyweight): 通过对象复用改善资源利用, 比如连接池
6、 Model-View-Controller(MVC):解耦合显示逻辑和业务逻辑, 比如Django, Flask, Tornado等框架都适合这种模式。

  • 代理模式

把对象的操作代理到另一个对象, 这里可以用到Stack、Queue, 把操作代理到deque。

from collections import deque

class Stack(obj):
	def __init__(self):
		self._deque = deque()
	def push(self, value):
		return self._deque.append(value)
	def pop(self):
		return self._deque.pop()
	def empty(self):
		return len(self._deque) == 0
  • 适配器模式

把不同的对象的接口适配到同一个接口, 当需要不同的对象统一接口的时候可以使用适配器模式

class Dog(obj):
	def __init__(self):
		self.name = 'dog'
	def bark(self):
		return 'wangwang'
class Cat(obj):
	def __init__(self):
		self.name = 'cat'
	def miao(self);
		return 'miaomiao'

class Adapter:
	def __init__(self, obj, **adapter_methods):
		self.obj = obj
		self.__dict__.update(adapted_methods)
	def __getattr__(self, attr):
		return getattr(self.obj, attr)

objects = []
dog = Dog()
objects.append(Adapter(dog, make_noise=dog.bark))
cat = Cat()
objects.append(Adapter(cat, make_noise=cat.miao))

for obj in objects:
	print "name:{}, ac:{}".format(obj.name, obj.make_noise())

三、行为型模式

1、 迭代器模式(Iterator): 通过统一identify接口迭代对象
2、 观察者模式(Observer)—发布订阅: 对象发生变化的时候, 观察者执行相应的动作
3、 策略模式(Strategy): 针对不同的输入使用不容的策略

  • 迭代器模式

Python内置对迭代器模式的支持, 可以用for遍历各种Iterable的数据类型, 不可迭代对象需要用(next__和__iter) 实现迭代器, 可以迭代的对象只使用__iter__

from collections import deque

class Stack(obj):
	def __init(self):
		self._deque =deque()
	def push(self, value):
		return self._deque.append(value)
	def pop(self):
		return self._deque.pop()
	def empty(self):
		return len(self._deque) == 0
	
	def __iter__(self):
		res = []
		for i in self._deque:
			res.append(i)
		for i in reversed(res):
			yield i
  • 观察者模式

发布订阅最为常见, 发布订阅用于解耦合逻辑, 可以通过回调等方式去实现, 当条件发生的时候可以使用相应的回调函数去触发下一层设计的逻辑

 
class Publisher:
    def __init__(self):
        self.observers = []
 
    def add(self, observer):
        if observer not in self.observers:
            self.observers.append(observer)
        else:
            print('Failed to add : {}'.format(observer))
 
    def remove(self, observer):
        try:
            self.observers.remove(observer)
        except:
            print('Failed to remove : {}'.format(observer))
 
    def notify(self):
        [o.notify_by(self) for o in self.observers]
 
class Formatter(Publisher):
    def __init__(self, name):
        super().__init__()
        self.name = name
        self._data = 0
 
    @property
    def data(self):
        return self._data
 
    @data.setter
    def data(self, new_value):
        self._data = int(new_value)
        self.notify()
 
class BinaryFormatter:
    
    def notify_by(self, publisher):
        print("{} : {} has now bin data = {}".format(
                            type(self).__name__,
                            publisher.name,
                            bin(publisher.data)))
  • 策略模式

根据不同输入采用不容的策略, 对歪暴露统一的接口, 内部采用不同的策略进行计算返回结果(这种和rpc或者云函数的意思蛮接近的, 外部只管按规则调用, 我直接返回结果给你, 其中过程外部是不需要知道的)

class Order:
	def __init__(self, price, discount_strategy=None):
		self.price = price
		self.discount_strategy = discount_strategy
	
	def price_after_discount(self):
		if self.discount_strategy:
			discount = self.discount_strategy(self)
		else:
			discount = 0
		return self.price - discount
	
	def __repr__(self):
		fmt='<Price: {}, price after discount: {}>'
		return fmt.fotmat(self.price, self.price_after_discount())
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值