python设计模式之常用创建模式总结(二)
前言
设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象。
系列文章
原型模式归纳理解
通过对原来对象的克隆获得新对象,不用重新初始化对象;
核心使用了copy和deepcopy方法;
一般使用在同一个上下文中,当需要对一个类创建很多个参数相同或大部分参数相同的实例化对象,但对象调用__init__初始化代价很大的时候。
简单工厂模式归纳理解
将类的实例化推迟到由它的子类来完成,当一个类希望由它的子类来指定它所创建的对象的时候,或者不知道它需要创建的实例对象的时候;
即通过继承的形式来完成,其最终目的是为了代码复用;
抽象工厂模式归纳理解
在简单工厂模式下再抽象一层。提供一个产品类库,只想显示它们的接口而不是实现。
目的是当类对象很庞大时,对简单工厂细分多个工厂,工厂类的代码也可以复用。
建造者模式
如果一个对象的实例化过程很复杂,同时实例化的属性有相互依赖的时候。
复杂包括该类有许多其他的类作为它的属性。
python实现举例
现在有一个射击游戏的需求,比如坦克大战,那么分析其涉及的类有:坦克,子弹;坦克分为敌方坦克,我方坦克,或分为轻型坦克,中型坦克,重型坦克;子弹分为敌方子弹和我方子弹,或穿甲弹,高爆弹,碎甲弹。
现在分析类的实例属性和方法:
坦克的属性:属于哪方,坦克类型,血量,速度,图片,安装的子弹;
坦克的功能:移动,射击,碰撞,死亡;
子弹的属性:属于哪方,子弹类型,血量,速度,图片;
子弹的功能:移动,碰撞,死亡;
- 定义类
class TanK(object):
def __init__(self, camp, type, blood, speed, image):
self.__camp = camp
self.__type = type
self.__blood = blood
self.__speed = speed
self.__image = image
self.bullet = None
def move(self):
pass
def fire(self):
pass
def crash(self):
pass
def dead(self):
pass
class Bullet(object):
def __init__(self, camp, type, blood, speed, image):
self.__camp = camp
self.__type = type
self.__blood = blood
self.__speed = speed
self.__image = image
def move(self):
pass
def crash(self):
pass
def dead(self):
pass
一般看上面两个类如此的相似,都会想到继承:
class Weapon(object):
def __init__(self, camp, type, blood, speed, image):
self.__camp = camp
self.__type = type
self.__blood = blood
self.__speed = speed
self.__image = image
def move(self):
pass
def crash(self):
pass
def dead(self):
pass
class TanK(Weapon):
def __init__(self, camp, type, blood, speed, image, bullet):
super().__init__(camp, type, blood, speed, image)
self.bullet = bullet
def move(self):
pass
def fire(self):
pass
def crash(self):
pass
def dead(self):
pass
class Bullet(Weapon):
def move(self):
pass
def crash(self):
pass
def dead(self):
pass
然而这并没有减少多少代码量,最重要的是每次创建一个实例至少需要传五个参数,资源消耗优化什么的更谈不上;
- 开始分析属性
坦克camp属性决定了image,type决定blood、speed、bullet
子弹camp属性决定了image,type决定blood、speed
于是重新划分类:
我方坦克;敌方轻型坦克,中型坦克,重型坦克;
我方穿甲弹,高爆弹,碎甲弹;敌方穿甲弹,高爆弹,碎甲弹;
- 重新定义
class Weapon(object):
def move(self):
pass
def crash(self):
pass
def dead(self):
pass
class Tank(Weapon):
def fire(self):
pass
class MyTank(Tank):
def __init__(self):
self.__blood = 50
self.__speed = 10
self.__image = "xxxx"
self.bullet = None
class EneSmallTank(Tank):
def __init__(self):
self.__blood = 50
self.__speed = 10
self.__image = "xxxxxx"
self.bullet = None
class EneMidTank(Tank):
def __init__(self):
self.__blood = 100
self.__speed = 8
self.__image = "abc"
self.bullet = None
class EneBigTank(Tank):
def __init__(self):
self.__blood = 150
self.__speed = 5
self.__image = "abcdfg"
self.bullet = None
class MySmallBullet(Weapon):
def __init__(self):
self.__blood = 20
self.__speed = 20
self.__image = "ff"
class MyMidBullet(Weapon):
def __init__(self):
self.__blood = 30
self.__speed = 20
self.__image = "gg"
class MyBigBullet(Weapon):
def __init__(self):
self.__blood = 40
self.__speed = 20
self.__image = "hh"
class EneSmallBullet(Weapon):
def __init__(self):
self.__blood = 20
self.__speed = 20
self.__image = "ff"
class EneMidBullet(Weapon):
def __init__(self):
self.__blood = 30
self.__speed = 20
self.__image = "gg"
class EneBigBullet(Weapon):
def __init__(self):
self.__blood = 40
self.__speed = 20
self.__image = "hh"
类虽然变得很多,但是创建类的实例变得方便,不过也有新的问题,游戏创建敌方坦克种类可能是随机的,但是类太多,我们应该提供统一的创建接口。
class WeaponFactory(object):
"""创建一个武器工厂"""
def create_weapon(self, type):
pass
class TankFactory(WeaponFactory):
"""创建坦克生产线,根据坦克类型生产坦克"""
def create_weapon(self, type):
if type == 'my':
return MyTank()
elif type == 'est':
return EneSmallTank()
elif type == 'emt':
return EneMidTank()
elif type == "ebt":
return EneBigTank()
else:
return
class BulletFactory(WeaponFactory):
"""创建子弹生产线"""
def create_weapon(self, type):
if type == 'msb':
return MySmallBullet()
elif type == 'mmb':
return MyMidBullet()
elif type == 'mbb':
return MyBigBullet()
elif type == "esb":
return EneSmallBullet()
elif type == "emb":
return EneMidBullet()
elif type == "ebb":
return EneBigBullet()
else:
return
工厂也需要实例化后才能创建坦克和子弹,但是工厂一个就够了,因此把BulletFactory和TankFactory设为单例模式。
class TankFactory(WeaponFactory):
"""创建坦克生产线,根据坦克类型生产坦克"""
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def create_weapon(self, type):
if type == 'my':
return MyTank()
elif type == 'est':
return EneSmallTank()
elif type == 'emt':
return EneMidTank()
elif type == "ebt":
return EneBigTank()
else:
return
class BulletFactory(WeaponFactory):
"""创建子弹生产线"""
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def create_weapon(self, type):
if type == 'msb':
return MySmallBullet()
elif type == 'mmb':
return MyMidBullet()
elif type == 'mbb':
return MyBigBullet()
elif type == "esb":
return EneSmallBullet()
elif type == "emb":
return EneMidBullet()
elif type == "ebb":
return EneBigBullet()
else:
return
子弹和坦克都是游戏过程中需要被大量创建的对象,因此我们可以使用原型模式来节约内存,在工厂初始化的时候创建几个坦克和子弹原型。
class TankFactory(WeaponFactory):
"""创建坦克生产线,根据坦克类型生产坦克"""
__instance = None
__first_one = False
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
if not self.__first_one:
self.__first_one = True
self.__mytank = MyTank()
self.__ene_small_tank = EneSmallTank()
self.__ene_mid_tank = EneMidTank()
self.__ene_big_tank = EneBigTank()
def create_weapon(self, type):
_map = {
'my':self.__mytank,
'est':self.__ene_small_tank,
'emt':self.__ene_mid_tank,
'ebt':self.__ene_big_tank,
}
if type in _map:
return copy.deepcopy(_map[type])
else:
return
class BulletFactory(WeaponFactory):
"""创建子弹生产线"""
__instance = None
__first_one = False
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
if not self.__first_one:
self.__first_one = True
self.__my_small_bullet = MySmallBullet()
self.__my_mid_bullet = MyMidBullet()
self.__my_big_bullet = MyBigBullet()
self.__ene_small_bullet = EneSmallBullet()
self.__ene_mid_bullet = EneMidBullet()
self.__ene_big_bullet = EneBigBullet()
def create_weapon(self, type):
_map = {
'msb': self.__my_small_bullet,
'mmb': self.__my_mid_bullet,
'mbb': self.__my_big_bullet,
'esb': self.__ene_small_bullet,
'emb': self.__ene_mid_bullet,
'ebb': self.__ene_big_bullet
}
if type in _map:
return copy.deepcopy(_map[type])
else:
return
总结
- 为了达到目标,创建模式中的各种模式需要灵活搭配,使得设计尽量符合代码设计的六大设计原则。
参考:
python设计模式之常用创建模式总结(二)的更多相关文章
- python设计模式之修饰器模式
python设计模式之修饰器模式 无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. [ ] 如果合理,可以直接将功能添加到对象所属的类(例如,添加一个新的方法) [ ] 使用组合 ...
- 简介Python设计模式中的代理模式与模板方法模式编程
简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...
- python设计模式之责任链模式
python设计模式之责任链模式 开发一个应用时,多数时候我们都能预先知道哪个方法能处理某个特定请求.然而,情况并非总是如此.例如,想想任意一种广播计算机网络,例如最早的以太网实现.在广播计算机网络中 ...
- python设计模式之享元模式
python设计模式之享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题.性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑.大型复杂系统中也可能会出现同样的问题,因为要在其 ...
- Python设计模式: 最佳的"策略"模式实践代码
Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...
- 实例解析Python设计模式编程之桥接模式的运用
实例解析Python设计模式编程之桥接模式的运用 这篇文章主要介绍了Python设计模式编程之桥接模式的运用,桥接模式主张把抽象部分与它的实现部分分离,需要的朋友可以参考下 我们先来看一个例子: #e ...
- C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder
part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...
- python设计模式之装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- python 设计模式之装饰器模式 Decorator Pattern
#写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...
随机推荐
- python的N个小功能(高斯模糊原理及实践)
原理: 二维高斯函数 1) 为了计算权重矩阵,需要设定σ的值.假定σ=1.5,则模糊半径为1的权重矩阵如下: 2) 这9个点的权重总和等于0.4787147,如果只计算 ...
- bzoj2301-Problem b
题意 \(T\le 5\times 10^4\) 次询问,每次询问 \(a,b,c,d,k\le 5\times 10^4\),求 \[ \sum _{i=a}^b\sum _{j=c}^d[gcd( ...
- 【bzoj3203】[Sdoi2013]保护出题人 凸包+二分
题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的 ...
- TCP(Transmission Control Protocol)学习笔记
一.TCP(Transmission Control Protocol)原理介绍(参考维基百科) TCP连接包括三种状态:连接建立.数据传送和连接终止. TCP用三路握手(three-way hand ...
- 复习JavaScript随手记
数据类型 基本类型 string number boolean undefined number类型,包含整数浮点数 NaN和自己都不相等,涉及NaN的计算结果都是NaN isNaN()函数用于判断一 ...
- TCP/IP地址格式转换API
1.htonl ()和ntohl( ) ntohl( )-----网络顺序转换成主机顺序(长整型) u_long PASCAL FAR ntohl (u_long netlong); htonl ( ...
- bzoj 2530 [Poi2011]Party 构造
2530: [Poi2011]Party Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 364 Solved: ...
- C++调用函数模仿数字钟表
调用系统函数,可以得到系统时间 #include<iostream> #include<windows.h> #include<time.h> using name ...
- 平衡树【Treap】
平衡树的板题,用Treap实现. 具体参见注释,写的很详细了,包括了原理,实现以及注意事项 蒟蒻写个注释板子写了两天,太弱了QAQ 感谢niiick指导 Code #include<iostre ...
- 第3章-Vue.js 指令扩展 和 todoList练习
一.学习目标 了解Vue.js指令的实现原理 理解v-model指令的高级用法 能够使用Vue.js 指令完成 todoList 练习(重点+难点) 二.todoList练习效果展示 2.1.效果图展 ...