设计模式之开闭原则

开闭原则

一、概念

在面向对象编程领域中,开闭原则规定软件中的类、对象、模块和函数对扩展应该是开放的,但是对于修改来说是封闭的。

这就意味着应该用抽象定义结构,用具体实现扩展细节,以此确保软件系统开发和维护过程中的可靠性。

开闭原则的核心思想可以理解成为面向抽象编程。

二、案例

对于外部的调用方来说,只需要能够体现出来面向抽象编程,定义出接口并实现其方法。

即使不修改原有方法体,只通过继承方式进行扩展,都可以体现出开闭原则。

比如说:计算出来三种形状的面积,如长方形、三角形、原型的面积,他们在类中已经按照固有的模式来进行实现,其中圆形面积公式π=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);
    }
}

这样子来进行操作也不失为一个好的方法。

四、核心思想

对修改关闭,对扩展开放!面向抽象编程

posted @ 2022-04-06 00:28  雩娄的木子  阅读(74)  评论(0编辑  收藏  举报