转载请注明出处!!!http://blog.csdn.net/zhonghuan1992
所有配套代码均在github上:https://github.com/ZHONGHuanGit/DesignPattern
跟着ZHONGHuan学习设计模式
开闭原则
上面讲完序,就开始讲开闭原则,有点不太优雅,不过,正如我说的,在学之前,周围的人和老师,网络上的人都觉得这个不错,你不太清楚,那么就学学吧,学完之后,再仔细去整合,思考,去除杂质,保留精华。在学的过程中总是不断自己停下来仔细思考的方式,我并不推荐学技术的人干(当然立志科研的人一定要有这种钻研精神),因为太耗时间。而且有时候你会发现,你疑问的就是后面提到的。唠叨完毕,开始讲讲开闭原则。
1988年,勃兰特·梅耶(Bertrand Meyer)在他的著作《面向对象软件构造(Object Oriented Software Construction)》中提出了开闭原则,它的原文是这样:“Softwareentities should be open for extension, but closed for modification”。翻译过来就是:“软件实体应当对扩展开放,对修改关闭”。
定义有点虚,可能你也会觉得矛盾,其实就是,你要改程序的,增加新的功能,那么不准修改原来的程序代码,只能增加新的代码。为什么要这样呢?疑问在心头,解决疑问的方式,让我们用举例来回答吧。
让我们来用NBA的篮球明星来举例好不好(体谅下作者是篮球迷吧!)。不懂篮球的同学也没关系,不会要求有专业知识。我们都明白,每个人的习惯是不一样的,篮球明星是人,所以篮球明星们的一些习惯是不一样的(这句话是为了回忆那些证明题╮(╯▽╰)╭)。有些篮球明星,比如科比,身体比较平均。詹姆斯,身体比较粗壮。艾弗森,身体比较瘦小。既然他们的身体不一样,那么他们的得分技巧必然不同,我们就写一个能够表示NBA球星的吧!
import java.util.*;
//将技巧抽象为一个方法,单独拿出来
interface Skill{
public void skill();
};
//詹姆斯的技巧
class JamesSkill implements Skill{
public void skill()
{
System.out.println("詹姆斯的技巧:战斧式扣篮");
}
};
//科比的技巧
class KobeSkill implements Skill{
public void skill()
{
System.out.println("科比的技巧: 后仰跳投");
}
};
//艾弗森的技巧
class AISkill implements Skill{
public void skill()
{
System.out.println("艾弗森的技巧: 变相");
}
};
/*
抽象的方法拿出来后,有不同的类来实现抽象方法这个接口,让不同的选手持有不同的行为类,这个设计方案叫做封装可变形。 同时,在后面的设计模式中我们也会讲到,这个叫做策略模式
*/
class NBAPlayer {
//姓名
private String name;
private Skill skill;
public NBAPlayer(String name,Skill skill){
this.name=name;
this.skill=skill;
}
public void setSkill(Skill skill){
this.skill=skill;
}
public Skill getSkill(){
return skill;
}
public String getName(){
return name;
}
public void action(){
skill.skill();
}
};
public class Main{
public static void main(String args[])
{
//不同的技巧
Skill jamesSkill=new JamesSkill();
Skill kobeSkill=new KobeSkill();
Skill aiSkill=new AISkill();
//不同的球员
NBAPlayer james=new NBAPlayer("James",jamesSkill);
NBAPlayer kobe=new NBAPlayer("kobe",kobeSkill);
NBAPlayer ai=new NBAPlayer("AI",aiSkill);
//会有不同的表现
james.action();
kobe.action();
ai.action();
}
}
代码可以这里下载 https://github.com/ZHONGHuanGit/DesignPattern
从代码中我们看到,不同的NBAPlayer的行为被抽象为一个接口,具体的实现放在具体的类中。之所以这样设计,是为了符合开闭原则。现在我们可以想想,当我们有新的球员来了,它的技巧是不一样的,这个时候我们就可以新建一个类,实现Skill接口,然后作为对象属性存在球员对象中。这样的优点,就是做的优点就是,新的球员增加不会更改原有的代码,只需要增加新的代码即可。是不是很不错啊,在设计中,我们尽量把代码中,将来可能会发生变化的地方封装起来,拿出去,用抽象的类封装,具体的实现放在后面的具体类中。因为我们更改起代码会特别方便。