📜  Java的开放封闭设计原则

📅  最后修改于: 2022-05-13 01:54:50.335000             🧑  作者: Mango

Java的开放封闭设计原则

开放封闭设计原则是软件开发领域最重要的设计原则之一。它是一组 5 项设计原则的一部分,通常以首字母缩写词“SOLID”为人所知

S - Single Responsibility Principle
O - Open Closed Principle
L - Liskov Substitution Principle
I - Interface Segregation
D - Dependency Inversion

按照 Robert C Martin 的说法,该原则指出软件实体(类、模块、函数)应该对扩展开放,对修改关闭。这意味着一个类应该足够灵活以适应业务需求变化时的变化而不破坏现有代码。因此,依赖类不必更改。这最大限度地减少了测试工作,我们只需要关注新的代码更改。

方法:

基本上有两种实现接口的主要方法:

  1. 使用继承
  2. 使用接口和抽象方法

方法一:使用继承



遵循这一原则的一种方法是使用继承。我们有一个对修改关闭的超类,它是基线的,并且是 jar 文件的一部分。任何想要修改超类行为的人都可以将其子类化,扩展它并添加新功能。这可确保超类行为保持不变,并且超类的客户端不必更改代码。然而继承引入了超和子之间的紧耦合-类实现。假设超类存在缺陷或超类版本升级引入代码更改,那么子类也需要修改。

示例:假设 Jane 开了一家面包店,并决定根据她的销售额保持简单和规模。

Java
// Java Program to Illustrate Open Closed Design Principle
// Using Inheritance
 
// Importing input output classes
import java.io.*;
 
// Class 1
// Helper class acting as parent class
class Cake {
 
    // Member variable of Cake class
    private int size;
    private float weight;
 
    // Constructor for cake which sets
    // only size and dimension of cake
    public Cake(int size, float weight)
    {
        // This keyword refers to current object itself
        this.size = size;
        this.weight = weight;
    }
 
    // Method
    // To bake the cake
    public void bake()
    {
        // Display message only
        System.out.println(
            "Baking cake with base as vanilla");
 
        // Print and display the size and weight of the cake
        System.out.println("Size is " + this.size
                           + " inches and weight is "
                           + this.weight + " kg.");
    }
}
 
// Class 2
// Helper class(Child class) of class 1
class PineappleCake extends Cake {
 
    // Member variables
    private int size;
    private float weight;
 
    // Constructor
    // To set the dimension of the pineapple cake
    public PineappleCake(int size, float weight)
    {
        // Super keyword refers to parent class instance
        super(size, weight);
 
        // This keyword refer to current instance
        this.size = size;
        this.weight = weight;
    }
 
    // Method 1
    // To decorate the pineapple cake
    private void decorateCake()
    {
        // Display messages only
        System.out.println("Decorating cake");
        System.out.println("Adding pineapple pieces");
    }
 
    // Method 2
    // To add cream to pineapple cake
    private void addCream()
    {
        // Print statement
        System.out.println("Adding white cream");
    }
 
    // Method 3
    // To bake a pineapple cake
    public void bake()
    {
 
        super.bake();
 
        // Calling the above two methods created
        addCream();
        decorateCake();
 
        // Print the dimension of the pineapple cake
        System.out.println("Pineapple cake - " + this.size
                           + " inches is ready");
    }
}
 
// Class 3
// Helper class(Child class) of class 1
class ChocolateCake extends Cake {
 
    // member variables
    private int size;
    private float weight;
 
    // Constructor
    // Setting the size nd weight of the chocolate cake
    public ChocolateCake(int size, float weight)
    {
 
        super(size, weight);
 
        this.size = size;
        this.weight = weight;
    }
 
    // Method 1
    // To decorate a chocolate cake
    private void decorateCake()
    {
 
        // Display commands only
        System.out.println("Decorating cake");
        System.out.println("Adding chocolate chips");
    }
 
    // Method 2
    // To add cream to chocolate cake
    private void addCream()
    {
 
        // Print statement
        System.out.println("Adding chocolate cream");
    }
 
    // Method 3
    // to bake a chocolate cake
    public void bake()
    {
 
        super.bake();
 
        // Calling the above two methods created
        addCream();
        decorateCake();
 
        // Print and display the dimension of chocolate cake
        System.out.println("Chocolate cake - " + this.size
                           + " inches is ready");
    }
}
 
