likes
comments
collection
share

所有的原则都是基于开闭原则,直到现在我才理解原则的尽头是开闭

作者站长头像
站长
· 阅读数 13

前言

  • 设计模式七大原则我们已经梳理了四种了。包括【单一原则】【接口隔离原则】【依赖倒转原则】【里氏替换原则】。当然前两种还未发表。后续补上。今天我们来看看什么叫开闭原则。相信不少学习过设计模式的小伙伴应该对开闭原则映像最为深刻吧。因为他是最重要也是最为明显的衡量标准的原则

基本介绍

  • 一、开闭原则是设计中最为基础,最为重要的设计原则
  • 二、一个类或者功能如果想要实现开闭原则就需要对内可以扩展,对外无需修改。用Java语言来说就是我们常常需要用抽象来构建整体思路,用具体的实现类或者子类来填充我们的细节

所有的原则都是基于开闭原则,直到现在我才理解原则的尽头是开闭

  • 开闭原则如何检验,只需要看是否符合上面的功能就可以了。我们一个类肯定会被别人使用。当我们对这个类功能进行升级优化这个对于这个类来说就是扩展。但是扩展的同时不能让已使用的功能有所改动。比如A类有一个方法fun1(int a );当我们扩展后就必须fun1(int a)且兼容原来的功能。
  • 三、当类需要变化时,尽量通过扩展的方式而不是修改的方式。一方面叠加修改会造成代码的冗长。另一方面我们无法保证修改的代码绝对没有问题。这样就造成加功能导致旧的功能出现问题
  • 四、其他的原则都基于开闭原则

场景开发

  • 现在我们有一个功能需要进行画图开发。根据用户选择的笔的类型进行画不同的形状。让我们看看我们的第一版代码吧
 public class OpenClose {
     public static void main(String[] args) {
         GraphicEditor editor = new GraphicEditor();
         Shape rectangle = new Rectangle();
         Shape circle = new Circle();
         editor.drawShape(rectangle);
         editor.drawShape(circle);
     }
 }
 ​
 class GraphicEditor{
     public void drawShape(Shape shape) {
         if (shape.type == 1) {
             System.out.println("圆形");
         } else {
             System.out.println("矩形");
         }
     }
 }
 class Shape{
     int type;
 }
 ​
 class Rectangle extends Shape {
     Rectangle(){
         this.type = 1;
     }
 }
 ​
 class Circle extends Shape {
     Circle(){
         this.type = 2;
     }
 }
  • 相信不少小伙伴都不会像上面进行分类开发。估计很大一部分人就是入参一个字符串。然后drawShape进行判断。能够将类型进行抽象化为形状的估计很少。但是即使我们进行抽象化了也不难发现上面的代码很难进行扩展。
  • 如果现在我们需要新增一个画三角形的笔。那么势必我们需要对drawShape进行修改。这就破坏了我们扩展性。上面我们提到新增功能是尽量是扩展而不是修改
  • 可想而知当我们新增一种形状的时候我们除了我们继承形状新增功能,我们还需要将GraphicEditor的逻辑进行改动。这个在某种程度上理解成客户端。这就造成了我们客户端的代码修改。而且是对核心逻辑直接修改。这样是很危险的。

升级

 public class OpenClose {
     public static void main(String[] args) {
         GraphicEditor editor = new GraphicEditor();
         Shape rectangle = new Rectangle();
         Shape circle = new Circle();
         editor.drawShape(rectangle);
         editor.drawShape(circle);
     }
 }
 ​
 class GraphicEditor{
     public void drawShape(Shape shape) {
         shape.draw();
     }
 }
 abstract class Shape{
     abstract public void draw();
 }
 ​
 class Rectangle extends Shape {
 ​
 ​
     @Override
     public void draw() {
         System.out.println("画矩形");
     }
 }
 ​
 class Circle extends Shape {
 ​
     @Override
     public void draw() {
         System.out.println("画圆形");
     }
 }
  • 之前我们的shape充当的是一种类型的功能。而改进之后shape充当的是执行的角色。每一种形状该画什么样的形状有子类自己决定。父类只需要定义出该有的功能的雏形。这样定义的好处是绘制的功能不需要客户端自己实现了。他们将绘制的功能解放出来后就轻松了。客户端拿到什么图形执行调用该图形的绘制功能就行了。
  • 这个时候我们需要开发新的图形叫做棱形。那么我们开发只需要新增一个类继承Shape并实现绘制棱形的功能。整个过程对于使用方即客户端来说并不需要对代码进行任何改动。

总结

  • 想要实现开闭原则就得依赖抽象。因为我们之前说了抽象负责整体框架设计,而子类或者实现类是负责细节处理的。这个设计正好就是开闭的一个运用。