質問

My business scenario is following:

There are several payment systems (PS1, PS2, PS3...) we can use to make payments. The common function is - ProcessPayment. The payment is based on data from database.

What design I could use?

1) Create IPaymentSystem interface with ProcessPayment method and PaymentSystemBase base class that works with database stuff such as connection, retrieving data and so on. Create particular classes PS1, PS2, PS3... that implement IPaymentSystem interface and derive from PaymentSystemBase base class in order to use common database stuff.

2) Create abstract base class that contains all together ProcessPayment method and database stuff.

3) Something else.

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...");
    }
}
役に立ちましたか?

解決 2

You'd rather create an abstract class in order to put there all the database stuff; if you want to declare an interface it is the abstract class should implement it:

// 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() {...}
}

他のヒント

From your code I assume that, in order to make a payment, I have to: - validate / check parameters - deal with a database connection - probably a lot more

In my opinion these actions should be done by two different objects. The PaymentSystem should use them as collaborators. No abstract classes.

The rule of thumb here is "favor composition over inheritance": http://www.hautelooktech.com/2013/02/05/design-principle-favor-composition-over-inheritance/

In order to be able to create different payment systems, you can extract an interface from every collaborator of your PaymentSystem and switch them (aka compose a new payment system) via property injection or, better, constructor injection.

http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/

To summarize, your PaymentSystem should be a "coordinator" of really simple collaborators.

I would use the first approach, Interface, Abstract class to implement general methods and concrete classes.

In my opinnion, abstract class is never a replacement for an interface, so I will discard the second approach.

Other solution could depend on your business, requirements,...

The only thing that could be wrong is that your classes could violate the single responsability, as it has to process payments and things like that and also create database conections. To me, database connection should be in another place.

Regards

In this scenario I would suggest you to go with Interface. Where only one method is involved. You give your own implementation for various Payment types (PS1, PS2, PS3...).

If you have a situation where you have more methods and variable which are going to be common for ProcessPayment then you can think of abstract class in which at least some methods behavior is not going to get changed. But remember you are losing class inheritance when you use Abstract class.

If only one method involved then go with Interface.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top