// Class 4
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an instance of pineapple cake
        // int the main() method
 
        // Custom dimension are passed as in arguments
        PineappleCake pineappleCake
            = new PineappleCake(7, 3);
 
        // Calling the bake() method of PineappleCake class
        // to bake the cake
        pineappleCake.bake();
 
        // Similarly, creating an instance of chocolate cake
        // in the main() method
        ChocolateCake chocolateCake
            = new ChocolateCake(5, 2);
 
        // Calling the bake() method of ChocolateCake class
        // to bake the cake
        chocolateCake.bake();
    }
}


Java
// Java Program to Illustrate Open Closed Design Principle
// Using Inheritance
// Alonside adding Parameter - Flavor to cakes
 
// Importing input output classes
import java.io.*;
 
// Class 1
// Helper class
// Acting as parent class
class Cake {
 
    // Member variables
    private int size;
    private float weight;
 
    // This is new declared variable to
    // hold the flavour for the cake
    private String flavor;
 
    // Constructor
    // To set the dimensions for the cake
    public Cake(int size, float weight, String flavor)
    {
 
        this.size = size;
        this.weight = weight;
 
        // Here this keyword sets the
        // current instance flavour to th cake
        this.flavor = flavor;
    }
 
    // Method
    // To bake the cake
    public void bake()
    {
 
        // Printing the flavour of the desired cake
        System.out.println("Baking cake with base as "
                           + this.flavor);
 
        // Printing the size and weight of the same cake
        System.out.println("Size is " + this.size
                           + " inches and weight is "
                           + this.weight + " kg.");
    }
}
 
// Class 2
// Helper class
class PineappleCake extends Cake {
 
    // Member variables for the pineapple cake
    private int size;
    private float weight;
    private String flavor;
 
    // Constructor
    // Updated as per requirements as sales rise flavour is
    // added, so do setting  the flavour
    public PineappleCake(int size, float weight,
                         String flavor)
    {
 
        // Super keyword refers to parent class
        super(size, weight, flavor);
 
        // This keyword refers to current instance
        this.size = size;
        this.weight = weight;
        this.flavor = flavor;
    }
 
    // Method 1
    // To decorate the cake
    private void decorateCake()
    {
 
        // Display commands only
        System.out.println("Decorating cake");
        System.out.println("Adding pineapple pieces");
    }
 
    // Method 2
    // To add cream to the flavored pineapple cake
    private void addCream()
    {
 
        System.out.println("Adding white cream");
    }
    // Method 3
    // To bake a flavored pineapple cake
    public void bake()
    {
 
        // Super keyword calls the Cake class bake() method
        super.bake();
 
        // Calling the above two methods
        addCream();
        decorateCake();
 
        // Printing the dimensions of
        // flavoured pineapple cake
        System.out.println("Pineapple cake - " + this.size
                           + " inches is ready");
    }
}
 
// Similarly setting the same for
// the 'flavoured' chocolate cake
 
// Class 3
// Helper class (Base class of parent class)
class ChocolateCake extends Cake {
 
    private int size;
    private float weight;
    private String flavor;
 
    // Updated constructor
    public ChocolateCake(int size, float weight,
                         String flavor)
    {
 
        super(size, weight, flavor);
 
        this.size = size;
        this.weight = weight;
        this.flavor = flavor;
    }
 
    // Method 1
    // To decorate the flavored chocolate cake
    private void decorateCake()
    {
 
        System.out.println("Decorating cake");
        System.out.println("Adding chocolate chips");
    }
 
    // Method 2
    // To add cream to the flavoured chocolate cake
    private void addCream()
    {
 
        System.out.println("Adding chocolate cream");
    }
 
    // Method 3
    // To bake a flavoured chocolate cake
    public void bake()
    {
 
        super.bake();
 
        addCream();
        decorateCake();
 
        System.out.println("Chocolate cake - " + this.size
                           + " inches is ready");
    }
}
 
