在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据7条原则来开发程序,从而提高软件开发效率,节约软件开发成本和维护成本。
可维护性:
定义:维护人员理解、改正、改动和改进这个软件的难易程度。
简单理解就是,软件的维护就是软件的再生。一个好的软件设计,必须能够允许新的设计要求以较为容易和平稳的方式加入到已有系统中去,从而使这个系统能够不断的焕发青春。
可复用性:“复用”有时译作“重用”,即重复使用的意思。
分类:①代码的复用②设计的复用③分析的复用④测试信息的复用
好处:①较高的生产效率②较高的软件质量③改善系统的可维护性
可维护性和可复用性的联系:通常认为,一个易于维护的系统,就是复用率较高的系统;而一个复用性较好的系统,就是一个易于维护的系统。
可扩展性:新的功能可以很容易的加入到系统中去。
灵活性:软件的应变能力。敏捷的软件架构为将来因为客户需求而变化时,能够做尽可能很少的修改。
定义:软件实体应当对扩展开放,对修改关闭。(在程序需要拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,就是为了使程序的扩展性好,易于维护和升级。)
软件实体包括以下几个部分:①项目中划分出的模块②类与接口③方法
热插拔:例如计算机为鼠标提供USB接口,进行插拔式操作,用的时候就插上,不用的时候就拔下来,好扩展。
实现方法:“抽象约束,封装变化”,即通过接口或抽象类为软件实体定义一个相对稳定的抽象层(抽象的就是规范),而将相同的可变因素封装在相同的具体实现类中(子类重写父类定义的抽象方法)。
因为抽象灵活性好,适应性广,只要抽象合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展。当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
应用:下面以搜狗输入法的皮肤为例介绍开闭原则的应用。
分析:搜狗输入法的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜好更换输入法皮肤。这些皮肤有共同的特点,可以为其定义一个抽象类(AbstractSkin),而每个具体的皮肤(DefaultSpectificSkin)和(NewSpecificSkin)是其子类。用户若要新增皮肤,只需创建一个新的实现类,而不需要修改原来的代码,满足“开闭原则”。
1.抽象皮肤类,里面包含展示皮肤的抽象方法,无返回值,不含参数。
public abstract class AbstractSkin {
//显示皮肤
public abstract void display();
}
2.具体皮肤类(默认皮肤,DefaultSpecificSkin),实现父类(AbstractSkin)中的抽象方法。
public class DefauleSpecificSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("默认皮肤");
}
}
3.具体皮肤类(新皮肤,NewSpecificSkin),同上。
public class NewSpecificSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("新皮肤");
}
}
4.搜狗输入法类(SouGouInput,因为要使用皮肤,所以聚合了AbstractSkin具体实现类的对象)
public class SougouInput {
//搜狗输入法要用皮肤,所以进行聚合
private AbstractSkin skin;
public void setSkin(AbstractSkin skin) {
this.skin = skin;
}
public void display(){
skin.display();
}
}
5.测试类
public class Client {
public static void main(String[] args) {
//1,创建搜狗输入法对象
SougouInput input = new SougouInput();
//2,创建皮肤对象(用搜狗输入法皮肤)
//DefauleSpecificSkin skin = new DefauleSpecificSkin();//用默认皮肤
NewSpecificSkin skin = new NewSpecificSkin();//使用新皮肤
//3,将皮肤设置到输入法中
input.setSkin(skin);
//4,显示皮肤
input.display();
}
}
运行结果
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}