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
#写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...
随机推荐
- 第184天:js创建对象的几种方式总结
面向对象编程(OOP)的特点: 抽象:抓住核心问题 封装:只能通过对象来访问方法 继承:从已有的对象下继承出新的对象 多态:多对象的不同形态 一.创建对象的几种方式 javascript 创建对象简单 ...
- SQL中INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN区别
sql中的连接查询有inner join(内连接).left join(左连接).right join(右连接).full join(全连接)四种方式,它们之间其实并没有太大区别,仅仅是查询出来的结果 ...
- P4169 [Violet]天使玩偶/SJY摆棋子
题目背景 感谢@浮尘ii 提供的一组hack数据 题目描述 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅 ...
- BZOJ2005 能量汇集 【gcd求和】
2005: [Noi2010]能量采集 Time Limit: 10 Sec Memory Limit: 552 MB Submit: 4368 Solved: 2607 [Submit][Sta ...
- acid(数据库事务正确执行的四个基本要素的缩写)
ACID,指数据库事务正确执行的四个基本要素的缩写.包含:原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability).一个支持事务(T ...
- 前端解放生产力之–动画(Adobe Effects + bodymovin + lottie)
大概很久很久以前,2017年,参加了第二届中国前端开发者大会(FDCon2017),除了看了一眼尤雨溪,印象最深刻的就是手淘渚薰分享的关于H5交互的内容了.时光荏苒,最近再次接触,简单回顾一下. 示例 ...
- 在VS2010中使用Git【图文】
http://blog.csdn.net/laogong5i0/article/details/10974285 在之前的一片博客<Windows 下使用Git管理Github项目>中简单 ...
- 简单shell 编程
简单shell编程 by dreamboy #!/bin/bash while true do echo clear echo echo " 系统维护菜单 " echo &qu ...
- [树莓派]wifi在面板看不到,但是可以scan到的解决方案
突然遇到一个问题,发现在wifi面板中找不到WiFi,但是运行scan命令可以发现WiFi,多方查找资料终于找到了一个解决方案: 运行如下命令: sudo apt-get install wicd ...
- jsp 文件无法加载 css、js 的问题
今天遇到一个问题是,在 jsp 里面引入 css.js,请求的状态是 200,但 css.js 的内容却是空的. 这是因为 servlet 有个 url-pattern,将 css.js 的路径当做 ...