// Class 4
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a pineapple cake in the main() method
        // Custom dimensions are passed as in arguments
        PineappleCake pineappleCake
            = new PineappleCake(7, 3, "vanilla");
 
        // Calling the bake() method of the PineappleCake
        // Class to bake the pinelapple cake
        pineappleCake.bake();
 
        // Similarly repeating the same with the chocolate
        // cake
 
        // Creating a chocolate cake by creating an object
        // of ChocolateCake class in the main method
        ChocolateCake chocolateCake
            = new ChocolateCake(5, 2, "chocolate");
 
        // Calling the bake() method of the ChocolateCake
        // Class to bake the chocolate cake
        chocolateCake.bake();
    }
}


Java
// Java Program to Illustrate Open Closed Design Principle
// Using Interfaces and abstract methods
 
// Importing input output classes
import java.io.*;
 
// Interface
interface Cake {
 
    // Abstract methods of this interface
    public void bake();
    public void addCream();
    public void decorateCake();
}
 
// Class 1
// Helper class implementing above interface
class ChocolateCake implements Cake {
 
    // Member variables of this class
    private String base;
    private int size;
    private float weight;
 
    // Constructor
    // To set the dimension to chocolate cake
    public ChocolateCake(String base, int size,
                         float weight)
    {
 
        this.base = base;
        this.size = size;
        this.weight = weight;
    }
 
    // @Override
    // Method 1
    // To add cream to chocolate cake
    public void addCream()
    {
        System.out.println("Adding chocolate cream");
    }
 
    // @Override
    // Method 3
    // To bake the chocolate cake
    public void bake()
    {
 
        // Printing the base of the cake
        System.out.println("Baking cake with base as "
                           + this.base);
 
        // Calling the methods
        addCream();
        decorateCake();
 
        // Printing the dimension of the chocolate cake
        System.out.println("Chocolate cake with "
                           + this.size
                           + " inches and weight:"
                           + this.weight + " kg is ready");
    }
 
    // @Override
    // Method 2
    // To decorate the chocolate cake
    public void decorateCake()
    {
 
        // Print statement only
        System.out.println(
            "Cake decoration with choco chips");
    }
}
 
// Repeating the same for pineapple cake
// as we did above for chocolate cake
 
// Class 2
// Helper class implementing the 'Cake' interface
class PineappleCake implements Cake {
 
    // Member variable
    private String base;
    private int size;
    private float weight;
 
    // Constructor
    // To set the dimension to pineapple cake
    public PineappleCake(String base, int size,
                         float weight)
    {
 
        this.base = base;
        this.size = size;
        this.weight = weight;
    }
 
    // @Override
    // Method 1
    // To add cream to pineapple cake
    public void addCream()
    {
 
        System.out.println("Adding white  cream");
    }
 
    // @Override
    // Method 2
    // To decorate the pineapple cake
    public void decorateCake()
    {
 
        System.out.println(
            "Cake decoration with pineapple pieces");
    }
}
 
// @Override
// Method 3
// To bake the pineapple cake
public void bake()
{
 
    System.out.println("Baking cake with base as "
                       + this.base);
    addCream();
    decorateCake();
 
    System.out.println("Pineapple cake with " + this.size
                       + " inches and weight:" + this.weight
                       + " kg is ready");
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Making cakes using interface and abstract methods
        // by creating objects here in main() method
 
        // Custom dimensional to both cakes are passed
        // as in arguments
 
        // 1. Pineapple cake
        Cake pineappleCake
            = new PineappleCake("vanilla", 7, 3);
 
        // Calling the bake() to
        // bake pineapple cake
        pineappleCake.bake();
 
        // 2. Chocolate cake
        Cake chocolateCake
            = new ChocolateCake("chocolate", 5, 2);
 
        // Calling the bake() to
        // bake chocolate cake
        chocolateCake.bake();
    }
}


输出
Baking cake with base as vanilla
Size is 7 inches and weight is 3.0 kg.
Adding white cream
Decorating cake
Adding pineapple pieces
Pineapple cake - 7 inches is ready
Baking cake with base as vanilla
Size is 5 inches and weight is 2.0 kg.
Adding chocolate cream
Decorating cake
Adding chocolate chips
Chocolate cake - 5 inches is ready

输出说明: 'Cake' 类是基类。每个蛋糕的底料都有香草味。我们有两个专业,即菠萝和巧克力口味的蛋糕。这些类使用 Cake 的 bake() 方法制作香草蛋糕,然后添加奶油并根据口味装饰蛋糕。

例子:

Java

