开闭原则
【 概念 】
- 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
- 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
- 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
- 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
【 特点 】
- 对扩展开放(对提供方)
- 对修改关闭(对使用方)
- 用抽象构建框架
- 用实现扩展细节
【 场景介绍 】
现在需要做一个画图形的功能 通过
GraphicEditor
类实现不同类型绘图
【 违反–开闭原则 】
、
public class OCP {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
}
}
class GraphicEditor{
public void drawShape(Shape shape){
if(shape.m_type == 1){
drawRectangle(shape);
}
else if(shape.m_type == 2){
drawCircle(shape);
}
}
private void drawRectangle(Shape s){
System.out.println(s.m_type + "画出:一个矩形");
}
private void drawCircle(Shape s){
System.out.println(s.m_type + "画出:一个圆形");
}
}
class Shape{
int m_type;
}
class Rectangle extends Shape{
Rectangle(){
super.m_type = 1;
}
}
class Circle extends Shape{
Circle(){
super.m_type = 2;
}
}
//---------
【 运行结果 】
可以看到
GraphicEditor
基本实现了只通过一个drawShape()
就能实现不同形状的绘制
但是,如果此时我们提出新增一个画 三角形 的需求,会发现需要直接修改drawShape()
同时还需要再重新创建三角形子类GraphicEditor
还需要增加对应三角形方法
public class OCP {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
//新增
graphicEditor.drawShape(new Triangle());
}
}
class GraphicEditor{
public void drawShape(Shape shape){
if(shape.m_type == 1){
drawRectangle(shape);
}
else if(shape.m_type == 2){
drawCircle(shape);
} else if (shape.m_type == 3) {
drawTriangle(shape);
}
}
private void drawRectangle(Shape s){
System.out.println(s.m_type + "画出:一个矩形");
}
private void drawCircle(Shape s){
System.out.println(s.m_type + "画出:一个圆形");
}
//新增
private void drawTriangle(Shape s){
System.out.println(s.m_type + "画出:一个三角形");
}
}
class Shape{
int m_type;
}
class Rectangle extends Shape{
Rectangle(){
super.m_type = 1;
}
}
class Circle extends Shape{
Circle(){
super.m_type = 2;
}
}
//新增
class Triangle extends Shape{
Triangle(){
super.m_type = 3;
}
}
【 遵循–开闭原则 】
public class OCP {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
//新增
graphicEditor.drawShape(new Triangle());
}
}
//此时使用者GraphicEditor不需要根据 业务新增子类而变化代码 实现OCP原则
class GraphicEditor{
public void drawShape(Shape shape) {
shape.draw();
}
}
//抽象基类 额外增加一个draw()方法供子类实现 及其他使用者调用
abstract class Shape{
int m_type;
void draw(){};
}
class Rectangle extends Shape{
Rectangle(){
super.m_type = 1;
}
@Override
void draw() {
System.out.println(this.m_type + "画出:一个矩形");
}
}
class Circle extends Shape{
Circle(){
super.m_type = 2;
}
@Override
void draw() {
System.out.println(this.m_type + "画出:一个圆形");
}
}
//新增
class Triangle extends Shape{
Triangle(){
super.m_type = 3;
}
@Override
void draw() {
System.out.println(this.m_type + "画出:一个三角形");
}
}
【 运行结果 】
基类Shape新增一个抽象方法
draw()
该方法可以提供给使用者GraphicEditor
且Shape子类实现时GraphicEditor
不需要做修改
【 注意实现及细节 】
这里的做法和依赖倒置的解决方法很相似 同样都是抽取出公用的方法作为接口
- 软件(类、模块和函数)应该对扩展开放,对修改关闭
- 用抽象构建框架,用实现扩展细节
- 软件需要变化时,尽量通过 拓展软件实体的行为来实现变化,而不是通过修改已有代码来实现变化
- 编程遵循其他原则,及使用设计模式就是为了实现开闭原则