设计模式中创建型模式 (二):原型模式


Prototype(原型模式)
简单的讲,就是一种克隆模式,使得一个系统独立于它的产品的创建、构成和表示。
它有和Abstract Factory和Builder一样的效果:它对客户隐藏了具体的产品类。另外,Prototype模式还有另外一些优点:
1、运行时刻增加和删除产品
2、用类动态配置应用。
它的主要缺陷是每一个Prototype的子类都必需实现Clone操作,这可能很困难。例如,当所考虑的类已经存在时就难以新增Clone操作。
当内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能也会很困难的。
我们将定义MazeFactory的子类MazePrototypeFactory.该子类将使用它要创建的对象的原型来为初始化,这样我们就不需要仅仅为了改变它所
创建的墙壁或房间的类而生子类了。

 

以下为示例代码:(VC6+sp6)下测试通过

 

// MapSite.h
#pragma  warning(disable: 4786)


#include 
< vector >
#include 
< map >
#include 
< iostream >
using   namespace  std;


// ##ModelId=48059C280115
enum  Direction
{
    North, South, East, West
}
;

//
// 申明所有类
class  Door;
class  MapSite;
class  Maze;
class  MazeBuilder;
class  MazeFactory;
class  MazeGame;
class  Room;
class  StandardMazeBuilder;
class  Wall;
class  MazePrototypeFactory;
//

// ##ModelId=48059C2800E6
class  MapSite
{
public:
    
//##ModelId=48059C280105
    virtual void Enter() = 0;
}
;

// ##ModelId=48059C280172
class  Wall:  public  MapSite
{
public:
    
//##ModelId=48059C280183
    Wall(){}

    
virtual Wall* Clone() const;

    
//##ModelId=48059C280184
    virtual void Enter(){printf("Wall::Enter() "); }
}
;


// ##ModelId=48059C280134
class  Room:  public  MapSite
{
public:
    
//##ModelId=48059C280144
    Room (int roomNo = 0){ _roomNumber = roomNo; }
    
//##ModelId=48059C280146
    MapSite* GetSide(Direction d)constreturn _sides[d]; }
    
//##ModelId=48059C280154
    void SetSide (Direction d, MapSite* s){ _sides[d] = s; }
    
    Room(
const Room& other);
    
virtual Room* Clone();
    
virtual void Initialize(int n);
    
//##ModelId=48059C280157
    virtual void Enter(){ printf("Room::Enter() "); }
    
    
//##ModelId=48059C280159
    int GetRoomNo()constreturn _roomNumber; }
private:
    
//##ModelId=48059C280164
    MapSite* _sides[4];
    
//##ModelId=48059C280168
    int _roomNumber;
}
;

// ##ModelId=48059C280191
class  Door:  public  MapSite
{
public:
    
//##ModelId=48059C2801A1
    Door(Room* r1= 0, Room* r2= 0){ _room1 = r1;_room2 = r2; }

    Door(
const Door& other);
    
    
virtual void Initialize(Room *r1, Room* r2);
    
virtual Door* Clone() const;
    
//##ModelId=48059C2801A4
    virtual void Enter(){ printf("Door::Enter() "); };
    
//##ModelId=48059C2801A6
    Room* OtherSideFrom(Room*);
private:
    
//##ModelId=48059C2801A9
    Room * _room1;
    
//##ModelId=48059C2801B2
    Room * _room2;
    
//##ModelId=48059C2801B6
    bool _isOpen;
}
;

// ##ModelId=48059C2801C0
class  Maze
{
public:
    
//##ModelId=48059C2801D0
    Maze(){ }
    
    Maze(
const Maze& other);
    
virtual Maze* Clone();

    
//##ModelId=48059C2801D1
    void AddRoom(Room* r)
    
{
        maproom[r
->GetRoomNo()] = r;
    }

    
//##ModelId=48059C2801D3
    Room* RoomNo(int no)return maproom[no]; }
    
private:
    
//##ModelId=48059C2801EF
    map<int, Room*> maproom;
    
//
}
;


// 建造迷宫的程序将MazeFactory作为一个参数,这样程序员就能指定要创建的房间,
// 墙壁和门等类
// ##ModelId=48059C2801FF
class  MazeFactory
{
public:
    
//##ModelId=48059C280200
    MazeFactory(){}
    
    
//##ModelId=48059C280201
    virtual Maze* MakeMaze()const
    
{
        
return new Maze;
    }

    
//##ModelId=48059C280203
    virtual Wall* MakeWall()const
    
{
        
return new Wall;
    }

    
//##ModelId=48059C28020F
    virtual Room* MakeRoom(int n)const
    
{
        
return new Room(n);
    }

    
//##ModelId=48059C280212
    virtual Door* MakeDoor(Room* r1, Room* r2)const
    
{
        
return new Door(r1, r2);
    }

}
;