// Java Program to Illustrate Open Closed Design Principle
// Using Inheritance
// Alonside adding Parameter - Flavor to cakes
 
// Importing input output classes
import java.io.*;
 
// Class 1
// Helper class
// Acting as parent class
class Cake {
 
    // Member variables
    private int size;
    private float weight;
 
    // This is new declared variable to
    // hold the flavour for the cake
    private String flavor;
 
    // Constructor
    // To set the dimensions for the cake
    public Cake(int size, float weight, String flavor)
    {
 
        this.size = size;
        this.weight = weight;
 
        // Here this keyword sets the
        // current instance flavour to th cake
        this.flavor = flavor;
    }
 
    // Method
    // To bake the cake
    public void bake()
    {
 
        // Printing the flavour of the desired cake
        System.out.println("Baking cake with base as "
                           + this.flavor);
 
        // Printing the size and weight of the same cake
        System.out.println("Size is " + this.size
                           + " inches and weight is "
                           + this.weight + " kg.");
    }
}
 
// Class 2
// Helper class
class PineappleCake extends Cake {
 
    // Member variables for the pineapple cake
    private int size;
    private float weight;
    private String flavor;
 
    // Constructor
    // Updated as per requirements as sales rise flavour is
    // added, so do setting  the flavour
    public PineappleCake(int size, float weight,
                         String flavor)
    {
 
        // Super keyword refers to parent class
        super(size, weight, flavor);
 
        // This keyword refers to current instance
        this.size = size;
        this.weight = weight;
        this.flavor = flavor;
    }
 
    // Method 1
    // To decorate the cake
    private void decorateCake()
    {
 
        // Display commands only
        System.out.println("Decorating cake");
        System.out.println("Adding pineapple pieces");
    }
 
    // Method 2
    // To add cream to the flavored pineapple cake
    private void addCream()
    {
 
        System.out.println("Adding white cream");
    }
    // Method 3
    // To bake a flavored pineapple cake
    public void bake()
    {
 
        // Super keyword calls the Cake class bake() method
        super.bake();
 
        // Calling the above two methods
        addCream();
        decorateCake();
 
        // Printing the dimensions of
        // flavoured pineapple cake
        System.out.println("Pineapple cake - " + this.size
                           + " inches is ready");
    }
}
 
// Similarly setting the same for
// the 'flavoured' chocolate cake
 
// Class 3
// Helper class (Base class of parent class)
class ChocolateCake extends Cake {
 
    private int size;
    private float weight;
    private String flavor;
 
    // Updated constructor
    public ChocolateCake(int size, float weight,
                         String flavor)
    {
 
        super(size, weight, flavor);
 
        this.size = size;
        this.weight = weight;
        this.flavor = flavor;
    }
 
    // Method 1
    // To decorate the flavored chocolate cake
    private void decorateCake()
    {
 
        System.out.println("Decorating cake");
        System.out.println("Adding chocolate chips");
    }
 
    // Method 2
    // To add cream to the flavoured chocolate cake
    private void addCream()
    {
 
        System.out.println("Adding chocolate cream");
    }
 
    // Method 3
    // To bake a flavoured chocolate cake
    public void bake()
    {
 
        super.bake();
 
        addCream();
        decorateCake();
 
        System.out.println("Chocolate cake - " + this.size
                           + " inches is ready");
    }
}
 
// Class 4
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating a pineapple cake in the main() method
        // Custom dimensions are passed as in arguments
        PineappleCake pineappleCake
            = new PineappleCake(7, 3, "vanilla");
 
        // Calling the bake() method of the PineappleCake
        // Class to bake the pinelapple cake
        pineappleCake.bake();
 
        // Similarly repeating the same with the chocolate
        // cake
 
        // Creating a chocolate cake by creating an object
        // of ChocolateCake class in the main method
        ChocolateCake chocolateCake
            = new ChocolateCake(5, 2, "chocolate");
 
        // Calling the bake() method of the ChocolateCake
        // Class to bake the chocolate cake
        chocolateCake.bake();
    }
}
输出
Baking cake with base as vanilla
Size is 7 inches and weight is 3.0 kg.
Adding white cream
Decorating cake
Adding pineapple pieces
Pineapple cake - 7 inches is ready
Baking cake with base as chocolate
Size is 5 inches and weight is 2.0 kg.
Adding chocolate cream
Decorating cake
Adding chocolate chips
Chocolate cake - 5 inches is ready

