python设计模式之常用创建模式总结(二)

前言

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

系列文章

原型模式归纳理解

  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

总结

  • 为了达到目标,创建模式中的各种模式需要灵活搭配,使得设计尽量符合代码设计的六大设计原则。

参考:

posted @ 2018-08-01 15:59  倥偬时光  阅读(602)  评论(0编辑  收藏  举报