博客信息

设计模式七大原则之开闭原则(ocp原则)

发布时间:『 2020-03-06 08:27』  博客类别:23种设计模式  阅读(558)

  • 概念

    开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则; 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节; 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则

  • 使用前

    需求:计算不同形状的面积

    先完成计算三角形、长方形的面积的需求

    package com.javaxl.design.rules.ocp.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:35
    *
    * 抽象的图形
    */
    public class Shape {
      public double getResult(){
          if(this instanceof Triangle){
              return ((Triangle) this).getWidth()*((Triangle) this).getHeight()/2;
          }else if(this instanceof Rectangle){
              return ((Rectangle) this).getHeight()*((Rectangle) this).getWidth();
          }
          return 0;
      };
    }


    package com.javaxl.design.rules.ocp.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:38
    * 三角形
    */
    public class Triangle extends Shape{
      private double width;
      private double height;

      public Triangle(double width, double height) {
          this.width = width;
          this.height = height;
      }

      public double getWidth() {
          return width;
      }

      public double getHeight() {
          return height;
      }
    }


    package com.javaxl.design.rules.ocp.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:40
    * 长方形
    */
    public class Rectangle extends Shape {
      private double width;
      private double height;

      public Rectangle(double width, double height) {
          this.width = width;
          this.height = height;
      }

      public double getWidth() {
          return width;
      }

      public double getHeight() {
          return height;
      }
    }

    package com.javaxl.design.rules.ocp.before;


    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:41
    */
    public class Client {
      public static void main(String[] args) {
    //       计算三角形的面积
          Triangle triangle = new Triangle(3,5);
          System.out.println("计算三角形的面积:"+triangle.getResult());

    //       计算长方形的面积
          Rectangle rectangle = new Rectangle(3,5);
          System.out.println("计算长方形的面积:"+rectangle.getResult());
      }
    }

    需求发生变更:此时需要新增圆形的计算面积的方式

    变更的代码如下:

    package com.javaxl.design.rules.ocp.beforePlus;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 11:21
    */
    public class Circular extends Shape {
      private double r;

      public Circular(double r) {
          this.r = r;
      }

      public double getR() {
          return r;
      }
    }


    public class Shape {
      public double getResult(){
          if(this instanceof Triangle){
              return ((Triangle) this).getWidth()*((Triangle) this).getHeight()/2;
          }else if(this instanceof Rectangle){
              return ((Rectangle) this).getHeight()*((Rectangle) this).getWidth();
          }else if(this instanceof Circular){
              return ((Circular) this).getR()*((Circular) this).getR()*3.14;
          }
          return 0;
      };
    }


    public class Client {
      public static void main(String[] args) {
    //       计算三角形的面积
          Triangle triangle = new Triangle(3,5);
          System.out.println("计算三角形的面积:"+triangle.getResult());

    //       计算长方形的面积
          Rectangle rectangle = new Rectangle(3,5);
          System.out.println("计算长方形的面积:"+rectangle.getResult());

          //       计算圆形的面积
          Circular circular = new Circular(2);
          System.out.println("计算圆形的面积:"+circular.getResult());
      }
    }

  • 使用后

    实现三角形、长方形的面积计算

    package com.javaxl.design.rules.ocp.after;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:35
    *
    * 抽象的图形
    */
    public abstract class Shape {
      public abstract double getResult();
    }


    package com.javaxl.design.rules.ocp.after;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:40
    * 长方形
    */
    public class Rectangle extends Shape {
      private double width;
      private double height;

      public Rectangle(double width, double height) {
          this.width = width;
          this.height = height;
      }

      @Override
      public double getResult() {
          return this.height*this.width;
      }
    }


    package com.javaxl.design.rules.ocp.after;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:38
    * 三角形
    */
    public class Triangle extends Shape {
      private double width;
      private double height;

      public Triangle(double width, double height) {
          this.width = width;
          this.height = height;
      }

      @Override
      public double getResult() {

          return this.height*this.width/2;
      }
    }


    package com.javaxl.design.rules.ocp.after;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:41
    */
    public class Client {
      public static void main(String[] args) {
    //       计算三角形的面积
          Triangle triangle = new Triangle(3,5);
          System.out.println("计算三角形的面积:"+triangle.getResult());

    //       计算长方形的面积
          Rectangle rectangle = new Rectangle(3,5);
          System.out.println("计算长方形的面积:"+rectangle.getResult());
      }
    }

    需求发生变更:此时需要新增圆形的计算面积的方式

    变更的代码如下:

    package com.javaxl.design.rules.ocp.afterPlus;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 11:16
    */
    public class Circular extends Shape {
      private double r;
      @Override
      public double getResult() {
          return 3.14*r*r;
      }

      public Circular(double r) {
          this.r = r;
      }
    }

    package com.javaxl.design.rules.ocp.afterPlus;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-16 10:41
    */
    public class Client {
      public static void main(String[] args) {
    //       计算三角形的面积
          Triangle triangle = new Triangle(3,5);
          System.out.println("计算三角形的面积:"+triangle.getResult());

    //       计算长方形的面积
          Rectangle rectangle = new Rectangle(3,5);
          System.out.println("计算长方形的面积:"+rectangle.getResult());

    //       计算圆形的面积
          Circular circular = new Circular(2);
          System.out.println("计算圆形的面积:"+circular.getResult());
      }
    }

    从上面的可以看出

    如果不遵循开闭原则:shape作为主体的类,一旦发生需求的变更,shape需要做对应的修改;

    如果遵循了开闭原则,shape作为主体的类无需修改;只需要扩展其子类即可;

    这就是“对扩展开放,对修改关闭”的含义;


下面3个原则浅显易懂,没啥好说的,不单开章节

合成复用原则

尽量使用合成/聚合的方式,而不是使用继承


单一职责原则

  • 概念

    降低类的复杂度,一个类只负责一项职责 提高类的可读性,可维护性 降低变更引起的风险,对于服务端的代码尽量做到只新增不修改

上面计算图形面积的案例也体现了单一职责原则:

使用单一职责前:计算面积的逻辑全部耦合在shape类;

使用单一职责后:计算面积的逻辑交给各个子类去实现;


迪米特法则

  • 概念

    一个对象应该对其他对象保持最少的了解 类与类关系越密切,耦合度越大 陌生的类最好不要以局部变量的形式出现在类的内部

其实就是单一职责原则的另一体现形式,将功能封装再封装,不要将所有的功能冗余在一起;



over......


关键字:     设计模式  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有