【问题标题】:Does this method belong to Value object or Manager这个方法是属于 Value 对象还是 Manager
【发布时间】:2014-02-05 16:00:28
【问题描述】:

在电子商务应用程序中,以下是高级 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)

【问题讨论】:

  • 我认为这在很大程度上取决于 API 的结构。

标签: java atg


【解决方案1】:

我有两个答案。一个是我称之为 Old Skool OOP 的东西,另一个是我称之为 New Skool OOP 的东西。

让我们先解决 New Skool。 GoFMartin 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 负责繁重的工作,而是将工作推给从属对象。这些模式很漂亮,因为:

  1. 它们消除了很多“if”语句,
  2. 代码更柔软,更容易扩展应用,并且
  3. 不是每个开发人员都对 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 范式中的很多地方都必须添加一个代码。

【讨论】:

    猜你喜欢
    • 2014-08-29
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2019-11-24
    相关资源
    最近更新 更多