// 创建各个部件,作用类似于MazeGame::CreateMaze();
// ##ModelId=48059C28021E
class  MazeBuilder
{
public:
    
//##ModelId=48059C28021F
    virtual void BuildMaze(){}
    
//##ModelId=48059C280221
    virtual void BuildRoom(int room){}
    
//##ModelId=48059C28022F
    virtual void BuildDoor(int roomFrom,int roomTo){}

    
//##ModelId=48059C280233
    virtual Maze* GetMaze()return 0; }
protected:
    
//##ModelId=48059C280235
    MazeBuilder(){}

}
;

class  StandardMazeBuilder:  public  MazeBuilder
{
public:
    StandardMazeBuilder()
{ _currentMaze = 0; }

    
virtual void BuildMaze(){ _currentMaze = (Maze*new StandardMazeBuilder; }
    
virtual void BuildRoom(int);
    
virtual void BuildDoor(int,int);

    
virtual Maze* GetMaze()return _currentMaze; }
private:
    Direction CommonWall(Room
*, Room*);//决定哪两个相邻的墙可以有门。
    Maze* _currentMaze;
}
;


// 创建迷宫的类
// ##ModelId=48059C28023D
class  MazeGame:  public  Maze
{
public:
    
//##ModelId=48059C28023F
    Maze* CreateMaze();//普通方法创建迷宫,硬编码方式
    
    
//##ModelId=48059C28024D
    Maze* CreateMaze2(MazeFactory& factory);//工厂类方式建造

    Maze
* CreateMaze3(StandardMazeBuilder& builder);//builder模式,建分部
    

    Maze
* CreateMaze4(MazePrototypeFactory& prototype);//原型模式
    
//##ModelId=48059C28024F
    void printMaze()
    
{
        
//好像比较麻烦
    }

}
;


class  MazePrototypeFactory:  public  MazeFactory
{
public:
    MazePrototypeFactory(Maze
* m,Wall* w, Room* r, Door* d)
    
{
        _prototypeMaze 
= m;
        _prototypeRoom 
= r;
        _prototypeWall 
= w;
        _prototypeDoor 
= d;
    }


    
virtual Maze* MakeMaze() const;
    
virtual Room* MakeRoom(int n) const;
    
virtual Wall* MakeWall() const;
    
virtual Door* MakeDoor(Room* r1, Room* r2) const;

private:
    Maze
* _prototypeMaze;
    Room
* _prototypeRoom;
    Wall
* _prototypeWall;
    Door
* _prototypeDoor;
}
;

//  MapSite.cpp : Defines the entry point for the console application.
//

#include 
" stdafx.h "

#include 
" MapSite.h "
Wall
*  Wall::Clone()  const
{
    
return new Wall(*this);
}



Room::Room(
const  Room &  other)
{
    
this->_roomNumber = other._roomNumber;
    memcpy(
this->_sides,other._sides,sizeof(_sides));
}

Room
*  Room::Clone()
{
    
return new Room(*this);
}

void  Room::Initialize( int  n)
{
    
this->_roomNumber = n;
}



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);
}


Maze::Maze(
const  Maze &  other)
{
    maproom.clear();
    
//maproom.insert(other.maproom.begin(),other.maproom.end());
    map<int, Room*>::const_iterator it;
    it 
= other.maproom.begin();
    
for ( ;it != other.maproom.end(); it++)
    
{
        maproom.insert(
*it);
    }

}


Maze
*  Maze::Clone()
{
    
return new Maze(*this);
}


void  StandardMazeBuilder::BuildRoom( int  n)
{
    
if(!_currentMaze->RoomNo(n))
    
{
        Room
* room = new Room(n);
        _currentMaze
->AddRoom(room);

        room
->SetSide(North, new Wall);
        room
->SetSide(South, new Wall);
        room
->SetSide(East, new Wall);
        room
->SetSide(West, new Wall);
    }

}


void  StandardMazeBuilder::BuildDoor( int  n1,  int  n2)
{
    Room
* r1 = _currentMaze->RoomNo(n1);
    Room
* r2 = _currentMaze->RoomNo(n2);
    Door
* d = new Door(r1, r2);

    r1
->SetSide(CommonWall(r1, r2), d);
    r2
->SetSide(CommonWall(r2, r1), d);
}


