在电子商务应用程序中,以下是高级API
interface Order{
public List<PaymentGroup> getPaymentGroups();
}
interface PaymentGroup{}
class PaymentGroupImpl implements PaymentGroup{}
class CreditCard extends PaymentGroupImpl{}
class GiftCard extends PaymentGroupImpl{}
class OrderManager{ //Manager component used to manipulate Order}
需要添加一些实用工具方法,例如hasGiftCard(), hasCreditCard(), getGiftCards(), getCreditCards()
两种方法 -
1)在Order
中添加这些内容。但是,这会导致Order和PaymentGroup实现者之间的耦合(如CreditCard,GiftCard)示例 -
interface Order {
public List<GiftCard> getGiftCards();
}
2)将这些移至OrderManager
。
class OrderManager{
public List<GiftCard> getGiftCards(Order order){}
}
我个人更喜欢2),我只是好奇有没有理由选择1)超过2)
答案 0 :(得分:2)
我有两个答案。一个是我称之为Old Skool OOP而另一个我称之为New Skool OOP。
让我们先解决New Skool。 GoF和Martin Fowler改变了人们对OOP的看法。添加像hasGiftCard()这样的方法会导致在代码中添加条件逻辑/分支。它可能看起来像这样:
if (order.hasGiftCard()) {
//Do gift card stuff
} else {
//Do something else
}
最终这种代码变得脆弱。在一个大型应用程序上,许多开发人员将编写谓词方法。谓词方法断言某些东西并返回true或false。这些方法通常以“has”,“is”或“contains”开头。例如,isValid(),hasAddress()或containsFood()。还有更多开发人员编写使用这些谓词方法的条件逻辑。
为了避免所有这些条件逻辑软件工程师改变了他们对面向对象的看法。他们开始使用策略模式,访问者模式和依赖注入等内容,而不是谓词方法和条件逻辑。您的问题域中的示例可能如下所示:
//Old Skool
if (this.hasCreditCard()) {
orderManager.processCreditCard(this.getCreditCards());
}
这是解决同一问题的另一种方法:
//New Skool
for(PaymentItem each : getPaymentItems()){
each.process(this);
}
New Skool方法将问题摆在首位。而不是让Order和OrderManager负责繁重的工作,而是将工作推送到下级对象。这些模式很光滑,因为:
那是新的Skool。回到那一天,我写了很多Old Skool面向对象的代码。如果你想走那条路,这是我的建议。
List getCreditCards() { List list = new ArrayList(); for(PaymentGroup each : getPaymentGroups()){ if(each.isCreditCard()) { list.add(each); } return list; }
- 在Order类中,创建类似hasCreditCards()的谓词方法。如果性能不是问题,请执行以下操作:
boolean hasCreditCards() { return !getCreditCards().isEmpty(); }
如果表现有问题,请做一些更聪明的事情:
boolean hasCreditCards() { for(PaymentGroup each : getPaymentGroups()){ if(each.isCreditCard()) { return true; } return false; } }
要意识到如果添加新的支付组,必须在旧Skool范例的很多地方添加代码。