设计模式中创建型模式

 

 相关的类图结构:

一直在看创建型,现在看的有两种模式:
Abstract factory(抽象工厂模式)
Builder(生成器模式)
这里用一个迷宫程序来说明这两种模式。
类MapSite是所有迷宫组件的公共抽象类。为简化例子,MapSite仅定义了一个操作Enter.
如果你进入一个房间,那么你的位置会发生改变。如果你试图进入一扇门,那么这两件事中
就会有一件发生:如果门是开着的,你进入另一个房间,如果门是关着的,那么你就会碰壁。
Room是MapSite的一个具体的子类,而MapSite定义了迷宫中构件之间的主要关系。
Room有指向其它MapSite对象的引用,并保存一个房间号,这个数字用来标识迷宫中的房间。
Enter为更加复杂的游戏操作提供了一个简单基础。例如,如果你在一个房间中说“向东走”,
游戏只能确定直接在东边的是哪一个MapSite并对它进行调用Enter.特定子类的Enter操作将计算
出你的位置是发生改变还是你会碰壁。在一个真正的游戏中,Enter可以将移动的游戏者作为一个参数。

我们定义的另一个类是MazeGame,由它来创建迷宫。一个简单直接的创建迷宫的方法是使用一系列的操作
将构件增加到迷宫中,然后连接它们。例如,下面的成员函数将创建一个迷宫,这个迷宫由两个房间和它们之间
的一扇门组成。Maze* MazeGame::CreateMaze(),这样的代码比较直接,属硬编
码方式
MazeFactory是一个创建迷宫的类工厂,它将创建迷宫的细节隐藏在这个工厂中,建造迷宫的程序将MazeFactory作为一个参数,这样程序员就能指定要创建的房间,墙壁和门等类。
MazeBuilder类则是采用一步步建造所有部件的方式来建迷宫。
abstract factory
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
它分离了具体的类,将客户与类的实现分离
它使得晚于交换产品系列
它有利于产品的一致性
难以支持新种类的产品
创建时常春藤用的一些技术:
1、将工厂作为单件
2、创建产品 。
以下将使用Abstract Factory模式创建我们前面所讨论的迷宫
类MazeFactory可以创建迷宫的组件。它建造房间,墙壁和房间之间的门。它可以
用于一个从文件中读取迷宫说明书图并建造迷宫的程序。或者它可以被用于一个
随机建造迷宫的程序。

Abstract Factory与Builder相似,因为它也可以创建复杂对象。主要的区别在于Builder模式
着重于一步步构造一个复杂对象。而Abstract Factory着重于多个系列的产品对象。Builder
在最后的一步返回产品,而对于Abstract Factory来说,产品是立即返回的。另外,Builder模式每一步产生一个组件,在其内部组合成一个对象后返回该对象。而Abstract Factory则是返回一系列的产品对象,内部不进行组合的动作,这是它们之间的最大的区别。

以下为相关代码,可以比较这两种模式的区别。

 

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


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

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

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

//##ModelId=48059C280134
class Room: public MapSite
{
public:
    
//##ModelId=48059C280144
    Room (int roomNo){ _roomNumber = 0; }
    
//##ModelId=48059C280146
    MapSite* GetSide(Direction d)constreturn _sides[d]; }
    
//##ModelId=48059C280154
    void SetSide (Direction d, MapSite* s){ _sides[d] = s; }
    
    
//##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=48059C280172
class Wall: public MapSite
{
public:
    
//##ModelId=48059C280183
    Wall(){}
    
//##ModelId=48059C280184
    virtual void Enter(){printf("Wall::Enter() "); }
}
;


//##ModelId=48059C280191
class Door: public MapSite
{
public:
    
//##ModelId=48059C2801A1
    Door(Room* r1= 0, Room* r2= 0){ _room1 = r1;_room2 = r2; }
    
    
//##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(){ }
    
    
//##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;
}
;

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

    Maze
* CreateMaze3(StandardMazeBuilder& builder);//builder模式,建分部
    
    
//##ModelId=48059C28024F
    void printMaze()
    
{
        
//好像比较麻烦
    }

}
;


//##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();
}





// MapSite.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 mg;
    mg.CreateMaze();

    MazeFactory factory;
    mg.CreateMaze2(factory);

    
//////////////////////////////////////////////////////////////////////////

    Maze
* maze;
    MazeGame game;
    StandardMazeBuilder builder;

    game.CreateMaze3(builder);
    maze 
= builder.GetMaze();
    
//////////////////////////////////////////////////////////////////////////
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

永远的麦田

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

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

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

打赏作者

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

抵扣说明:

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

余额充值