我有两个答案。一个是我称之为 Old Skool OOP 的东西,另一个是我称之为 New Skool OOP 的东西。
让我们先解决 New Skool。 GoF 和 Martin Fowler 改变了人们看待 OOP 的方式。添加诸如 hasGiftCard() 之类的方法会导致在代码中添加条件逻辑/分支。它可能看起来像这样:
if (order.hasGiftCard()) {
//Do gift card stuff
} else {
//Do something else
}
最终这种代码会变得脆弱。在大型应用程序中,许多开发人员将编写谓词方法。谓词方法断言某些东西并返回真或假。这些方法通常以单词“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 负责繁重的工作,而是将工作推给从属对象。这些模式很漂亮,因为:
- 它们消除了很多“if”语句,
- 代码更柔软,更容易扩展应用,并且
- 不是每个开发人员都对 Order 和 OrderManager 进行更改,而是将工作分散到更多类中,并且代码合并更容易。
那是新斯库尔。过去,我写了很多 Old Skool 面向对象的代码。如果你想走那条路,这是我的建议。
- 恕我直言,您不需要 PaymentGroup 接口和 PaymentGroupImpl 类。如果所有支付类都继承了 PaymentGroupImpl,那么就去掉接口,把 PaymentGroup 变成一个类。
- 将 isCreditCard()、isGiftCertificate() 等方法添加到 PaymentGroup 类。让他们都返回“false”。
- 在 PaymentGroup 的子类中,覆盖这些方法以在适当的情况下返回 true。例如,在 CreditCard 类中,isCreditCard() 应该返回“true”。
- 在 Order 类中,创建按类型过滤付款的方法。创建 getCreditCards()、getGiftCertificates() 等方法。在传统 Java 中(没有 lambda 或辅助库),这些方法可能看起来像这样
列出 getCreditCards() {
列表列表 = 新的 ArrayList();
for(PaymentGroup each : getPaymentGroups()){
如果(每个.isCreditCard()){
list.add(每个);
}
返回列表;
}
-在 Order 类中,创建谓词方法,如 hasCreditCards()。如果性能不是问题,请执行以下操作:
boolean hasCreditCards() {
返回 !getCreditCards().isEmpty();
}
如果性能是一个问题,做一些更聪明的事情:
boolean hasCreditCards() {
for(PaymentGroup each : getPaymentGroups()){
如果(每个.isCreditCard()){
返回真;
}
返回假;
}
}
意识到如果你添加一个新的支付组,在 Old Skool 范式中的很多地方都必须添加一个代码。