【问题标题】:Swift Prototype Design Pattern [closed]Swift 原型设计模式
【发布时间】:2016-08-04 15:06:58
【问题描述】:

有人可以帮我理解这段 Swift 代码吗?根据我目前正在阅读的书,此代码是原型设计模式的实现:

class AbstractCard {
    var name: String?
    var mana: Int?
    var attack: Int?
    var defense: Int?
    init(name:String?, mana:Int?, attack:Int?, defense:Int?) {
        self.name = name
        self.attack = attack
        self.defense = defense
        self.mana = mana
    }
    func clone() -> AbstractCard {
        return AbstractCard(name: self.name, mana: self.mana, attack:
            self.attack, defense: self.defense)
    }
}
class Card: AbstractCard {
    var someNumber: Int
    override init(name:String?, mana:Int?, attack:Int?, defense:Int? ){
        someNumber = 2
        super.init(name: name,mana: mana,attack: attack,defense:
            defense)
    }
}
// Simulate our client
// This is the card that we will copy
let raidLeader = Card(name: "Raid Leader", mana: 3, attack: 2, defense: 2)
// Now we use our faceless Manipulator card to clone the

let facelessManipulator = raidLeader.clone()
print("\(facelessManipulator.name, facelessManipulator.mana, facelessManipulator.attack, facelessManipulator.defense)")
print(facelessManipulator.dynamicType) // prints "AbstractCard"

如果克隆对象的 dynamicType 仍然是 AbstractCard 而不是 Card,那么这种模式的意义何在。您甚至无法访问特定于 Card 的变量。我尝试将此对象转换为 Card,但出现错误 "Execution was interrupted reason: signal SIGABRT"

【问题讨论】:

  • 我认为您需要在 Card 中覆盖 clone
  • cloneAbstractCard 中的实现有点没有意义,不是吗?因为这只是一个抽象类。

标签: swift design-patterns


【解决方案1】:

让我们先弄清楚原型模式:

原型模式通过复制现有对象(称为原型)来创建新对象。

首先Prototype模式的实现方式有很多种,我认为本书的作者在这个案例中试图以最恰当的方式向你解释该模式的一个用户案例。

因此,当有人放入 cmets 时,应在子类中重写 clone 方法以允许正确克隆对象,如下所示:

class Card: AbstractCard {

   var someNumber: Int

   override init(name:String?, mana:Int?, attack:Int?, defense:Int? ){
      someNumber = 2
      super.init(name: name,mana: mana,attack: attack,defense:
        defense)
   }

   override func clone() -> AbstractCard {
      return Card(name: self.name, mana: self.mana, attack:
        self.attack, defense: self.defense)
   }
}

我不得不说,我曾担任这本书的技术审稿人,我认为作者以更好的方式表达了他对这种模式的使用。

如果您仔细考虑,每次在 Swift 中使用值类型(数组、Int、Bool 等)时都会应用这种模式,因为每次将实例的值分配给另一个实例时,都会使用相同的值创建一个新副本价值观。问题在于参考值(类),每次将实例分配给新实例时,它们都会共享其值和对它们的修改。

实现该模式的另一种方式是使用NSCopying 协议,该协议声明了提供对象功能副本的方法,在我看来是最常用的。

例如:

class Card: NSObject, NSCopying {

   var name: String?
   var mana: Int?
   var attack: Int?
   var defense: Int?

   init(name:String?, mana:Int?, attack:Int?, defense:Int?) {
      self.name = name
      self.attack = attack
      self.defense = defense
      self.mana = mana
   }

   func copyWithZone(zone: NSZone) -> AnyObject {
       return Card(name: self.name, mana: self.mana, attack: self.attack, defense: self.defense)
   }
}

// Simulate our client
// This is the card that we will copy
let raidLeader = Card(name: "Raid Leader", mana: 3, attack: 2, defense: 2)
// Now we use our faceless Manipulator card to clone the

let facelessManipulator = raidLeader.copy() as Card
raidLeader.attack = 5

print("\(facelessManipulator.name, facelessManipulator.mana,   facelessManipulator.attack, facelessManipulator.defense)")
print("\(raidLeader.name, raidLeader.mana, raidLeader.attack, raidLeader.defense)")

您可以在这个问题中了解更多关于这种方式的信息:

希望对你有所帮助。

【讨论】:

  • 感谢您的回答。作者没有在书中覆盖clone是有原因的吗?是因为AbstractCardCard 实际上是同一个东西吗?
  • 是的,我认为作者的主要目标是隐藏创建对象的代码,使其不被我认为使用它们的组件。
猜你喜欢
  • 1970-01-01
  • 2011-07-25
  • 2016-03-25
  • 2015-06-29
  • 1970-01-01
  • 2012-12-02
  • 2012-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多