在面向对象编程领域中,开闭原则规定软件中的类、对象、模块和函数对扩展应该是开放的,但是对于修改来说是封闭的。
这就意味着应该用抽象定义结构,用具体实现扩展细节,以此确保软件系统开发和维护过程中的可靠性。
开闭原则的核心思想可以理解成为面向抽象编程。
对于外部的调用方来说,只需要能够体现出来面向抽象编程,定义出接口并实现其方法。
即使不修改原有方法体,只通过继承方式进行扩展,都可以体现出开闭原则。
比如说:计算出来三种形状的面积,如长方形、三角形、原型的面积,他们在类中已经按照固有的模式来进行实现,其中圆形面积公式π=3.14。但是由于后续π的精度对于某些场景来说是不足的,还需要来进行扩展,接下来通过模拟这个场景来体现出开闭原则。
代码如下所示:
/** * @Description 但是对于三个类来说,都是计算面积的,但是针对于不同的具体的类来说,有不同的实现方式 * 那么这样子来进行操作的话,有违单一职责原则;所以这里不能够这样子来进行使用! * @Author liguang * @Date 2022/04/06/00:02 */ public interface ICalculateionArea { /** *计算长方形的面积 * @param x 长方形的唱 * @param y 长方形的款 * @return */ double rectangle(double x,double y); /** * 计算三角形的面积 s = 根号p*(p-a)*(p-b)*(p-c),其中p=(a+b+c)/2 * @param x 一条边 * @param y 一条边 * @param z 一条边 * @return */ double triandle(double x ,double y,double z); /** * 计算圆形面积 * @param r 圆的半径 * @return */ double circular(double r); }
查看一下对应的实现类:
public class CalculateionArea implements ICalculateionArea { private final double PAI = 3.14D; @Override public double rectangle(double x, double y) { return x*y; } @Override public double triandle(double x, double y, double z) { double p = (x+y+z)/2; return Math.sqrt(p*(p-x)*(p-y)*(p-z)) ; } @Override public double circular(double r) { return PAI*r*r; } }
编写对应的测试类:
public class Test { public static void main(String[] args) { CalculateionArea calculateionArea = new CalculateionArea(); double triandleArea = calculateionArea.triandle(3, 4, 5); System.out.println("三角形的面积是:"+triandleArea); double circularArea = calculateionArea.circular(3); System.out.println("圆形的面积是:"+circularArea); double rectangleArea = calculateionArea.rectangle(1, 2); System.out.println("长方形的面积是:"+rectangleArea); } }
但是现在有了新的业务需要单独的进行扩展下,需要的π的精度需要更高一点,但是如果修改了原来的值,肯定是违反了开闭原则的。会对原来的业务功能造成对应的错误(隐藏的),所以为了现有的实现类不对原来的实现类造成影响,那么选择一个新的类来对其进行继承,以继承的方式来进行选择实现新的功能。
对应的格式如下所示:
/** * @Description 想要在此基础之上来进行修改操作 * @Author liguang * @Date 2022/04/06/00:15 */ public class CalculateionAreaExt extends CalculateionArea{ private final double PAI = 3.1495926D; @Override public double circular(double r) { return PAI*r*r; } }
那么这样子也就意味着可以对原来的功能没有影响,而且这里也可以来进行面向抽象编程,和原来的功能是一样的。
编写对应的测试类,如下所示:
public class TestExt { public static void main(String[] args) { ICalculateionArea calculateionArea = new CalculateionArea(); double triandleArea = calculateionArea.triandle(3, 4, 5); System.out.println("三角形的面积是:"+triandleArea); double circularArea = calculateionArea.circular(3); System.out.println("圆形的面积是:"+circularArea); double rectangleArea = calculateionArea.rectangle(1, 2); System.out.println("长方形的面积是:"+rectangleArea); System.out.println("---------------------------"); System.out.println("-----------------------------------"); System.out.println("-----------------------------------"); System.out.println("-----------------------------------"); System.out.println("-----------------------------------"); ICalculateionArea calculateionAreaExt = new CalculateionAreaExt(); double circularAreaExt = calculateionAreaExt.circular(3); System.out.println("圆形的面积是:"+circularAreaExt); } }
这样子来进行操作也不失为一个好的方法。
对修改关闭,对扩展开放!面向抽象编程