用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
我们希望我们的框架类和应用类进行解藕,但又必须知道如何创建应用类的对象。(很抽象=。=)
—— 声明一个克隆自身的接口。
—— 实现一个克隆自身的操作。
—— 让一个原型克隆自身从而创建一个新的对象。
Prototype 有许多和 Abstract Factory 和 Builder 一样的效果: 它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
当一个系统的原型数目不固定时(也就是说,它们可以动态创建和销毁),要保持一个可用原型的注册表。
原型管理器是一个关联存储器,它返回一个与给定关键字匹配的原型。
写下了这么多笔记,这么多概念还是有点蒙圈 =。= ,于是又到维基百科搜了一下。
维基百科给出的定义:
原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据
这就理解了!!其实就是 OC 中的 copy,C++中的拷贝构造函数 =。= 。
我们来看看在 Swift 这么实现吧。其实 Swift 结构体本身就是值语义的 = = 。所以我用 Class ,根据书上的例子来个 Swift 版好了。
下面是我们 Swift 版本的 MazePrototypeFactory
。使用泛型可以让我们的 MazePrototypeFactory
适用于不同类型的 Door,Wall,Room 。 这里新的构造器只初始化它的原型。
class MazePrototypeFactory<W, D, R>: MazeFactory where W: WallType, D: DoorType, R: RoomType { var prototypeMaze: Maze var prototypeDoor: D var prototypeWall: W var prototypeRoom: R func makeRoom(_ n: Int) -> RoomType { return R(no: n) } func makeMaze() -> Maze { return Maze() } init(m: Maze, d: D, w: W, r: R) { prototypeMaze = m prototypeDoor = d prototypeWall = w prototypeRoom = r } }
我们以克隆原型的方式定义, makeWall
和 makeDoor
。
extensionMazePrototypeFactory{ funcmakeWall() -> WallType { return prototypeWall.clone() } funcmakeDoor(r1: RoomType, r2: RoomType) -> DoorType { let door = prototypeDoor.clone() door.initialize(r1: r1, r2: r2) return door } }
我们只需要使用基本的原型进行初始化,就可以由 MazePrototypeFactory 来创建一个原型的或缺省得迷宫。
let simpleMazeFactory = MazePrototypeFactory(m: Maze(), d: Door(), w: Wall(), r: Room()) let game = MazeGame.createMaze(mazeFactory: simpleMazeFactory) print("/(game)")
打印结果:
=========================== Maze room: room_2 Room north is Optional(Wall) south is Optional(Wall) east is Optional(Wall) west is Optional(Door) room_1 Room north is Optional(Wall) south is Optional(Wall) east is Optional(Door) west is Optional(Wall) ===========================
和之前的例子一样,我们又需要定义一个 Bombed 的迷宫。这次我们就不需要去定义一个 Bombed 的抽象工厂类了。我们以 BombedWall
和 RoomWithABomb
作为原型就可以构造出一个 Bombed 的迷宫。
let bombMazeFactory = MazePrototypeFactory(m: Maze(), d: Door(), w: BombedWall(), r: RoomWithABomb()) let bombedGame = MazeGame.createMaze(mazeFactory: bombMazeFactory) print("/(bombedGame)")
打印结果:
=========================== Maze room: room_2 RoomWithABomb Bombe is false north is Optional(BombedWall Bombe is false) south is Optional(BombedWall Bombe is false) east is Optional(BombedWall Bombe is false) west is Optional(Door) room_1 RoomWithABomb Bombe is false north is Optional(BombedWall Bombe is false) south is Optional(BombedWall Bombe is false) east is Optional(Door) west is Optional(BombedWall Bombe is false) ===========================
Prototype 一般可以和 Abstract Factory 一起使用,大量使用 Composite 和 Decorator 也可以 Prototype 获得收益。
附: Playground 代码
欢迎讨论、批评、指错。