设计模式学习总结:原型模式(Protetype)

1.场景分析

2.意图

用原型实例指定创建对象的类型,并且通过拷贝这些原型创建新的对象。

3.适用性

  1. 当一个系统应该独立于它的产品创建、构成和表示时。
  2. 当要实例化的类是在运行时刻指定时,例如动态加载。
  3. 为了避免创建一个与产品类层次平行的工厂类层次时。
  4. 当一个类的实例只能有几个不同状态组合中的一种时。

4.结构

这里写图片描述

5.优缺点

优点:

  1. 可以在运行时刻增加和删除产品。
  2. 可以通过改变值来指定新对象。高度动态的系统允许你通过对象复合定义新的行为,而不用定义新的类型。实际上,克隆一个原型类似于实例化了一个类,Prototype模式可以极大的减少系统所需要的类的数目。
  3. 用类动态配置应用。一个希望动态载入类的实例的应用不能静态引用类的构造器。而应该由运行环境在载入时自动创建每个类的实例,并用原型管理器来管理这个实例。

缺点:

Prototype的主要缺点是每一个原型都必须实现clone操作,也有时是很困难的。当内部包括一些不支持拷贝或者有循环引用的对象时,实现克隆操作将很困难。

6.实现

1>使用一个原型管理器。当一个系统中原型数目不固定时(也就是它们可以被动态创建或销毁),要保持一个可用原型的注册表。原型管理器是一个关联存储器,它返回一个与给定关键字相匹配的原型。
2>实现克隆操作。Prototype的最困难处就在于正确的实现clone操作,当对象包含循环引用时尤为棘手。克隆一个结构复杂的原型通常需要深拷贝,因此你必须保证克隆对象的构建也是原型构件的克隆(特别是对于一些指针和引用)。
3>初始化克隆对象。通常你需要引入一个Init操作来设定克隆后对象的状态。

7.代码示例

我们接下来用原型模式来实现迷宫游戏。

#include <iostream>
using namespace std;

class Room;
class Maze
{
public:
    Maze *clone();
    void addRoom(Room *room);
    //...
};

class Room
{
public:
    Room *clone();
    //...
};

class Wall
{
public:
    Wall *clone();
    //...
};

class Door
{
public:
    Door(){}
    Door(const Door &door)
    {
        _r1 = door._r1;
        _r2 = door._r2;
    }

    void init(Room *r1, Room *r2)
    {
        _r1 = r1;
        _r2 = r2;
    }

    Door*clone()
    {
        return new Door(*this);
    }

private:
    Room *_r1 = nullptr;
    Room *_r2 = nullptr;
};

//抽象工厂
class MazeFactory
{
public:
    virtual Maze *makeMaze();
    virtual Room *makeRoom(int roomId);
    virtual Wall *makeWall();
    virtual Door *makeDoor(Room *r1, Room *r2);
};

//迷宫游戏类
class MazeGame
{
public:
    //通过一个MazeBuilder来创建一个迷宫
    Maze *createMaze(MazeFactory *factory)
    {
        Maze *maze = factory->makeMaze();
        Room *r1 = factory->makeRoom(1);
        Room *r2 = factory->makeRoom(2);
        Door *door = factory->makeDoor(r1, r2);

        maze->addRoom(r1);
        maze->addRoom(r2);

        return maze;
    }
};

class MazePrototypeFactory : public MazeFactory
{
public:
    MazePrototypeFactory(Maze *m, Wall *w, Room *r, Door *d)
    {
        _mazeProto = m;
        _wallProto = w;
        _roomProto = r;
        _doorProto = d;
    }

    Maze *makeMaze()
    {
        return _mazeProto->clone();
    }
    Room *makeRoom()
    {
        return _roomProto->clone();
    }
    Wall *makeWall()
    {
        return _wallProto->clone();
    }
    Door *makeDoor(Room *r1, Room *r2)
    {
        Door *door = _doorProto->clone();
        door->init(r1, r2);
        return door;
    }

private:
    Maze *_mazeProto = nullptr;
    Room *_roomProto = nullptr;
    Wall *_wallProto = nullptr;
    Door *_doorProto = nullptr;
};

int main()
{
    MazeGame game;
    MazePrototypeFactory mazeFactory(new Maze(), new Wall(), new Room(), new Door());
    Maze *maze = game.createMaze(&mazeFactory);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值