美文网首页程序员架构算法设计模式和编程理论手机移动程序开发
设计模式笔记及Swift上的实现之四『PROTOTYPE(原型)

设计模式笔记及Swift上的实现之四『PROTOTYPE(原型)

作者: sim_cai | 来源:发表于2017-01-30 21:27 被阅读34次

    意图

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

    动机

    我们希望我们的框架类和应用类进行解藕,但又必须知道如何创建应用类的对象。(很抽象=。=)

    使用性

    • 当要实例化的类是在运行时刻指定是,例如,通过动态加载
    • 为了避免创建一个与产品类层次平行的工厂类层次
    • 当一个类的实例只能有几个不同状态组合中的一种。

    结构

    ## 参与者

    • Prototype

    —— 声明一个克隆自身的接口。

    • ConcretePrototype

    —— 实现一个克隆自身的操作。

    • Client

    —— 让一个原型克隆自身从而创建一个新的对象。

    协助

    • 客户请求一个原型克隆自身。

    效果

    Prototype 有许多和 Abstract Factory 和 Builder 一样的效果: 它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。

    1. 运行时刻增加和删除产品
    2. 改变值以指定新对象
    3. 改变结构以指定新对象
    4. 减少子类的构造
    5. 用类动态配置应用

    实现原型是,要考虑的问题

    • 使用一个原型管理器

    当一个系统的原型数目不固定时(也就是说,它们可以动态创建和销毁),要保持一个可用原型的注册表。
    原型管理器是一个关联存储器,它返回一个与给定关键字匹配的原型。

    • 实现克隆操作
    • 初始化克隆对象

    维基百科定义

    写下了这么多笔记,这么多概念还是有点蒙圈 =。= ,于是又到维基百科搜了一下。

    维基百科给出的定义:

    原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
    原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据

    这就理解了!!其实就是 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
        }
    }
    

    我们以克隆原型的方式定义,makeWallmakeDoor

    extension MazePrototypeFactory {
        
        func makeWall() -> WallType {
            return prototypeWall.clone()
        }
        
        func makeDoor(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 的抽象工厂类了。我们以 BombedWallRoomWithABomb 作为原型就可以构造出一个 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 代码

    欢迎讨论、批评、指错。

    相关文章

      网友评论

        本文标题:设计模式笔记及Swift上的实现之四『PROTOTYPE(原型)

        本文链接:https://www.haomeiwen.com/subject/qrphittx.html