我的业务情景如下:
我们可以使用多种支付系统(PS1,PS2,PS3 ......)进行付款。常见的功能是 - ProcessPayment。付款基于数据库中的数据。
我可以使用哪种设计?
1)使用ProcessPayment方法和PaymentSystemBase基类创建IPaymentSystem接口,该基类适用于数据库内容,如连接,检索数据等。创建特定的类PS1,PS2,PS3 ......实现IPaymentSystem接口,并从PaymentSystemBase基类派生,以便使用常见的数据库内容。
2)创建包含所有ProcessPayment方法和数据库内容的抽象基类。
3)其他东西。
interface IPaymentSystem
{
void ProcessPayment();
}
public class PaymentSystemBase
{
public PaymentSystemBase()
{
CheckInputParameters();
CreateDatabaseConnection();
}
protected void CheckInputParameters() {}
protected void CreateDatabaseConnection() {}
}
public class PS1 : PaymentSystemBase, IPaymentSystem
{
public void ProcessPayment()
{
Console.WriteLine("Process PS1...");
}
}
public class PS2 : PaymentSystemBase, IPaymentSystem
{
public void ProcessPayment()
{
Console.WriteLine("Process PS2...");
}
}
答案 0 :(得分:2)
从您的代码中我假设,为了付款,我必须: - 验证/检查参数 - 处理数据库连接 - 可能更多
在我看来,这些行动应该由两个不同的对象完成。 PaymentSystem应该将它们用作协作者。没有抽象类。
这里的经验法则是“赞成合成而不是继承”:http://www.hautelooktech.com/2013/02/05/design-principle-favor-composition-over-inheritance/
为了能够创建不同的支付系统,您可以从PaymentSystem的每个协作者中提取一个界面,并通过属性注入或更好的构造函数注入来切换它们(也就是组成一个新的支付系统)。
http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/
总而言之,您的PaymentSystem应该是非常简单的协作者的“协调者”。
答案 1 :(得分:0)
我会使用第一种方法,Interface,Abstract类来实现一般方法和具体类。
在我看来,抽象类绝不是接口的替代品,所以我将放弃第二种方法。
其他解决方案可能取决于您的业务,要求......
唯一可能出错的是,您的课程可能会违反单一的责任,因为它必须处理付款等事情并创建数据库连接。对我来说,数据库连接应该在另一个地方。
此致
答案 2 :(得分:0)
在这种情况下,我建议您使用Interface。只涉及一种方法。您可以为各种付款类型(PS1,PS2,PS3 ......)提供自己的实施。
如果你有一些情况,你有更多的方法和变量,这对于ProcessPayment来说是常见的,那么你可以想到抽象类,其中至少有一些方法行为不会被改变。但请记住,当您使用Abstract类时,您正在丢失类继承。
如果只涉及一种方法,那么请使用Interface。
答案 3 :(得分:0)
你宁愿创建一个抽象类来放置所有数据库的东西; 如果你想声明接口,那么抽象类应该实现它:
// Not necessary
public IPaymentable {
void ProcessPayment();
}
// Interface should be implemented here
public abstract class PaymentSystemBase: IPaymentable {
...
private IDatabaseConnection connectToDatabase() {...}
...
protected void loadFromDatabase() {...}
protected void saveToDatabase() {...}
...
protected PaymentSystemBase() {...}
public abstract void ProcessPayment();
}
// A concrete class should only override ProcessPayment() method
public class PS1: PaymentSystemBase {
public override void ProcessPayment() {...}
}
// A concrete class should only override ProcessPayment() method
public class PS2: PaymentSystemBase {
public override void ProcessPayment() {...}
}