首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >区分不同处理的类类型的最佳方法

区分不同处理的类类型的最佳方法
EN

Stack Overflow用户
提问于 2015-03-17 09:39:34
回答 3查看 82关注 0票数 0

我想知道使用以下每一种方法来区分主父类的子类并以不同的方式处理它们的优缺点。我知道这是很基本的,但我在任何地方都找不到这些方法的完全比较。

例如:-我有一个OneTimePayment支付超级抽象类和两个扩展类switchPaymentState订阅--我有一个方法switchPaymentState,它应该以不同的方式处理这些类型。

  • 选项1:使用instanceof 公共无效switchPaymentState(支付支付){if(OneTimePayment的支付实例){//做某事}否则如果(订阅的支付实例){//做其他的}}
  • 备选案文2:使用枚举类型参数(或其他.) 公共枚举PaymentType { ONE_TIME_PAYMENT,订阅;}公共抽象支付(PaymentType类型){ this.type = type;} public OneTimePayment() { super(ONE_TIME_PAYMENT);}公共订阅(){Super(订阅);} 然后: 公共无效switchPaymentState(支付){交换机(payment.type){ case ONE_TIME_PAYMENT: //做一些中断;case订阅://做某事中断;}}
  • 备选方案3:使用重载方法 公共无效switchPaymentState(OneTimePayment支付){ //do }公共空switchPaymentState(订阅付款){//做某事}

那么,哪一种方式是最好的(还是完全相反?)为什么?

编辑:我需要根据类类型执行的操作并不是对类本身的操作,我需要从支付中获取一些数据并通过其他服务发送它,因此像在类中实现这个功能并调用它这样的解决方案在这种情况下不会有帮助。谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-17 09:53:18

在许多情况下,您的选项3将无法工作,因为重载是在编译时而不是在运行时解决的。如果引用的类型为Payment,则不可能使用重载。

在面向对象的设计方面,使用覆盖的方法是“最干净”的方法。然而,它的缺点是,类似的功能是针对多个类的,而在切换和解决方案的实例中,所有的东西都是在一起的。

提供两个世界中最好的一种选择是所谓的访问者模式。为每个类创建一个接口PaymentVisitor,为每个类创建一个句柄方法,如下所示:

代码语言:javascript
复制
interface PaymentVisitor {
    void visitOneTimePayment(OneTimePayment payment);
    void visitSubscription(Subscription payment);
}

然后在抽象超类中添加一个方法访问:

代码语言:javascript
复制
abstract class Payment {
    ...
    abstract void callVisitor(PaymentVisitor visitor);
}

它在所有子类中实现如下:

代码语言:javascript
复制
class OneTimePayment {
    ...
    @Override void callVisitor(PaymentVisitor visitor) {
        visitor.handleOneTimePayment(this);
    }
}

class Subscription {
    ...
    @Override void callVisitor(PaymentVisitor visitor) {
        visitor.handleSubscription(this);
    }
}

现在,在所有情况下,您都会编写类似于(用伪Java)的东西:

代码语言:javascript
复制
switch (type of x) {
    case OneTimePayment:
         // Code
         break;
     case Subscription:
         // Code
         break;
}

现在,您可以编写干净的和类型安全的:

代码语言:javascript
复制
x.callVisitor(new PaymentVisitor() {
    @Override void handleOneTimePayment(OneTimePayment payment) {
        // Code
    }
    @Override void handleSubscription(Subscription payment) {
        // Code
    }
});

还请注意,访问者是在内部类中实现的,因此仍然可以访问方法主体中定义的所有(实际上)最终变量。

票数 1
EN

Stack Overflow用户

发布于 2015-03-17 09:46:19

最模块化的方式是使用覆盖。

您将有一个switchPaymentState方法,它接受基本类型--支付--并调用支付类中的一个方法来进行处理。该方法可以在每个支付子类中重写。

代码语言:javascript
复制
public void switchPaymentState(Payment payment)
{
    payment.handlePayment();
}

您的switchPaymentState方法不需要知道哪些子类存在支付,如果明天添加新的子类,它也不需要更改。

票数 3
EN

Stack Overflow用户

发布于 2015-03-17 10:08:31

不管你是怎么做的,我认为这个开关有点反模式。更标准的OO方法是在两个子类中实现相同的方法,并让每个类适当地管理事物。换句话说

代码语言:javascript
复制
abstract class Payment {
    abstract void processPayment(BigDecimal amount);
    abstract void processRefund...
} 

class OneTimePayment extends Payment {
    void processPayment(BigDecimal amount){... }

    void processRefund...
}

等。

另外,除非您在超类中重用大量代码,否则考虑使用基于接口的实现而不是子类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29095708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档