Smalltalk - 在这种情况下如何避免类型攻击?

时间:2016-12-26 16:48:41

标签: smalltalk typechecking object-oriented-analysis

这是一个例子。

假设以下约束:

  • 一家商店只能有5种产品。
  • 食品店只能添加食品。
  • 服装店只能添加衣服产品。
  • 混合商店可以添加两种产品。

我有以下课程:

  • AbstractShop

    • FoodShop
    • ClothesShop
    • MixedShop
  • AbstractProduct

    • 服装
    • 食品

功能:

    AbstractShop>>addProduct: aProduct
    (products size < 5)
    ifTrue:[^ products add:aProduct]
    ifFalse:[ self error: 'A shop can only have five products' ]

    FoodShop>>addProduct: aProduct
    (aProduct isMemberOf: Food)
    ifTrue:[^ super addProduct: aProduct]
    ifFalse:[ self error: 'You can only add food products to a foodshop' ]

    ClothesShop>>addProduct: aProduct
    (aProduct isMemberOf: Clothing)
    ifTrue:[^ super addProduct: aProduct]
    ifFalse:[ self error: 'You can only add clothing products to a clothes shop' ]

"ClothesShop doesn't override the addProduct, because it can add them both."

如何避免检查产品类型,看它是否可以添加到商店?我想避免这种情况,因为这是一种难闻的气味。我尝试使用Double Dispatch来解决它,但它似乎使代码更难以维护。

2 个答案:

答案 0 :(得分:6)

您也可以使用双重调度执行此操作:

AbstractShop>>addProduct: aProduct
  (products size < 5)
    ifTrue:[ ^ aProduct addToShop: self ]
    ifFalse:[ self error: 'A shop can only have five products' ]

AbstractShop>>addFoodProduct: aProduct
  ^ self subclassResponsibility

AbstractShop>>addClothingProduct: aProduct
  ^ self subclassResponsibility

FoodShop>>addFoodProduct: aProduct
  ^ products add: aProduct

FoodShop>>addClothingProduct: aProduct
  self error: 'You can only add clothing products to a clothes shop'

AbstractProduct>>addToShop: aShop
  ^ self subclassResponsibility

Food>>addToShop: aShop
  ^ aShop addFoodProduct: self

Clothing>>addToShop: aShop
  ^ aShop addClothingProduct: self

关于你的用例,我想说最好有一系列支持的项目,你可能会有很多商店有不同的项目组合。但是,通过双重发送,您永远不会检查类型。

答案 1 :(得分:2)

这是我们多次使用的模式。该类声明了哪些事物(或哪些类的实例)可以处理。

AbstractShop class >> allowedProducts
   self subclassResponsibility

FoodShop class >> allowedProducts
   ^#(Food)

ClothesShop class >> allowedProducts
   ^#(Clothing)

MixedShop class >> allowedProducts
   ^AbstractProduct subclasses

AbstractShop >> isAllowed: aProduct
   ^self class allowedProducts includes: aProduct class

 AbstractShop>>addProduct: aProduct
    products size < 5
       ifFalse:[ self error: 'A shop can only have five products' ].
    (self isAllowed: aProduct) 
       ifFalse: [self error: 'Product not allowed in this shop' ].
    ^ products add:aProduct

您不应重新定义addProduct。

但是如果气味有所说明,那么也应该提取容量检查中的魔术常数5,并且您应该将产品的验证与添加分开。

我从不喜欢称之为AbstractSomething,这也是一种难闻的气味。在您的情况下,仅使用商店和产品是足够抽象的。