0

一个满嘴的问题,但它是我一直在努力解决的 OO 原则。假设我有一个电子商务应用程序并且有支付方式的概念,例如信用卡、Paypal、Apple pay 等。用户可以选择选择哪种支付方式,所以我需要将它们全部显示在一个列表中在屏幕上,根据选择的不同,这将用于驱动 UI,呈现不同的文本/图像/交互,并且将通过稍微不同的方式序列化为在线支付请求。

这是一些代码:

public class PaypalPayment : PaymentMethod {

    public string Token;
    public string String;

}

public class CreditCardPayment : PaymentMethod {

    public Address Address;
    public CreditCard CreditCard;

}

interface PaymentMethod {

}


public class Booking {
    public PaymentMethod PaymentMethod; //generic object

    //or

    public PaypalPayment PaypalPayment;
    public CreditCardPayment CreditCardPayment;
}

因此,在我的预订类中,我可以有一个由接口引用的通用支付对象,但我无法在没有强制转换的情况下访问底层类型,这很糟糕,因为实际上它们在域方面不共享任何公共属性。或者,我有多个属性以不同的方式感觉不好。用户只能选择一种付款方式,因此其他付款方式必须为空或某种空对象,我必须查询枚举或询问每种付款方式是否为空。此外,我的付款方式选择屏幕有点麻烦,因为我不能只迭代一个泛型类型,我必须明确建立列表。

从理论上讲,我可以向 PaymentMethod 接口添加一些方法,例如 Serialise() 或所有支付方法共有的一些 UI 表示方法,但是我必须在我不想做的模型对象中实现它们在我的模型层。

总的来说,我在典型的面向对象语言中没有一个干净的解决方案。我用 c# 编写了这个,但这可以适用于任何 OO 语言。

4

2 回答 2

1

在您的设计中,数据似乎已与逻辑分离。因此,为了让行为发生,Booking可能不得不沉迷于不适当的亲密关系中,因此出现了选角问题。Payment

一个惯用的 OO 实现将 1/ 定义明确的职责,并 2/ 将其操作和数据封装在同一个类中。然后,您可以在这些类的家族之上进行抽象,以便消费者代码可以统一调用它们的行为。

策略又名策略模式可能是付款的不错选择。

在 UI 方面,最好避免使用抽象,并为不同的支付方式使用不同的 UI。或者,您可以有一个抽象的 UI 支付模型,其具体实现知道如何呈现自己。

于 2015-05-12T12:12:32.747 回答
0

拥有一个接口并且无法访问底层类型正是抽象和松散耦合所追求的。这不应该很糟糕,但应该是可取的。要让所有可能的实例可供选择,您可以使用一个存储库来返回所有付款方式的集合。要实现这个存储库,您可以使用您喜欢的 ORM 并从数据库中加载它们,使用您喜欢的 IoC/DI 容器并让它创建您接口的所有实现者,或者对创建进行硬编码。无论适合您的需要和项目的需要。如果您也使用存储库的接口,您可以稍后交换实现。

于 2015-05-12T10:06:51.780 回答