Search code examples
c#class-design

The class design - interface or abstract class?


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...");
    }
}

Solution

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