热门问题
时间线
聊天
视角
原型模式
来自维基百科,自由的百科全书
Remove ads
原型模式(英語:prototype pattern),是一種創建型模式[1]:117,其特點在於通過「複製」一個已經存在的實例來返回新的實例,而不是新建實例。被複製的實例就是我們所稱的「原型」,這個原型是可定製的。

原型模式多用於創建複雜的或者耗時的實例,因為這種情況下,複製一個已經存在的實例使程序運行更高效;或者創建值相等,只是命名不一樣的同類數據。
結構

在上面的UML類圖中,Client類提及Prototype接口來克隆一個Product。Product1類通過創建自身複本來實現Prototype接口。
UML序列圖展示了運行時交互:Client對象調用clone()於prototype:Product1對象之上,它創建並返回自身的一個複本(product:Product1對象)。
示例
下面是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<100; i++)
tempCookie = cm.makeCookie();//通过复制原型返回多个cookie
}
}
下面是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()]
Remove ads
下面是基於《設計模式》書中前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<MapSite> clone() const = 0;
virtual ~MapSite() = default;
};
class Room: public MapSite {
private:
int roomNumber;
shared_ptr<array<shared_ptr<MapSite>, 4>> sides;
public:
explicit Room(int n = 0):
roomNumber{n}, sides{std::make_shared<array<shared_ptr<MapSite>, 4>>()} {}
~Room() = default;
Room& setSide(Direction d, shared_ptr<MapSite> ms) {
(*sides)[static_cast<size_t>(d)] = std::move(ms);
std::println("Room::setSide {} ms", d);
return *this;
}
virtual void enter() override {}
virtual unique_ptr<MapSite> clone() const override {
return std::make_unique<Room>(*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<MapSite> clone() const override {
return std::make_unique<Wall>(*this);
}
};
class Door: public MapSite {
private:
shared_ptr<Room> room1;
shared_ptr<Room> room2;
public:
explicit Door(shared_ptr<Room> r1 = nullptr, shared_ptr<Room> r2 = nullptr):
MapSite(), room1{std::move(r1)}, room2{std::move(r2)} {}
~Door() = default;
virtual void enter() override {}
[[nodiscard]]
virtual unique_ptr<MapSite> clone() const override {
return std::make_unique<Door>(*this);
}
void initialize(shared_ptr<Room> r1, shared_ptr<Room> r2) {
room1 = std::move(r1);
room2 = std::move(r2);
}
Door(const Door&) = delete;
Door& operator=(const Door&) = delete;
};
class Maze {
private:
vector<shared_ptr<Room>> rooms;
public:
Maze() = default;
~Maze() = default;
Maze& addRoom(shared_ptr<Room> r) {
std::println("Maze::addRoom {}", reinterpret_cast<void*>(r.get()));
rooms.push_back(std::move(r));
return *this;
}
[[nodiscard]]
shared_ptr<Room> roomNo(int n) const {
for (const Room& r: rooms) {
// actual lookup logic here...
}
return nullptr;
}
[[nodiscard]]
virtual unique_ptr<Maze> clone() const {
return std::make_unique<Maze>(*this);
}
};
class MazeFactory {
public:
MazeFactory() = default;
virtual ~MazeFactory() = default;
[[nodiscard]]
virtual unique_ptr<Maze> makeMaze() const {
return std::make_unique<Maze>();
}
[[nodiscard]]
virtual shared_ptr<Wall> makeWall() const {
return std::make_shared<Wall>();
}
[[nodiscard]]
virtual shared_ptr<Room> makeRoom(int n) const {
return std::make_shared<Room>(n);
}
[[nodiscard]]
virtual shared_ptr<Door> makeDoor(shared_ptr<Room> r1, shared_ptr<Room> r2) const {
return std::make_shared<Door>(std::move(r1), std::move(r2));
}
};
class MazePrototypeFactory: public MazeFactory {
private:
unique_ptr<Maze> prototypeMaze;
shared_ptr<Room> prototypeRoom;
shared_ptr<Wall> prototypeWall;
shared_ptr<Door> prototypeDoor;
public:
MazePrototypeFactory(unique_ptr<Maze> m, shared_ptr<Wall> w, shared_ptr<Room> r, shared_ptr<Door> d):
MazeFactory(), prototypeMaze{std::move(m)}, prototypeRoom{std::move(r)},
prototypeWall{std::move(w)}, prototypeDoor{std::move(d)} {}
~MazePrototypeFactory() = default;
virtual unique_ptr<Maze> makeMaze() const override {
return prototypeMaze->clone();
}
[[nodiscard]]
virtual shared_ptr<Room> makeRoom(int n) const override {
return prototypeRoom->clone();
}
[[nodiscard]]
virtual shared_ptr<Wall> makeWall() const override {
return prototypeWall->clone();
}
[[nodiscard]]
virtual shared_ptr<Door> makeDoor(shared_ptr<Room> r1, shared_ptr<Room> r2) const override {
shared_ptr<Door> 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<Maze> createMaze(MazePrototypeFactory& factory) {
unique_ptr<Maze> maze = factory.makeMaze();
shared_ptr<Room> r1 = factory.makeRoom(1);
shared_ptr<Room> r2 = factory.makeRoom(2);
shared_ptr<Door> 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<Maze>(),
std::make_shared<Wall>(),
std::make_shared<Room>(0),
std::make_shared<Door>()
);
unique_ptr<Maze> 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
Remove ads
參見
引用
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads
