C++ 中的创建模式
一般来说,一种模式是指一种独特的形式,它使人们能够轻松地履行积极的责任。从技术上讲,样式可以被视为帮助应用程序在其布局中共享专有技术的小工具。
设计模式:在面向对象的术语中使用时间段布局示例来执行职责,同时定义对象、类、接口、继承层次结构,并将它们分解为具有关系的课程。一旦将这些类型的步骤作为样本考虑在内,它们就可以在使用它们的帮助下重复使用,以解决许多不寻常的地方问题。
创建模式:通常,系统具有有关其对象的创建、组合和表示的信息。创建模式已经处理了从对象创建到其表示的所有事情。
- 系统不需要担心它的对象是如何创建、表示等的。这样的创建模式被称为对象创建模式。这将对象实例化委托给另一个对象。
- 除此之外,还有一些创建模式也可以通过使用继承的概念来管理类的实例化过程。这些模式被称为创建模式,在这两种模式中,对象创建模式更为重要。它们定义了一小组可以执行更复杂任务的基本行为,而不是定义一组固定的行为。
- 创建模式包含有关具体类的信息,这些信息主要由系统使用。
- 它们不提供有关具体类的不同实例如何创建以及它们如何组合在一起的信息。
- 系统对它的对象唯一了解的是抽象类声明的对象的接口。
基于以上两类创建模式,即对象和类,除了类创建模式Factory Method模式外,共有5种创建模式,它们都是对象创建模式。
- 抽象工厂模式
- 建造者模式
- 工厂方法模式
- 原型模式
- 单例模式
让我们开始详细讨论这些模式。
1. 抽象工厂模式
抽象工厂模式是一种对象创建模式,也称为工具包。此模式的目的是通过接口为特定客户端实例化一组相关对象,以不指定任何具体类的方式。
示例:考虑一个迷宫游戏的示例,其中 Maze_Game 类的成员函数create() 用于构建迷宫。该代码的问题是,它被编写为只创建两个房间,它们之间有一扇门。因此,这使得创建具有不同组件的迷宫变得困难。为了克服这个问题,创建了一个 MazeFactory (MF) 类,它根据程序员指定的门、墙和房间的规范创建房间。
解决方案:
C++
#include
using namespace std;
// Code of Maze_Factory Class is flows,
class Maze_Factory {
public:
Maze_Factory(); // Constructor
virtual Maze* createMaze() const { return new Maze; }
virtual Rooms* createsRooms(int rno) const
{
return new Rooms(rno);
}
virtual Wall* createsWall() const { return new wall; }
virtual Wall* createsWall() const;
{
return new Wall;
}
virtual Door* createsDoor(Room* ro1, Room*, ro2) const
{
return new Door(ro1, ro2);
}
};
// Therefore the code for creating a maze using an object of
// A Maze_Factory as a parameter is given below,
Maze* Maze_Game::create(Maze_Factory& f)
{
Maze* m = f.createMaze();
Room* ro1 = f.createRoom(1);
room* ro2 = f.createRoom(2);
Door* d = f.create Door(ro1, ro2);
m-- > addRoom(ro1);
m-- > addRoom(ro2);
// create room1
ro1-- > setSide(North, f.createwall());
ro1-- > setSide(south, f.createwall());
ro1-- > setSide(East, d);
ro1-- > setSide(West, f.createwall());
// create room2
ro2-- > setSide(North, f.createwall());
ro2-- > setSide(South, f.createwall());
ro2-- > setSide(East, f.createWall());
ro2-- > setSide(West, d);
return m;
}
C++
#include
using namspace std;
class MazeUsingBuilder {
public:
virtual void createMaze() {}
virtual void createMaze(into) {}
virtual void createDoor(int fromRoom,
int toRoom)
{
}
virtual Maze* getMaze()
{
return 0;
}
protected:
MazeUsingBuilder();
};
C++
#include
using namespace std;
Maze* Maze*_Game :: create(MazeUsingBuilder& b)
{
b.createMaze();
b.createRoom(1);
b.createRoom(2);
b.createDoor(1,2);
return.bgetMaze();
}
C++
class MazeUsingFactory
{
public:
virtual Maze*createMaze()const
{
return new Maze;
}
virtual Room*createRoom()const
{
return new Room(N);
}
virtual Wall*create()const
{
return new Wall;
}
virtual Door*createDoor(Room*ro1,Room*ro2)const
{
return new Door(ro1,ro2);
}
}
C++
Maze* Maze_Game ::create();
{
Maze* m = createMaze();
Room* ro1 = createRoom(1);
Room* ro2 = createRoom(2);
Door*d = createDoor(ro1,ro2);
m-->addRoom(ro1);
m-->addRoom(ro2);
ro1-->setSide(North,createWall());
ro1-->setSide(South,createWall());
ro1-->setSide(East,d);
ro1-->setSide(West,createWall());
ro2-->setSide(North,createWall());
ro2-->setSide(South,createWall());
ro2-->setSide(East,createWall());
ro2-->setSide(West,d);
return m;
}
C++
class MazeUsingPrototype : public MazeUsingFactory
{
public:
MazeUsingProtype(Maze*, Wall*, Room*, Door*);
virtual Maze* createMaze() const;
virtual Room* createRoom(int) const;
virtual Wall* createWall() const;
virtual Door* createDoor(Room*, Room*) const;
private:
Maze* Maze_prototype;
Room* Room_protype;
Wall* Wall_prototype;
Door* Door_prototype;
}
MazeUsingPrototype::MazeUsingProtype
(Maze* mz, Wall* wl, Room* rm, Door* dr)
{
Maze_prototype = mz;
Wall_Prototype = wl;
Room_Prototype = rm;
Door_Prototype = dr;
}
C++
Room* MazeUsingPrototyping::createRoom
(int N)const;
{
Room* r = Room_Prototype-->clone;
r-->Initialize(N);
return r;
}
Wall* MazeUsingPrototype::createWall()
const;
{
return Wall_Prototype-->clone;
}
Door* MazeUsingPrototype::createDoor
(Room*ro1, Room* ro2)const;
{
Door*d = Door_Prototye-->clone();
d-->Initialize(ro1,ro2);
return d;
}
C++
Maze_Game g;
MazeUsingPrototype MyMaze
(new Maze,new Wall,new Room, new Door);
Maze* m = g.create(MyMaze);
C++
class Singleton
{
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* oneInstance();
};
// implementation of Instance() is given below
Singleton* Singleton::oneInstance = 0;
Singleton* Singleton:: Instance();
{
if(oneInstance==0)
{
oneInstance = new Singleton;
}
return oneInstance;
}
2. 建造者模式
构建器设计模式的意图是使用算法构建复杂对象,使其构造独立于其表示方式。通过这样做,用于创建特别复杂对象的构造过程可以用于以不同方式表示同一对象。
示例:考虑迷宫游戏示例。 MazeUsing-Builder 类定义了一个用于创建迷宫的接口。
C++
#include
using namspace std;
class MazeUsingBuilder {
public:
virtual void createMaze() {}
virtual void createMaze(into) {}
virtual void createDoor(int fromRoom,
int toRoom)
{
}
virtual Maze* getMaze()
{
return 0;
}
protected:
MazeUsingBuilder();
};
上面的类包含 4 个方法,其中方法 createMaze()、create room() 和 createDoor() 分别创建一个迷宫、具有特定房间号的房间和编号房间之间的门。 getMaze() 方法将迷宫返回给客户端,但默认情况下,这些操作不执行任何操作。它们被 MazeUsingBuilder 类的子类覆盖。
MazeUsingBuilder 可以被构建迷宫的程序用作参数。因此,create() 的修改版本如下:
C++
#include
using namespace std;
Maze* Maze*_Game :: create(MazeUsingBuilder& b)
{
b.createMaze();
b.createRoom(1);
b.createRoom(2);
b.createDoor(1,2);
return.bgetMaze();
}
从上面的代码可以看出,MazeUsingBuilder 类隐藏了迷宫内部表示的方式。也就是说,没有显示房间、门和墙壁的类别定义以及这些部分组合在一起以构建完整迷宫的方式。
3.工厂方法模式
工厂方法模式是一种类创建模式,也称为虚拟构造函数。工厂方法的意图是定义一个创建对象的接口并将类的实例化推迟到子类。
示例:考虑迷宫游戏示例。如前所述,createMaze() 的问题在于 MazeUsingFactory 为迷宫、房间和墙壁等不同组件定义了工厂方法。工厂方法允许子类选择这些组件。
解决方案:类 MazeUsingFactory 的工厂方法代码如下:
C++
class MazeUsingFactory
{
public:
virtual Maze*createMaze()const
{
return new Maze;
}
virtual Room*createRoom()const
{
return new Room(N);
}
virtual Wall*create()const
{
return new Wall;
}
virtual Door*createDoor(Room*ro1,Room*ro2)const
{
return new Door(ro1,ro2);
}
}
这里,工厂方法是 createMaze()、createRoom()、createDoor() 和 createWall()。所有这些方法都返回迷宫的各个组成部分。
因此,使用工厂方法创建迷宫的 create() 代码如下:
C++
Maze* Maze_Game ::create();
{
Maze* m = createMaze();
Room* ro1 = createRoom(1);
Room* ro2 = createRoom(2);
Door*d = createDoor(ro1,ro2);
m-->addRoom(ro1);
m-->addRoom(ro2);
ro1-->setSide(North,createWall());
ro1-->setSide(South,createWall());
ro1-->setSide(East,d);
ro1-->setSide(West,createWall());
ro2-->setSide(North,createWall());
ro2-->setSide(South,createWall());
ro2-->setSide(East,createWall());
ro2-->setSide(West,d);
return m;
}
4.原型模式
原型模式指定如何使用特定类的原型实例创建特定类型的对象,以及如何通过克隆该原型生成其他对象。
示例:创建了一个名为 MazeUsingPrototype 的 MazUsingFactory 类的子类。在这个类中,首先创建并初始化 Maze、Room、Wall 和 Door 类的对象原型。此初始化是通过添加到 MazeUsingFactory 的参数化构造函数完成的。
解决方案:创建原型的代码如下,
C++
class MazeUsingPrototype : public MazeUsingFactory
{
public:
MazeUsingProtype(Maze*, Wall*, Room*, Door*);
virtual Maze* createMaze() const;
virtual Room* createRoom(int) const;
virtual Wall* createWall() const;
virtual Door* createDoor(Room*, Room*) const;
private:
Maze* Maze_prototype;
Room* Room_protype;
Wall* Wall_prototype;
Door* Door_prototype;
}
MazeUsingPrototype::MazeUsingProtype
(Maze* mz, Wall* wl, Room* rm, Door* dr)
{
Maze_prototype = mz;
Wall_Prototype = wl;
Room_Prototype = rm;
Door_Prototype = dr;
}
上述过程的代码如下,
C++
Room* MazeUsingPrototyping::createRoom
(int N)const;
{
Room* r = Room_Prototype-->clone;
r-->Initialize(N);
return r;
}
Wall* MazeUsingPrototype::createWall()
const;
{
return Wall_Prototype-->clone;
}
Door* MazeUsingPrototype::createDoor
(Room*ro1, Room* ro2)const;
{
Door*d = Door_Prototye-->clone();
d-->Initialize(ro1,ro2);
return d;
}
为了创建一个原型实例或默认迷宫。 MazeUsingPrototype 类的原型是用迷宫组件的原型创建和初始化的。
C++
Maze_Game g;
MazeUsingPrototype MyMaze
(new Maze,new Wall,new Room, new Door);
Maze* m = g.create(MyMaze);
这里,MyMaze 是 MazeUsingPrototype 的原型实例。
5. 单例模式
单例模式是对象创建模式之一,单例模式确保特定类只有一个实例。它还使该实例可以全局访问。
例子:
C++
class Singleton
{
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* oneInstance();
};
// implementation of Instance() is given below
Singleton* Singleton::oneInstance = 0;
Singleton* Singleton:: Instance();
{
if(oneInstance==0)
{
oneInstance = new Singleton;
}
return oneInstance;
}
在这里,对于 Singleton 类,可以观察到该类的构造函数是受保护类型的。因此,当任何客户端尝试直接实例化此类或创建另一个实例时,将在编译此代码期间显示错误消息。因此,这确保了一个类不能有多个实例。
创造模式的特点:
创建模式处理对象的创建和表示。他们将对象的使用与创建逻辑分开。创建模式提供的两个重要特性是:
- 它们封装了关于创建和实例化哪个具体类的知识。
- 它们隐藏了对象创建的过程,从而将对象的使用与其创建逻辑分开。
使用创建模式,开发人员只需要关心类的使用,而不用担心它的具体类是如何创建或实例化的。
应用:
- 使用多组对象之一完成系统配置时。
- 当系统不需要担心其对象的实例化所涉及的过程时。
- 当用户想要以仅显示其接口的方式显示对象的类库时。