前言

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

系列文章

原型模式归纳理解

  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. 【Quartz.NET】Quartz.NET 入门

    概述 Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调度作业.它实现了 ...

  2. hadoop和spark搭建记录

    因玩票需要,使用三台搭建spark(192.168.1.10,192.168.1.11,192.168.1.12),又因spark构建在hadoop之上,那么就需要先搭建hadoop.历经一个两个下午 ...

  3. solr服务器的查询过程

    SolrDispatchFilter的作用 This filter looks at the incoming URL maps them to handlers defined in solrcon ...

  4. Java NIO中的Buffer

    简介 Buffer缓冲区,首先要弄明白的是,缓冲区是怎样一个概念.它其实是缓存的一种,我们常说的缓存,包括保存在硬盘上的浏览器缓存,保存在内存中的缓存(比如Redis.memcached).Buffe ...

  5. C++解析(20):智能指针与类型转换函数

    0.目录 1.智能指针 2.转换构造函数 3.类型转换函数 4.小结 1.智能指针 内存泄漏(臭名昭著的Bug): 动态申请堆空间,用完后不归还 C++语言中没有垃圾回收机制 指针无法控制所指堆空间的 ...

  6. [ZJOI2014]力 FFT

    题面 题解: \[F_j = \sum_{i < j}\frac{q_iq_j}{(i - j)^2} - \sum_{i > j}{\frac{q_iq_j}{(i - j)^2}}\] ...

  7. 洛谷 P2498 [SDOI2012]拯救小云公主 解题报告

    P2498 [SDOI2012]拯救小云公主 题目描述 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到\(boss\)的洞穴门口,他一下子就懵了,因为面前不只是一 ...

  8. 【bzoj4596】黑暗前的幻想乡

    Portal -->bzoj4596 Solution 这题的话..因为\(N\)比较小啊所以我们可以大力容斥(尽管实际算下来复杂度有点爆炸不过实测是能过的qwq) 枚举包含了哪些颜色的边,每次 ...

  9. 前端PHP入门-035-Session的实例

      登陆例子:(请注意一定要自己敲一遍,不要CV大法) 首先上一下成果图,激起同学们写的欲望,登录页如下: 点击登陆之后如下: 说明哦了,么问题.接下来自己实现一下. 首先数据库信息: 新建一个名为 ...

  10. Tensorflow BatchNormalization详解:1_原理及细节

    Batch Normalization: 原理及细节 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 吴恩达deeplearningai课程 课程笔记 Udacity课程 为了标准化 ...