定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修改关闭,并没有明确的告诉我们。以前,如果有人告诉我“你进行设计的时候一定要遵守开闭原则”,我会觉的他什么都没说,但貌似又什么都说了。因为开闭原则真的太虚了。
在仔细思考以及仔细阅读很多设计模式的文章后,终于对开闭原则有了一点认识。其实,我们遵循设计模式前面5大原则,以及使用23种设计模式的目的就是遵循开闭原则。也就是说,只要我们对前面5项原则遵守的好了,设计出的软件自然是符合开闭原则的,这个开闭原则更像是前面五项原则遵守程度的“平均得分”,前面5项原则遵守的好,平均分自然就高,说明软件设计开闭原则遵守的好;如果前面5项原则遵守的不好,则说明开闭原则遵守的不好。
其实笔者认为,开闭原则无非就是想表达这样一层意思:用抽象构建框架,用实现扩展细节。因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了。当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性才行。
说到这里,再回想一下前面说的5项原则,恰恰是告诉我们用抽象构建框架,用实现扩展细节的注意事项而已:单一职责原则告诉我们实现类要职责单一;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合。而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。
最后说明一下如何去遵守这六个原则。对这六个原则的遵守并不是是和否的问题,而是多和少的问题,也就是说,我们一般不会说有没有遵守,而是说遵守程度的多少。任何事都是过犹不及,设计模式的六个设计原则也是一样,制定这六个原则的目的并不是要我们刻板的遵守他们,而需要根据实际情况灵活运用。对他们的遵守程度只要在一个合理的范围内,就算是良好的设计。我们用一幅图来说明一下。
图中的每一条维度各代表一项原则,我们依据对这项原则的遵守程度在维度上画一个点,则如果对这项原则遵守的合理的话,这个点应该落在红色的同心圆内部;如果遵守的差,点将会在小圆内部;如果过度遵守,点将会落在大圆外部。一个良好的设计体现在图中,应该是六个顶点都在同心圆中的六边形。
在上图中,设计1、设计2属于良好的设计,他们对六项原则的遵守程度都在合理的范围内;设计3、设计4设计虽然有些不足,但也基本可以接受;设计5则严重不足,对各项原则都没有很好的遵守;而设计6则遵守过渡了,设计5和设计6都是迫切需要重构的设计。
下面是使用开闭原则的一个简单示例,虽有些不准确,但是是这个意思(领会精神)
定义一个接口,寻找美女
package com.loulijun.chapter6;
public interface IFindGirl {
//年龄
public int getAge();
//姓名
public String getName();
//长相
public String getFace();
//身材
public String getFigure();
} |
实现这个接口
package com.loulijun.chapter6;
public class FindGirl implements IFindGirl {
private String name;
private int age;
private String face;
private String figure;
public FindGirl(String name, int age, String face, String figure)
{
this .name = name;
this .age = age;
this .face = face;
this .figure = figure;
}
@Override
public int getAge() {
return age;
}
@Override
public String getFace() {
return face;
}
@Override
public String getFigure() {
return figure;
}
@Override
public String getName() {
return name;
}
} |
场景:大街上
package com.loulijun.chapter6;
import java.text.NumberFormat;
import java.util.ArrayList;
public class Street {
private final static ArrayList<IFindGirl> girls = new ArrayList<IFindGirl>();
//静态初始化块
static
{
girls.add( new FindGirl( "张含韵" , 23 , "可爱型" , "165cm/47kg" ));
girls.add( new FindGirl( "高圆圆" , 33 , "时尚型" , "165cm/48kg" ));
girls.add( new FindGirl( "章泽天" , 19 , "清纯型" , "168cm/47kg" ));
}
public static void main(String args[])
{
System.out.println( "----------美女在这里----------" );
for (IFindGirl girl:girls)
{
System.out.println( "姓名:" +girl.getName()+ " 年龄:" +girl.getAge()+
" 长相:" +girl.getFace()+ " 身材:" +girl.getFigure());
}
}
} |
运行结果:
----------美女在这里----------
姓名:张含韵 年龄:23 长相:可爱型 身材:165cm/47kg
姓名:高圆圆 年龄:33 长相:时尚型 身材:165cm/48kg
姓名:章泽天 年龄:19 长相:清纯型 身材:168cm/47kg
但是如果想独立分出一个外国美女的类别的话(比如增加一个国籍),可以通过修改接口、修改实现类、通过扩展来实现。
如果修改接口,也就意味着修改实现类,这样对项目的变动太大了,所以不推荐
如果修改实现类,这样虽能解决问题,但是明显有些牵强,如果需要其他变动的时候会显得逻辑混乱
所以,通过扩展来实现是最简单的方式
如何扩展:
可以定义一个IForeigner接口继承自IFindGirl,在IForeigner接口中添加国籍属性getCountry(),然后实现这个接口即可,然后就只需要在场景类中做稍微修改就可以了
package com.loulijun.chapter6;
public interface IForeigner extends IFindGirl {
//国籍
public String getCountry();
} |
实现接口
package com.loulijun.chapter6;
public class ForeignerGirl implements IForeigner {
private String name;
private int age;
private String country;
private String face;
private String figure;
public ForeignerGirl(String name, int age, String country, String face, String figure)
{
this .name = name;
this .age = age;
this .country = country;
this .face =face;
this .figure = figure;
}
@Override
public String getCountry() {
// TODO Auto-generated method stub
return country;
}
@Override
public int getAge() {
// TODO Auto-generated method stub
return age;
}
@Override
public String getFace() {
// TODO Auto-generated method stub
return face;
}
@Override
public String getFigure() {
// TODO Auto-generated method stub
return figure;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
} |
然后在场景类中只需要修改如下代码即可,其他不变
girls.add( new ForeignerGirl( "Avirl" , 28 , "美国" , "性感型" , "160cm/45kg" ));
|
不过这些设计原则到不是绝对的,而是根据项目需求,实际需求来定夺使用
相关推荐
本篇将深入探讨“开闭原则”(Open Close Principle,OCP)、“状态模式”以及“模板方法模式”,并提供一个结合这三种模式的实际代码示例。 首先,我们来理解“开闭原则”(OCP)。这是面向对象设计的一个基本原则...
2.设计模式的六大原则 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要... 3.Java的23中设计模式 从这一块开始,我们详细介绍Java中23种设计模式的概念,应用...
1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和...
开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。...
1、开闭原则(Open Close Principle) 2、里氏代换原则(Liskov Substitution Principle) 3、依赖倒转原则(Dependence Inversion Principle) 4、接口隔离原则(Interface Segregation Principle) 5、迪米特法则...
1、开闭原则(Open Close Principle) 对扩展开放,对修改关闭。 2、里氏代换原则(Liskov Substitution Principle) 只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生...
1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和...
原则3: 开闭原则 Open-Close Principle(OCP) 即对扩展开放,对修改关闭。这是另一种非常棒的设计原则,可以防止其他人更改已经测试好的代码。理论上,可以在不修改原有的模块的基础上,扩展功能。这也是开闭原则的...
1. **开闭原则 (Open Close Principle, OCP)**:这一原则要求软件实体(如类、模块、函数等)应对于扩展开放,而对于修改封闭。这意味着在面对新的需求时,我们应该尽可能地通过添加新代码而不是修改已有代码来实现...
二、OCP(Open-Close Principle):开闭原则 OCP是软件设计的七大原则之一,它的定义是:软件实体(类、模块、函数/方法等等)对于扩展应该是开放的,对于修改应该是封闭的。OCP可以提高软件模块的可重用性和可维护...
设计模式的六大原则1、开闭原则(Open Close Principle)开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,...
- 开闭原则(Open Close Principle):软件实体应当对扩展开放,对修改关闭。 通过以上知识点的讲解,我们可以看到,设计模式不仅可以帮助我们解决实际编程中的具体问题,还可以提升代码的可读性、可维护性,以及...
开闭原则(Open Close Principle) 里氏代换原则(Liskov Substitution Principle) 依赖倒转原则(Dependency Inversion Principle) 接口隔离原则(接口隔离原则) 迪米特法则,又称最少知道原则(Demeter ...
开闭原则(Open Close Principle) 开闭原则是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括是:为了使程序的扩展性好,易于维护和升级。想...
#OCP 如果我们希望添加一个新的三角形形状,那么我们所做的就是添加 另一个实现形状接口的子类。 无需更改 GraphicalEditor。 好处:- • 无需单元测试。 • 无需了解GraphicEditor 的源代码。...
1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级...
#### 一、开闭原则(Open-Close Principle) **定义:** 开闭原则强调的是软件实体(类、模块、函数等)应该是可扩展的但不可修改的,即软件实体应该对扩展开放,对修改关闭。 **实践方法:** - **接口或抽象类...
一、开闭原则(Open Close Principle)### 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。 所以一句话概括就是:为了使程序的扩展性好,易于维护...
开闭原则(Open Close Principle):对扩展开放,对修改关闭。 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是: 为了使程序的扩展性好,易于维护和升级。想要达到这样的...
#设计模式的六大原则##1、开闭原则(Open Close Principle)开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展...