2016-12-26 65 views
3

这是一个例子。Smalltalk - 如何避免在这种情况下typechecks?

假设以下限制:

  • A商店只能有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

显示Smalltalk做事方式的两本书是http://stephane.ducasse.free.fr/FreeBooks/BestSmalltalkPractices/Draft-Smalltalk%20Best%20Practice%20Patterns%20Kent%20Beck.pdf和http:// sdmeta。 gforge.inria。fr/FreeBooks/SmalltalkDesignPatternCompanion /这些都是最后一本书的草稿,最好购买实体书,但这些是第二好的选择。 –

回答

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就足够抽象。

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 

关于您的使用情况下,我会说,这是更好地支持了项目的集合,你都可能有不同的组合,许多商店项目。但双重派遣你永远不会检查类型。

+0

这是IMO更好的答案 –

相关问题