2016-12-26 105 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更好的答案 –

相關問題