【问题标题】:Smalltalk - How to avoid typechecks in this situation?Smalltalk - 在这种情况下如何避免类型检查?
【发布时间】:2016-12-26 16:48:41
【问题描述】:

这是一个例子。

假设以下约束:

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

我有以下课程:

  • 抽象商店

    • 食品店
    • 服装店
    • MixedShop
  • 抽象产品

    • 服装
    • 食物

功能:

    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 解决这个问题,但它似乎使代码更难维护。

【问题讨论】:

标签: smalltalk typechecking object-oriented-analysis


【解决方案1】:

你也可以通过双重调度来做到这一点:

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

关于您的用例,我会说最好有一个受支持的项目集合,因为您可能有许多商店具有不同的项目组合。但是使用双重调度,您永远不会检查类型。

【讨论】:

  • 这是 IMO 更好的答案
【解决方案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,这也是一种难闻的气味。在您的情况下,仅使用 Shop 和 Product 就足够抽象了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    相关资源
    最近更新 更多