设计六大原则,其实在网络上很多地方都有描述,并且都很详尽。我在这里找了一篇简单易懂的的文章,整理过来,主
要是为了方便自己以及学生查看。
设计六大原则:单一职责原则,里氏替换原则,依赖倒置原则,接口隔离原则,迪米特法则,开闭原则
接下来,我们一个一个的分别描述这六大原则
单一职责原则:
单一职责原则:又称之为单一功能原则,它规定我们在制定类或制定模块时,一个类或一个模块只有一个原因可
以导致它改变,它是内聚的体现。大家应该都知道我们程序编写的最基本的原则“高内聚,低耦合”,内聚描述的是软
件模块内部的联系,一个好的内聚块应该是只做以及做好一件事;耦合则是描述的是模块间的联系,耦合强弱取决于
模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。“高内聚,低耦合”是我们判断一个设计的好
坏的最根本的原则,我们六大原则也是围绕着这一个思想在不断的体现。
那么什么是职责,职责就是指变化的原因,这个通俗点理解就是说:你的代码写好后,导致你代码修改的原因,
为什么要去修改它,原因是否只有1个?
违背单一原则的场景:我这里采用依旧其他文章中的动物的示例,早期, 项目中这个动物类有个行为叫“呼吸”,
还有个行为是“吃草”。类图如下:
package yuanze;
/**
* 动物类
*
* @author Administrator
*
*/
public class Animal {
private String name;// 动物的名称
public Animal() {
super();
// TODO Auto-generated constructor stub
}
public Animal(String name) {
super();
this.name = name;
}
/**
* 吃草
*/
public void eat() {
System.out.println(name + "吃草!");
}
/**
* 呼吸
*/
public void breathe() {
System.out.println(name + "呼吸空气!");
}
}
客户端程序调用时,如下:
package yuanze;
public class Test {
public static void main(String[] args) {
Animal yang = new Animal("羊");
Animal niu = new Animal("牛");
yang.eat();
yang.breathe();
niu.eat();
niu.breathe();
}
}
执行下来的结果是:
羊吃草!
羊呼吸空气!
牛吃草!
牛呼吸空气!
嗯,很不错,得到了我们想要的结果。可以上线了……
但是上线后,却发现我们的这种设计,好像不太满足吃肉的东西,也不太满足水下生物,他们呼吸的是水,怎么
办呢?较多的程序员,应该就会这样搞:
我再加上一个“呼吸”,“吃肉”的方法不就可以了么,O(∩_∩)O哈哈哈~
package yuanze;
/**
* 动物类
*
* @author Administrator
*
*/
public class Animal {
private String name;// 动物的名称
public Animal() {
super();
// TODO Auto-generated constructor stub
}
public Animal(String name) {
super();
this.name = name;
}
/**
* 吃草
*/
public void eat() {
System.out.println(name + "吃草!");
}
/**
* 吃肉
*/
public void eat2() {
System.out.println(name + "吃肉!");
}
/**
* 呼吸
*/
public void breathe() {
System.out.println(name + "呼吸空气!");
}
/**
* 呼吸
*/
public void breathe2() {
System.out.println(name + "呼吸水!");
}
}
客户端程序也修改为:
package yuanze;
public class Test {
public static void main(String[] args) {
Animal yang = new Animal("羊");
Animal niu = new Animal("牛");
yang.eat();
yang.breathe();
niu.eat();
niu.breathe();
Animal gou = new Animal("狗");
Animal yu = new Animal("鱼");
gou.eat2();
gou.breathe();
yu.eat();
yu.breathe2();
}
}
执行后的结果是:
羊吃草!
羊呼吸空气!
牛吃草!
牛呼吸空气!
狗吃肉!
狗呼吸空气!
鱼吃草!
鱼呼吸水!
这下应该可以上线了吧,O(∩_∩)O哈哈哈~
但是客户还是不满意,说:你完全没考虑到两栖动物,也没考虑到淡水鱼与海水鱼啊,你这设计不行……
我们下来分析,导致Animal变化的原因有:根据动物的种类与吃,那么我们可以大体分为很多种,如:陆地草食
系动物,陆地肉食系动物,水下草食系动物,水下肉食系动物,两栖动物…… 这么多的类型,我们放置在同一个
类型中,那么任何一个变化,这个类也就需要不断的变化,类的功能越来越复杂,负责的事情越来越多,后期的维护
也就越来越困难。如果我们在修改的过程中,手抖了,就可能导致其他的动物吃草的,变吃肉的了……
当然,就不用说客户需求的不断的变化,水下又可分为淡水,海水。陆地生物,一会要考虑它奔跑的能力,一会又要
考虑它其他繁殖……
总体来说,上述的设计,就是违背了单一职责原则。
那么相对较好的设计,应该是:
即便,突然某一天客户说要将水下分为:淡水,海水
这样的设计后,如果需要修改其中的某一个,就不会涉及到其他的修改了,也符合后面要说的“开闭原则”,每一个类
也只负责一种类型的动物,而不用去关心其他类型动物的行为。
当然,很多情况下,是否要完全遵循“单一职责原则”,视具体情况而定。如果代码重构的量大,重构后又得不偿失的
话,就自己看到处理即可……
遵循单一职责原的优点有:
提高类的可读性,提高系统的可维护性;
变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功
能的影响。
需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责
原则。