• 设计模式 笔记 原型模式 prototype




    //---------------------------15/04/07----------------------------


    //prototype 原型模式--对象创建型模式


    /*

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

        2:动机:

        3:适用性:

            1>当一个系统应该独立于它的产品创建、构成和表示时

            2>当要实例化的类是在运行时刻制定时,例如通过动态装载

            3>为了避免创建一个与产品类层次平行的工厂类层次时

            4>当一个类的实例只能有几个不同状态组合中的一种时

        4:结构:

            Client:

            prototype------------------------------->Prototype:

            Operation()                              Clone()

            { p = prototype->Clone()}                   |

                                                |                   |

                                    ConcretePrototype1:     ConcretePrototype2:

                                    Clone()                 Clone()

                                    {return copy of self}   {return copy of self}

        5:参与者:

            1>Prototype:声明一个克隆自身的接口。

            2>ConcretePrototype:实现一个克隆自身的操作。

            3>Client:让一个原型克隆自身从而创建一个新的对象。

        6:协作:客户请求一个原型克隆自身。

        7:效果:

            1>优点:

                1)运行时刻可以增加和删除产品,更加灵活。

                2)改变值以指定新对象。 可以为对象指定新值来实例化新的对象,

                  这种设计可以极大减少系统所需的类的数目。

                3)改变结构以制定新对象。 针对一些由部件和子部件来创建的对象,

                  反映了Composite模式(改变child的多少或类型等)以及Decorator模式(暂时不知道<未知标记>)

                  这里Clone需要实现为深拷贝,不然child都是一样的这个结构改变一下,别的结构就跟着改变了。

                4)减少子类的构造。相比较于Factory Method,不需要创建一个creator类层次,

                  需要一个对象时只用克隆一个就行,而不是靠creator类创建。

                5)用类动态配置应用(不懂<未知标记>)

            2>缺陷:

                每一个子类都必须实现Clone操作。当类已经存在,新增Clone操作会很难。当内部包括一些不

                支持拷贝(不支持拷贝,就无法调用拷贝构造函数实现Clone操作)或有循环引用(要实现深拷贝,就

                要不断重复了)的对象时,实现克隆也会很困难。

        8:实现:

            1>使用一个原型管理器。 当一个系统中原型数目不固定时(也就是,客户会动态创建和销毁),要保持一个可

              用原型的注册表。客户可以通过注册表来存储和检索原型。

            2>实现克隆操作。对一些复杂的对象进行深拷贝。

            3>初始化克隆对象 如果原型的类已经定义好了设置关键状态的操作就不用提供initialize操作,

              否则,就必须提供一个initialize操作来初始化参数。

        9:代码示例:                                                         */


    //原型工厂

    class MazePrototypeFactory : public MazeFactory

    {

    public:

        MazePrototypeFactory(Maze*, Wall*, Room*, Door*);

        

        virtual Maze* MakeMaze() const;

        virtual Room* MakeRoom(int) const;

        virtual Wall* MakeWall() const;

        virtual Door* MakeDoor(Room*, Room*) const;

        

    private:

        Maze*   _prototypeMaze;

        Room*   _prototypeRoom;

        Wall*   _prototypeWall;

        Door*   _prototypeDoor;

    };


    //初始化每一个原型

    MazePrototypeFactory::MazePrototypeFactory

    (Maze* m, Wall* w, Room* r, Door* d)

    {

        _prototypeMaze = m;

        _prototypeRoom = r;

        _prototypeWall = w;

        _prototypeDoor = d;

    }


    //实现基类的virtual方法,内部调用Clone实现

    Wall* MazePrototypeFactory::MakeWall() const

    {

        return _prototypeWall->Clone();

    }


    //效用Clone后还要初始化克隆对象

    Door* MazePrototypeFactory::MakeDoor(Room* r1, Room* r2) const

    {

        Door* door = _prototypeDoor->Clone();

        door->Initialize(r1, r2);

        return door;

    }

    //使用方法

    MakeGame game;

    MazePrototypeFactory simpleMazeFactor(new Maze, new Wall, new Room, new Door);

    maze* maze = game.CreateMaze(simpleMazeFactor);

    /////////


    //下面要换其中的部件,来实现新的原型类,要作为部件,必须实现clone操作

    MazePrototypeFactory bombedMazeFactory(

    new Maze, new BombedWall, new RoomWithABomb, new Door);


    //Door中有两个数据可以设置或者说需要设置,所以要提供一个initilize函数

    class Door : public MapSite

    {

    public:

        Door();

        Door(const Door&);

        

        virtual void Initialize(Room*, Room*);

        virtual Door* Clone() const;

        virtual void Enter();

        Room* OtherSideFrom(Room*);

        

    private:

        Room* _room1;

        Room* _room2;

    };


    Door::Door (const Door& other)

    {

        _room1 = other._room1;

        _room2 = other._room2;

    }


    void Door::Initialize(Room* r1, Room* r2)

    {

        _room1 = r1;

        _room2 = r2;

    }


    Door* Door::Clone() const

    {

        return new Door(*this);

    }


    //这里应该也有一个initialize函数才对。用来设置是否有炸弹

    class BombedWall : public wall

    {

    public:

        BombedWall();

        BombedWall(const BombedWall&);

        

        virtual Wall* Clone() const;

        bool HasBomb();

        

    private:

        bool _bomb;

    };


    BombedWall::BombedWall(const BombedWall& other) : Wall(other)

    {

        _bomb = other._bomb;

    }


    Wall* BombedWall::Clone() const

    {

        return new BombedWall(*this);

    }


    //这样子每次用的时候都要重新使用部件创建一个

    //可以用一个map存起来

    map<string,MazePrototypeFactory> MazeTable;

    MazeTable.insert(make_pair("bombedMazeFactory",bombedMazeFactory));

    //要用的时候取出:

    game.CreateMaze(map["bombedMazeFactory"]);

    //可以把直接map封装到game中,然后致用传入一个字符串就行。

    //不过这样需要提供一个注册函数和销毁函数,来对进行注册和销毁。


    //下面是ios设计模式解析版本的:

    /*

        1:在以下情形,会考虑使用原型模式:

            1>需要创建的对象应独立于其类型与创建方式。(太抽象<未知标记>)

            2>要实例化的类是在运行时决定的。

            3>不想要与产品层次相对应的工厂层次。

            4>不同类的实例间的差异仅仅是状态的若干组合。因此复制响应数量的原型比手工实例化更加方便。

            5>类不容易创建,比如每个组件可以把其他组件作为子节点的组合对象。复制已有的组合

              对象,并对副本进行修改会更加容易。

        2:考虑使用原型模式的情景:

            1>有很多相关的类,其行为略不同,而且主要差别在于内部属性,比如名称,图像等;

            2>徐傲使用组合对象作为其他东西的基础,比如,使用组合对象作为组件来构建另一个组合对象。

    */




  • 相关阅读:
    mapreduce深入剖析5大视频
    深入理解Apache Flink
    什么是Apache Flink
    Hadoop IO
    HDFS操作及小文件合并
    HDFS分布式文件系统
    hbase 核心知识
    机器学习--简单神经网络
    Hbase访问方式
    LeetCode 167. Two Sum II
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983145.html
Copyright © 2020-2023  润新知