【问题标题】:Smalltalk - How to avoid typechecks in this situation?Smalltalk - 在这种情况下如何避免类型检查?
【发布时间】:2016-12-26 16:48:41
【问题描述】:
这是一个例子。
假设以下约束:
- 一个商店只能有 5 种产品。
- 食品店只能添加食品。
- 服装店只能添加服装产品。
- 混合商店可以添加两种产品。
我有以下课程:
功能:
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
关于您的用例,我会说最好有一个受支持的项目集合,因为您可能有许多商店具有不同的项目组合。但是使用双重调度,您永远不会检查类型。
【解决方案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 就足够抽象了。