前言

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

系列文章

原型模式归纳理解

  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. vue.js+vue-router+webpack keep-alive用法

    本文是机遇 提纲:   现有需求 各个解决方案的优缺点 相关的问题延伸 keep-alive使用详解   现有需求   每个项目中都存在许多列表数据展示页面,而且通常包含一些筛选条件以及分页.   并 ...

  2. 【UNIX环境编程、操作系统】孤儿进程和僵尸进程

    基本概念: 在类UNIX系统中,僵尸进程是指完成执行(通过exit系统调用,或运行时发生致命错误或收到终止信号所致)但在操作系统的进程表中仍然有一个进程表表项(进程控制块PCB),处于"终止 ...

  3. UVA12546_LCM Pair Sum

    题目的意思是求 [西伽马(p+q)]其中lcm(p,q)=n. 又见数论呀. 其实这个题目很简单,考虑清楚了可以很简单的方法飘过. 我一开始是这样来考虑的. 对于每一个单独的质因子,如果为p,它的次数 ...

  4. 3294 [SCOI2016]背单词

    题目描述 Lweb 面对如山的英语单词,陷入了深深的沉思,”我怎么样才能快点学完,然后去玩三国杀呢?“.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ...

  5. 导航控制器里边添加UIScrollView (automaticallyAdjustsScrollViewInsets)

    导航控制器里边如果添加UIScrollView会导致放大操作异常怪异,此时设置 self.automaticallyAdjustsScrollViewInsets = false

  6. 利用Runloop优化流畅度

    我们可以对runloop添加观察者,当观察到状态为kCFRunLoopExit,kCFRunLoopBeforeWaiting的时候,做一些耗时的处理,废话不说,直接上代码 - (void)viewD ...

  7. 【BZOJ3105】新Nim游戏(线性基)

    [BZOJ3105]新Nim游戏(线性基) 题面 BZOJ Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以 ...

  8. Middle of Linked List

    Find the middle node of a linked list. Example Given 1->2->3, return the node with value 2. Gi ...

  9. AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)

    结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...

  10. 基于线程池技术的web服务器

    前言:首先简单模拟一个场景,前端有一个输入框,有一个按钮,点击这个按钮可以实现搜索输入框中的相关的文本和图片(类似于百度.谷歌搜索).看似一个简单的功能,后端处理也不难,前端发起一个请求,后端接受到这 ...