【问题标题】:Too many abstract functions - OOP Best practices太多抽象函数 - OOP 最佳实践
【发布时间】:2017-12-03 22:36:14
【问题描述】:

Abstract 类的抽象函数声明有多少?

例如,对于基于会员的支付系统:

支持多种支付方式:

  • 信用卡
  • 令牌(信用卡支付,但使用令牌)
  • 重定向(即 Paypal)
  • 手动(管理员手动向用户收费)

我有一个抽象类 PaymentMode,上面的不同模式扩展到这个类。

每种模式都有自己独特的方法逻辑,我必须在 PaymentMode 类中为这些方法声明抽象方法

// each mode has own way of validating the customer data
validate();

// own logic of cleaning customer data (e.g removing/adding/updating)
preparePaymentData();

// returns a string for saving in database, subclass must implement so developers plan to extend the PaymentMode abstract will be forced to return the correct value
getModeOfPayment();

// each mode has its own logic when determining payment gateways to attempt
getGatewaysToAttempt();

// before sending the payment to gateway, each mode has its own logic when adding specific data
addCustomDataSpecificForGateway();

// check if transaction has failed, different payment modes has different logic of determining a failed transaction
isTransactionFailed()

每种模式都有 6 个独特的逻辑,我已经设法将通用代码通用化并将其放在 PaymentMode 类中。

随着我们实施每种模式独有的新功能,这个数字可能会增加。

在我看来,我担心如果任何未来的开发人员扩展我的 PaymentMode 类,他必须实现所有抽象函数声明。

那么大量的抽象函数声明是否表明糟糕的设计?多少算太多?

如果它是一个糟糕的设计,你能推荐任何可以解决这个问题的技术或设计模式

谢谢

【问题讨论】:

  • 如果您的抽象类确实没有实现功能,并且您不希望它会实现,那么您可以考虑只使用 接口。如果您想描述付款的行为,而不具体指定行为是什么,那么使用接口将是一个非常合适的选择。
  • @TimBiegeleisen 感谢您的建议,但我的抽象类中包含一些功能,因为这些不同的支付方式共享一些共同的功能
  • 我不认为拥有一些抽象方法有什么不好的。您还可以考虑同时使用接口和抽象类。

标签: oop abstract-class


【解决方案1】:

没有具体细节很难回答,但是:

显然对抽象方法(接口或抽象类中的方法)没有硬性限制,尽管越少总是更清晰、更容易理解。

表明次优设计是您需要使用每种新的支付方式修改支付方式的抽象。对我来说,这表明抽象失败。 OOP 不仅仅是将通用代码提取出来,避免重复,它还涉及抽象。

我会研究以某种方式将控制权真正的控制权)转移到付款方式。信任付款方式,将付款任务委托给它。

我的意思是,您保留控制某处,您要求付款方式完成其工作的特定部分(不同的具体方法的部分不同)。像validate()prepare...() 这样的步骤。而且,您希望它为您提供“网关”,所以现在付款方式之外的代码(即使它是超类)必须知道那是什么,或者如何处理它。

与其做所有这些,不如尝试提出一种设计,将完全控制权转移到支付方式,这样它就可以在没有外部代码的情况下完成它的工作,假设任何特定的步骤集。

例如:

public interface PaymentMethod {
    Receipt payFor(Bill bill);
}

这里的PaymentMethod 负责自己做所有事情。重定向用户,将收据保存在数据库中,无论需要什么。一旦您对这种“主要”抽象感到满意(它涵盖了所有用例),您就可以创建较小的抽象来涵盖诸如保存到数据库之类的细节,前提是所有方法都相同。

与此相关:不要使用抽象父类作为在类之间共享代码的一种方式,这不完全是继承的目的。为不同的“代码片段”创建适当的抽象,并让它们被“更大”的抽象(即组合)使用。

【讨论】:

    【解决方案2】:

    没有这么多的抽象函数声明是不好的,尽管数量巨大可能意味着设计存在缺陷。请注意单一责任原则。

    您已经定义了 4 种模式 - 所以我认为在您的情况下,您应该为每种模式做 4 个接口。完成此操作后,您可以查看所有 4 个的共同点并提取基本接口。您可以考虑为所有它们提取 6 个独特的逻辑也作为接口...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2011-04-14
      • 2011-03-29
      • 2013-06-19
      • 2010-10-04
      相关资源
      最近更新 更多