一、基本介绍
(1)开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
(2)一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
(3)当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
(4)编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
二、应用实例
设计一个画图形的功能,类图如下:
说明:GraphicEditor是一个用于画图形的类,其中三个方法分别代表绘制图形drawShape,绘制矩形drawRectangle,绘制圆形drawCircle,Rectangle和Circle都继承自Shape类,drawShape根据传入shape对象的m_type来判断具体是绘制什么图形
代码实现:
1 public class OpenClosePrinciple { 2 public static void main(String[] args) { 3 GraphicEditor graphicEditor = new GraphicEditor(); 4 graphicEditor.drawShape(new Rectangle()); 5 graphicEditor.drawShape(new Circle()); 6 } 7 } 8 9 //用于绘图的类 10 class GraphicEditor { 11 //接收Shape对象,根据m_type来绘制不同的图形 12 public void drawShape(Shape shape) { 13 if (shape.m_type == 1) { 14 drawRectangle(shape); 15 } else if (shape.m_type == 2) { 16 drawCircle(shape); 17 } 18 } 19 20 public void drawRectangle(Shape rectangle) { 21 System.out.println("绘制矩形"); 22 } 23 24 public void drawCircle(Shape circle) { 25 System.out.println("绘制圆形"); 26 } 27 } 28 29 //基类Shape 30 class Shape { 31 int m_type; 32 } 33 34 class Rectangle extends Shape { 35 public Rectangle() { 36 super.m_type = 1; 37 } 38 } 39 40 class Circle extends Shape { 41 public Circle() { 42 super.m_type = 2; 43 } 44 }
运行结果:
分析:
(1)优点是比较好理解,简单易操作。
(2)缺点是违反了设计模式的开闭原则,即对扩展开放(提供方),对修改关闭(使用方)。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
(3)比如我们这时要新增加一个图形种类三角形,我们需要做如下修改,修改的地方较多
新需求:增加绘制三角形功能
说明:首先我们要新增一个Triangle类继承Shape,并且将其m_type置为3,在GraphicEditor中新增一个drawTriangle方法用于绘制三角形
代码实现:
1 public class OpenClosePrinciple { 2 public static void main(String[] args) { 3 GraphicEditor graphicEditor = new GraphicEditor(); 4 graphicEditor.drawShape(new Rectangle()); 5 graphicEditor.drawShape(new Circle()); 6 graphicEditor.drawShape(new Triangle()); 7 } 8 } 9 10 //用于绘图的类 11 class GraphicEditor { 12 //接收Shape对象,根据m_type来绘制不同的图形 13 public void drawShape(Shape shape) { 14 if (shape.m_type == 1) { 15 drawRectangle(shape); 16 } else if (shape.m_type == 2) { 17 drawCircle(shape); 18 } else if (shape.m_type == 3) { 19 drawTriangle(shape); 20 } 21 } 22 23 public void drawRectangle(Shape rectangle) { 24 System.out.println("绘制矩形"); 25 } 26 27 public void drawCircle(Shape circle) { 28 System.out.println("绘制圆形"); 29 } 30 31 public void drawTriangle(Shape triangle) { 32 System.out.println("绘制三角形"); 33 } 34 } 35 36 //基类Shape 37 class Shape { 38 int m_type; 39 } 40 41 class Rectangle extends Shape { 42 public Rectangle() { 43 super.m_type = 1; 44 } 45 } 46 47 class Circle extends Shape { 48 public Circle() { 49 super.m_type = 2; 50 } 51 } 52 53 class Triangle extends Shape { 54 public Triangle() { 55 super.m_type = 3; 56 } 57 }
运行结果:
分析:虽然我们将功能实现了,但是每次增加新的图形都要这样操作未免太过麻烦,于是我们需要使用开闭原则来对程序进行改进,改进思路是把Shape类做成抽象类,并提供一个抽象的draw方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承 Shape,并实现 draw 方法即可,使用方的代码就不需要修改,这样就满足了开闭原则
代码实现:
1 public class OpenClosePrinciple { 2 public static void main(String[] args) { 3 GraphicEditor graphicEditor = new GraphicEditor(); 4 graphicEditor.drawShape(new Rectangle()); 5 graphicEditor.drawShape(new Circle()); 6 graphicEditor.drawShape(new Triangle()); 7 } 8 } 9 10 //用于绘图的类 11 class GraphicEditor { 12 public void drawShape(Shape shape) { 13 shape.draw(); 14 } 15 } 16 17 //基类Shape 18 abstract class Shape { 19 int m_type; 20 21 //抽象方法:绘制图形 22 public abstract void draw(); 23 } 24 25 class Rectangle extends Shape { 26 public Rectangle() { 27 super.m_type = 1; 28 } 29 30 @Override 31 public void draw() { 32 System.out.println("绘制矩形"); 33 } 34 } 35 36 class Circle extends Shape { 37 public Circle() { 38 super.m_type = 2; 39 } 40 41 @Override 42 public void draw() { 43 System.out.println("绘制圆形"); 44 } 45 } 46 47 class Triangle extends Shape { 48 public Triangle() { 49 super.m_type = 3; 50 } 51 52 @Override 53 public void draw() { 54 System.out.println("绘制三角形"); 55 } 56 }
运行结果:
分析:运行结果与上面的代码相同,但是如果我们这时候新增一个绘制梯形的需求,只需要扩展代码即可,不需要修改原有代码
代码实现:
1 public class OpenClosePrinciple { 2 public static void main(String[] args) { 3 GraphicEditor graphicEditor = new GraphicEditor(); 4 graphicEditor.drawShape(new Rectangle()); 5 graphicEditor.drawShape(new Circle()); 6 graphicEditor.drawShape(new Triangle()); 7 graphicEditor.drawShape(new Trapezoid()); 8 } 9 } 10 11 //用于绘图的类 12 class GraphicEditor { 13 public void drawShape(Shape shape) { 14 shape.draw(); 15 } 16 } 17 18 //基类Shape 19 abstract class Shape { 20 int m_type; 21 22 //抽象方法:绘制图形 23 public abstract void draw(); 24 } 25 26 class Rectangle extends Shape { 27 public Rectangle() { 28 super.m_type = 1; 29 } 30 31 @Override 32 public void draw() { 33 System.out.println("绘制矩形"); 34 } 35 } 36 37 class Circle extends Shape { 38 public Circle() { 39 super.m_type = 2; 40 } 41 42 @Override 43 public void draw() { 44 System.out.println("绘制圆形"); 45 } 46 } 47 48 class Triangle extends Shape { 49 public Triangle() { 50 super.m_type = 3; 51 } 52 53 @Override 54 public void draw() { 55 System.out.println("绘制三角形"); 56 } 57 } 58 59 class Trapezoid extends Shape { 60 public Trapezoid() { 61 super.m_type = 4; 62 } 63 64 @Override 65 public void draw() { 66 System.out.println("绘制梯形"); 67 } 68 }
运行结果:
分析:这时候我们发现,仅仅增加了一个新的类Trapezoid继承Shape并且实现了draw方法就实现了功能,在扩展了代码功能的同时也没有对原有代码进行较大的改动,这就是开闭原则的魅力所在