Direction StandardMazeBuilder::CommonWall(Room
*  r1, Room *  r2)
{
    
if(r1 == NULL || r2 == NULL )
        
return North;
    
if(r1->GetSide(North) == r2->GetSide(South))
        
return North;
    
if(r1->GetSide(South) == r2->GetSide(North))
        
return South;
    
if(r1->GetSide(West) == r2->GetSide(East))
        
return West;
    
if(r1->GetSide(East) == r2->GetSide(West))
        
return East;
    
return North;
}




// ##ModelId=48059C28023F
Maze *  MazeGame::CreateMaze()
{
    Maze
* aMaze = new Maze;
    Room
* r1 = new Room(1);
    Room
* r2 = new Room(2);
    Door
* theDoor = new Door(r1,r2);
    
    aMaze
->AddRoom(r1);
    aMaze
->AddRoom(r2);
    
    r1
->SetSide(North, new Wall);
    r1
->SetSide(East, theDoor);
    r1
->SetSide(South, new Wall);
    r1
->SetSide(West, new Wall);
    
    
    r2
->SetSide(North, new Wall);
    r2
->SetSide(East, new Wall);
    r2
->SetSide(South, new Wall);
    r2
->SetSide(West, theDoor);
    
    
return aMaze;
}
 


// ##ModelId=48059C28024D
Maze *  MazeGame::CreateMaze2(MazeFactory &  factory)
{
    Maze
* aMaze = factory.MakeMaze();
    Room
* r1 = factory.MakeRoom(1);
    Room
* r2 = factory.MakeRoom(2);
    Door
* aDoor = factory.MakeDoor(r1, r2);
    
    aMaze
->AddRoom(r1);
    aMaze
->AddRoom(r2);
    
    r1
->SetSide(North, factory.MakeWall());
    r1
->SetSide(East, aDoor);
    r1
->SetSide(South, factory.MakeWall());
    r1
->SetSide(West, factory.MakeWall());
    
    r2
->SetSide(North, factory.MakeWall());
    r2
->SetSide(East, factory.MakeWall());
    r2
->SetSide(South, factory.MakeWall());
    r2
->SetSide(West, aDoor);
    
return aMaze;
}


Maze
*  MazeGame::CreateMaze3(StandardMazeBuilder &  builder)
{
    builder.BuildMaze();

    builder.BuildRoom(
1);
    builder.BuildRoom(
2);
    builder.BuildDoor(
12);

    
return builder.GetMaze();
}


Maze
*  MazeGame::CreateMaze4(MazePrototypeFactory &  prototype)
{
    Maze
* aMaze = prototype.MakeMaze();
    Room
* r1 = prototype.MakeRoom(1);
    Room
* r2 = prototype.MakeRoom(2);
    Door
* aDoor = prototype.MakeDoor(r1, r2);
    
    aMaze
->AddRoom(r1);
    aMaze
->AddRoom(r2);
    
    r1
->SetSide(North, prototype.MakeWall());
    r1
->SetSide(East, aDoor);
    r1
->SetSide(South, prototype.MakeWall());
    r1
->SetSide(West, prototype.MakeWall());
    
    r2
->SetSide(North, prototype.MakeWall());
    r2
->SetSide(East, prototype.MakeWall());
    r2
->SetSide(South, prototype.MakeWall());
    r2
->SetSide(West, aDoor);

    
return aMaze;
}


Maze
*  MazePrototypeFactory::MakeMaze()  const
{
    
return _prototypeMaze->Clone();
}


Wall
*  MazePrototypeFactory::MakeWall()  const
{
    
return _prototypeWall->Clone();
}


Room
*  MazePrototypeFactory::MakeRoom( int  n)  const
{
    Room
* room = _prototypeRoom->Clone();
    room
->Initialize(n);
    
return room;
}


Door
*  MazePrototypeFactory::MakeDoor (Room *  r1, Room *  r2)  const  
{
    Door
* door = _prototypeDoor->Clone();
    door
->Initialize(r1, r2);
    
return door;
}


//  testMapSite.cpp : Defines the entry point for the console application.
//

#include 
" stdafx.h "
#include 
" MapSite.h "
int  main( int  argc,  char *  argv[])
{
    printf(
"Hello World! ");

    MazeGame game;
    MazePrototypeFactory simpleMazeFactory(
new Maze, new Wall, new Room, new Door);
    Maze
* maze = game.CreateMaze4(simpleMazeFactory);
    
return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远的麦田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值