原型模式

类图]]
原型模式(),是一种创建型模式,其特点在于通过「复制」一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的「原型」,这个原型是可定制的。

原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。

结构
在上面的UML类图中,Client类提及Prototype接口来克隆一个Product。Product1类通过创建自身复本来实现Prototype接口。

UML序列图展示了运行时交互:Client对象调用clone()于prototype:Product1对象之上,它创建并返回自身的一个复本(product:Product1对象)。

示例
Java
下面是Java例子:

/ Prototype Class /
public class Cookie implements Cloneable {
public Object clone() throws CloneNotSupportedException {
//In an actual implementation of this pattern you would now attach references to
//the expensive to produce parts from the copies that are held inside the prototype.
return (Cookie) super.clone();
}
}

/ Concrete Prototypes to clone /
public class CoconutCookie extends Cookie { }

/ Client Class/
public class CookieMachine {
private Cookie cookie;//cookie必须是可复制的

public CookieMachine(Cookie cookie) {
this.cookie = cookie;
}

public Cookie makeCookie() {
try {
return (Cookie) cookie.clone();
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}

public static void main(String args[]){
Cookie tempCookie = null;
Cookie prot = new CoconutCookie();
CookieMachine cm = new CookieMachine(prot); //设置原型
for(int i=0; i
Python
下面是Python例子:

import copy

class Prototype():
def clone(self):
return copy.copy(self)

class Product(Prototype):
def __init__(self, number=0, **kwargs):
self.number = number
for key, value in kwargs.items():
self.__dict__[key] = value

class ProductCreator():
def __init__(self, proto):
self.proto = proto
self.number = proto.number
def __call__(self):
self.number += 1
r = self.proto.clone()
r.number = self.number
return r

product0 = Product()
product_creator = ProductCreator(product0)
products = [product0]
for i in range(1, 20):
products += [product_creator()]

C++
下面是基于《设计模式》书中前C++98实现的C++23实现迷路园游戏例子:

import std;

using std::array;
using std::shared_ptr;
using std::unique_ptr;
using std::vector;

enum class Direction: char {
NORTH,
SOUTH,
EAST,
WEST
};

class MapSite {
public:
virtual void enter() = 0;
virtual unique_ptr clone() const = 0;
virtual ~MapSite() = default;
};

class Room: public MapSite {
private:
int roomNumber;
shared_ptr, 4>> sides;
public:
explicit Room(int n = 0):
roomNumber{n}, sides{std::make_shared, 4>>()} {}

~Room() = default;

Room& setSide(Direction d, shared_ptr ms) {
(*sides)[static_cast(d)] = std::move(ms);
std::println("Room::setSide {} ms", d);
return *this;
}

virtual void enter() override {}

virtual unique_ptr clone() const override {
return std::make_unique(*this);
}

Room(const Room&) = delete;
Room& operator=(const Room&) = delete;
};

class Wall: public MapSite {
public:
Wall():
MapSite() {}

~Wall() = default;

virtual void enter() override {}

nodiscard
virtual unique_ptr clone() const override {
return std::make_unique(*this);
}
};

class Door: public MapSite {
private:
shared_ptr room1;
shared_ptr room2;
public:
explicit Door(shared_ptr r1 = nullptr, shared_ptr r2 = nullptr):
MapSite(), room1{std::move(r1)}, room2{std::move(r2)} {}

~Door() = default;

virtual void enter() override {}

nodiscard
virtual unique_ptr clone() const override {
return std::make_unique(*this);
}

void initialize(shared_ptr r1, shared_ptr r2) {
room1 = std::move(r1);
room2 = std::move(r2);
}

Door(const Door&) = delete;
Door& operator=(const Door&) = delete;
};

class Maze {
private:
vector> rooms;
public:
Maze() = default;
~Maze() = default;

Maze& addRoom(shared_ptr r) {
std::println("Maze::addRoom {}", reinterpret_cast(r.get()));
rooms.push_back(std::move(r));
return *this;
}

nodiscard
shared_ptr roomNo(int n) const {
for (const Room& r: rooms) {
// actual lookup logic here...
}
return nullptr;
}

nodiscard
virtual unique_ptr clone() const {
return std::make_unique(*this);
}
};

class MazeFactory {
public:
MazeFactory() = default;

virtual ~MazeFactory() = default;

nodiscard
virtual unique_ptr makeMaze() const {
return std::make_unique();
}

nodiscard
virtual shared_ptr makeWall() const {
return std::make_shared();
}

nodiscard
virtual shared_ptr makeRoom(int n) const {
return std::make_shared(n);
}

nodiscard
virtual shared_ptr makeDoor(shared_ptr r1, shared_ptr r2) const {
return std::make_shared(std::move(r1), std::move(r2));
}
};

class MazePrototypeFactory: public MazeFactory {
private:
unique_ptr prototypeMaze;
shared_ptr prototypeRoom;
shared_ptr prototypeWall;
shared_ptr prototypeDoor;
public:
MazePrototypeFactory(unique_ptr m, shared_ptr w, shared_ptr r, shared_ptr d):
MazeFactory(), prototypeMaze{std::move(m)}, prototypeRoom{std::move(r)},
prototypeWall{std::move(w)}, prototypeDoor{std::move(d)} {}

~MazePrototypeFactory() = default;

virtual unique_ptr makeMaze() const override {
return prototypeMaze->clone();
}

nodiscard
virtual shared_ptr makeRoom(int n) const override {
return prototypeRoom->clone();
}

nodiscard
virtual shared_ptr makeWall() const override {
return prototypeWall->clone();
}

nodiscard
virtual shared_ptr makeDoor(shared_ptr r1, shared_ptr r2) const override {
shared_ptr door = prototypeDoor->clone();
door->initialize(std::move(r1), std::move(r2));
return door;
}

MazePrototypeFactory(const MazePrototypeFactory&) = delete;
MazePrototypeFactory& operator=(const MazePrototypeFactory&) = delete;
};

class MazeGame {
public:
MazeGame() = default;
~MazeGame() = default;

nodiscard
unique_ptr createMaze(MazePrototypeFactory& factory) {
unique_ptr maze = factory.makeMaze();
shared_ptr r1 = factory.makeRoom(1);
shared_ptr r2 = factory.makeRoom(2);
shared_ptr door = factory.makeDoor(r1, r2);

maze->addRoom(std::move(r1))
.addRoom(std::move(r2));

r1->setSide(Direction::NORTH, factory.makeWall())
.setSide(Direction::EAST, door)
.setSide(Direction::SOUTH, factory.makeWall())
.setSide(Direction::WEST, factory.makeWall());

r2->setSide(Direction::NORTH, factory.makeWall())
.setSide(Direction::EAST, factory.makeWall())
.setSide(Direction::SOUTH, factory.makeWall())
.setSide(Direction::WEST, door);

return maze;
}
};

int main(int argc, char* argv[]) {
MazeGame game;
MazePrototypeFactory simpleMazeFactory(
std::make_unique(),
std::make_shared(),
std::make_shared(0),
std::make_shared()
);

unique_ptr maze = game.createMaze(simpleMazeFactory);
}

程序的输出为:

Maze::addRoom 0x1160f50
Maze::addRoom 0x1160f70
Room::setSide 0 0x11613c0
Room::setSide 2 0x1160f90
Room::setSide 1 0x11613e0
Room::setSide 3 0x1161400
Room::setSide 0 0x1161420
Room::setSide 2 0x1161440
Room::setSide 1 0x1161460
Room::setSide 3 0x1160f90

参见

  • 函数原型

引用
外部链接

评论 (0)

  • 还没有评论,来抢沙发吧。