Composite Reuse Principle or CRP

Use object composition rather than inheritance for reuse purposes. The principle of composite reuse is to encourage the use of combinations of objects in preference to inheritance.

The sample

public abstract class BankCard {

    public string UserName { get; set; }/ / user name
    public string Balance { get; set; }/ / the balance

    public abstract void Transfer(BankCard card, double amount);/ / transfer
    public abstract void Withdraw(double amount);/ / withdrawals
    public abstract void Deposit(double amount);/ / deposit
    public abstract void Overdraft(double amount);/ / overdraft

    public virtual void ShowMessage() {
        Console.WriteLine($"THis is {this.ToString()}!"); }}Copy the code
// CCB ordinary bank card
public class CCBCard : BankCard {

    public override void Deposit(double amount) {
        Console.WriteLine("Deposit");
    }

    public override void Overdraft(double amount) {
        throw new NotImplementedException();
    }

    public override void Transfer(BankCard card, double amount) {
        Console.WriteLine("Transfer");
    }

    public override void Withdraw(double amount) {
        Console.WriteLine("Withdraw"); }}Copy the code

More than most of this design will function encapsulation in BankCard abstract base classes, ordinary bank CARDS of CCB CCBCard class inherits the base class, but on the CCB bank card clearly didn’t overdraw function, led to the no overdraw function of bank CARDS to add a default overdraw implementation, this is obviously unreasonable. In addition, if you change any function in the base class, all classes that inherit from BankCard may have to be overwritten, which clearly does not meet the open close principle. The transfer method uses BankCard type parameters, which obviously does not comply with Richter’s substitution principle. The following is a solution for your reference:

public abstract class BankCardBase {

    public string UserName { get; set; }/ / user name
    public string Balance { get; set; }/ / the balance

    public virtual void ShowMessage() {
        Console.WriteLine($"THis is {this.ToString()}!"); }}Copy the code

A separate abstract base class, BankCardBase, provides user names, balances, and other basic functions.

public interface ICard {

    void Transfer(BankCardBase card, double amount);/ / transfer
    void Withdraw(double amount);/ / withdrawals
    void Deposit(double amount);/ / deposit

}

public interface ICreditCard : ICard {

    void Overdraft(double amount);/ / overdraft

}
Copy the code

Abstract ICard bank card basic operation interface, including transfer, withdrawal and deposit. ICreditCard Credit card interface, considering that credit cards must contain ordinary bank card functions, so inherit the ICard interface.

// CCB ordinary bank card
public class CCBCard : BankCardBase.ICard {

    public void Deposit(double amount) {
        Console.WriteLine("Deposit");
    }

    public void Transfer(BankCardBase card, double amount) {
        Console.WriteLine("Transfer");
    }

    public void Withdraw(double amount) {
        Console.WriteLine("Withdraw"); }}Copy the code

CCB ordinary bank card entity class inherits from the abstract base class of bank card and realizes ICard bank card interface.

// Construction Bank Dragon Credit Card
public class CCBDragonCard : BankCardBase.ICreditCard {

    public void Deposit(double amount) {
        Console.WriteLine("Deposit");
    }

    public void Overdraft(double amount) {
        Console.WriteLine("Overdraft");
    }

    public void Transfer(BankCardBase card, double amount) {
        Console.WriteLine("Transfer");
    }

    public void Withdraw(double amount) {
        Console.WriteLine("Withdraw"); }}Copy the code

Construction Bank Dragon card entity class, inherit from the abstract base class of bank card and achieve ICreditCard credit card interface.

After the above code transformation, the base class BankCardBase only contains the basic functions of the bank card, the bank card interface ICard only contains the business operations related to the bank card, and the credit card interface ICreditCard only contains the business operations related to the credit card, which has no influence on each other. Modifying the functions of ordinary bank cards or credit cards will not affect the business logic of other types of bank cards, in line with the open and closed principle.

The transfer method uses the base class parameter BankCardBase and adopts the feature of “replacing the parent class object with the subclass object at runtime”, which makes the code highly scalable and conforms to the Richter substitution principle. In this example, we first use the combination of the various classes and interfaces instead of a single base class inheritance relationships before to make the function of the ordinary bank CARDS and credit CARDS, make the design more efficient, high maintainability, and these classes and interfaces can also be infinite reasonable reuse, this principle is synthesis of reuse.