方法二:使用接口和抽象方法

  • 我们用一组方法定义了一个接口。
  • 接口定义了一个契约,并且它是关闭的以进行修改。根据业务需求,我们可以有不同的接口实现。这确保了类之间的松散耦合。实现类彼此独立。

实现:为了更好的理解,我们重构了前面的例子。我们有一个蛋糕界面,它有不同的烘焙蛋糕步骤。 Pineapple 和 Chocolate Cake 类实现了这个接口,定义了它们自己的面包基料、奶油和装饰。

例子:

Java

// Java Program to Illustrate Open Closed Design Principle
// Using Interfaces and abstract methods
 
// Importing input output classes
import java.io.*;
 
// Interface
interface Cake {
 
    // Abstract methods of this interface
    public void bake();
    public void addCream();
    public void decorateCake();
}
 
// Class 1
// Helper class implementing above interface
class ChocolateCake implements Cake {
 
    // Member variables of this class
    private String base;
    private int size;
    private float weight;
 
    // Constructor
    // To set the dimension to chocolate cake
    public ChocolateCake(String base, int size,
                         float weight)
    {
 
        this.base = base;
        this.size = size;
        this.weight = weight;
    }
 
    // @Override
    // Method 1
    // To add cream to chocolate cake
    public void addCream()
    {
        System.out.println("Adding chocolate cream");
    }
 
    // @Override
    // Method 3
    // To bake the chocolate cake
    public void bake()
    {
 
        // Printing the base of the cake
        System.out.println("Baking cake with base as "
                           + this.base);
 
        // Calling the methods
        addCream();
        decorateCake();
 
        // Printing the dimension of the chocolate cake
        System.out.println("Chocolate cake with "
                           + this.size
                           + " inches and weight:"
                           + this.weight + " kg is ready");
    }
 
    // @Override
    // Method 2
    // To decorate the chocolate cake
    public void decorateCake()
    {
 
        // Print statement only
        System.out.println(
            "Cake decoration with choco chips");
    }
}
 
// Repeating the same for pineapple cake
// as we did above for chocolate cake
 
// Class 2
// Helper class implementing the 'Cake' interface
class PineappleCake implements Cake {
 
    // Member variable
    private String base;
    private int size;
    private float weight;
 
    // Constructor
    // To set the dimension to pineapple cake
    public PineappleCake(String base, int size,
                         float weight)
    {
 
        this.base = base;
        this.size = size;
        this.weight = weight;
    }
 
    // @Override
    // Method 1
    // To add cream to pineapple cake
    public void addCream()
    {
 
        System.out.println("Adding white  cream");
    }
 
    // @Override
    // Method 2
    // To decorate the pineapple cake
    public void decorateCake()
    {
 
        System.out.println(
            "Cake decoration with pineapple pieces");
    }
}
 
// @Override
// Method 3
// To bake the pineapple cake
public void bake()
{
 
    System.out.println("Baking cake with base as "
                       + this.base);
    addCream();
    decorateCake();
 
    System.out.println("Pineapple cake with " + this.size
                       + " inches and weight:" + this.weight
                       + " kg is ready");
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Making cakes using interface and abstract methods
        // by creating objects here in main() method
 
        // Custom dimensional to both cakes are passed
        // as in arguments
 
        // 1. Pineapple cake
        Cake pineappleCake
            = new PineappleCake("vanilla", 7, 3);
 
        // Calling the bake() to
        // bake pineapple cake
        pineappleCake.bake();
 
        // 2. Chocolate cake
        Cake chocolateCake
            = new ChocolateCake("chocolate", 5, 2);
 
        // Calling the bake() to
        // bake chocolate cake
        chocolateCake.bake();
    }
}
输出
Baking cake with base as vanilla
Adding white  cream
Cake decoration with pineapple pieces
Pineapple cake with 7 inches and weight:3.0 kg is ready
Baking cake with base as chocolate
Adding chocolate cream
Cake decoration with choco chips
Chocolate cake with 5 inches and weight:2.0 kg is ready

输出说明:接口提供抽象层,促进松耦合。未来,简可以推出其他口味的蛋糕,有不同的底料、奶油和装饰。