前言

设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象。

系列文章

原型模式归纳理解

  1. 通过对原来对象的克隆获得新对象,不用重新初始化对象;

  2. 核心使用了copy和deepcopy方法;

  3. 一般使用在同一个上下文中,当需要对一个类创建很多个参数相同或大部分参数相同的实例化对象,但对象调用__init__初始化代价很大的时候。

简单工厂模式归纳理解

  1. 将类的实例化推迟到由它的子类来完成,当一个类希望由它的子类来指定它所创建的对象的时候,或者不知道它需要创建的实例对象的时候;

  2. 即通过继承的形式来完成,其最终目的是为了代码复用;

抽象工厂模式归纳理解

  1. 在简单工厂模式下再抽象一层。提供一个产品类库,只想显示它们的接口而不是实现。

  2. 目的是当类对象很庞大时,对简单工厂细分多个工厂,工厂类的代码也可以复用。

建造者模式

  • 如果一个对象的实例化过程很复杂,同时实例化的属性有相互依赖的时候。

  • 复杂包括该类有许多其他的类作为它的属性。

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设计模式之常用创建模式总结(二)的更多相关文章

  1. python设计模式之修饰器模式

    python设计模式之修饰器模式 无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. [ ] 如果合理,可以直接将功能添加到对象所属的类(例如,添加一个新的方法) [ ] 使用组合 ...

  2. 简介Python设计模式中的代理模式与模板方法模式编程

    简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...

  3. python设计模式之责任链模式

    python设计模式之责任链模式 开发一个应用时,多数时候我们都能预先知道哪个方法能处理某个特定请求.然而,情况并非总是如此.例如,想想任意一种广播计算机网络,例如最早的以太网实现.在广播计算机网络中 ...

  4. python设计模式之享元模式

    python设计模式之享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题.性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑.大型复杂系统中也可能会出现同样的问题,因为要在其 ...

  5. Python设计模式: 最佳的"策略"模式实践代码

    Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...

  6. 实例解析Python设计模式编程之桥接模式的运用

    实例解析Python设计模式编程之桥接模式的运用 这篇文章主要介绍了Python设计模式编程之桥接模式的运用,桥接模式主张把抽象部分与它的实现部分分离,需要的朋友可以参考下 我们先来看一个例子: #e ...

  7. C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder

    part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...

  8. python设计模式之装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  9. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

随机推荐

  1. DHCP:动态主机配置协议

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...

  2. 内存测试——Android Studio中对应进程的Heap

    通过Android Studio的Heap查看该程序的目前占用内存大小,多次进出界面,观察内存内存大小的变化.用Heap监测应用进程使用内存情况的步骤如下: 1. 启动Android Studio—& ...

  3. BZOJ 1925 地精部落(DP)

    一道很经典的DP题. 题意:求n排列中波动排列的种数. 不妨考虑DP,令dp1[i][j],表示1-j的排列中,第一项为i之后递增的波动排列种数.dp2[i][j]表示1-j的排列中,第一项为i之后递 ...

  4. XTU 1233 Coins(DP)

    题意: n个硬币摆成一排,问有连续m个正面朝上的硬币的序列种数. 很明显的DP题.定义状态dp[i][1]表示前i个硬币满足条件的序列种数.dp[i][0]表示前i个硬币不满足条件的序列种数. 那么显 ...

  5. Appium与Robotium区别

    Appium是基于UIAutomator框架实现的.Appium测试进程与目标应用进程是分开的,所以Appium不能直接访问目标应用的各种element属性进行copy&paste,而只能模拟 ...

  6. CF521D Shop 贪心

    题意: \(n\)个数,有\(m\)个操作,形如: 1,将\(x_i\)​改成\(val_i\)​ 2,将\(x_i\)加上\(val_i\)​ 3,将\(x_i\)​乘上\(val_i\) 其中第\ ...

  7. CF712E Memory and Casinos 期望概率

    题意:\(n\)个赌场,每个赌场有\(p_{i}\)的胜率,如果赢了就走到下一个赌场,输了就退回上一个赌场,规定\(1\)号赌场的上一个是\(0\)号赌场,\(n\)号赌场的下一个是\(n + 1\) ...

  8. 我是一个CPU:这个世界慢!死!了!

    最近小编看到一篇十分有意思的文章,多方位.无死角的讲解了CPU关于处理速度的理解,看完之后真是豁然开朗.IOT时代,随着科技的发展CPU芯片的处理能力越来越强,强大的程度已经超乎了我们的想象.今天就把 ...

  9. 【BZOJ1458】【洛谷4311】士兵占领(网络流)

    [BZOJ1458][洛谷4311]士兵占领(网络流) 题面 BZOJ权限题,洛谷真好 Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最 ...

  10. 解题:ZJOI 2014 力

    题面 事实说明只会FFT板子是没有用的,还要把式子推成能用FFT/转化一下卷积的方式 虽然这个题不算难的多项式卷积 稍微化简一下可以发现实际是$q_i$和$\frac{1}{(i-j)^2}$在卷,然 ...