在建筑工地上,经常看到的是建筑工人在盖房子,却看不到制砖工人在切制砖瓦;在汽车厂房里,经常看到汽车工人在组装汽车,却看不到有工人在制造轮胎。社会化的分工越来越细,这就是当今社会的运转模式,同样,在软件开发过程中,分工也越来越细,有人专门做UI设计,有人专门做系统设计,有人专门做代码编写,有人专门做测试,这就是软件开发的模式。分工越细,从事某项分工的人员就越专业,比如程序设计,由于它是把人类思维具体化过程中的一种方法,所以特别不好掌握,因此就有一些专家把他们在解决这一问题过程中积累的一些经验进行总结,以帮助后来人更好地掌握从抽象到具体的方法,就是设计模式。
1.1 小巩的疑惑
小巩大学刚毕业,就进入了某软件公司做程序员,经过3个月的Java培训后,被分配到了大拿这个项目组,大拿是公司的技术架构师,水平很高。大拿的项目组目前正在给一家企业做人事软件,小巩被安排来开发薪资程序的一小部分。
小巩早就想一显身手了,还没有接到大拿的设计文档,就粗略看了一下需求文档,开始设计开发了。因为这家企业有很多子公司,所以小巩进行了如下设计,首先抽象一个薪资类,然后所有的子公司薪资类都继承这个抽象的薪资类。抽象薪资类的示意代码如下:
//******* Salary.java**************
package com.gongdan;
public interface Salary {
void computerSalary ();
}
河北子公司的薪资类示意代码如下:
//******* HeBeiSalary.java**************
package com.gongdan;
public class HeBeiSalary implements Salary {
public void computerSalary() {
System.out.println("开始计算河北子公司的薪资");
}
}
吉林子公司的薪资类示意代码如下:
//******* JiLinSalary.java**************
package com.gongdan;
public class JiLinSalary implements Salary {
public void computerSalary() {
System.out.println("开始计算吉林子公司的薪资");
}
}
这样当客户端调用的时候,首先判断是哪个子公司,然后再新建一个薪资类的对象就可以了,客户端调用的示意代码如下:
//******* Client.java**************
package com.gongdan;
public class Client {
/*根据参数创建不同的对象*/
public Salary createSalary (String name) {
Salary salary = null;
if ("HeBei".equals(name))
salary = new HeBeiSalary();
else if ("JiLin".equals(name))
salary = new JiLinSalary();
return salary;
}
/*具体的薪资计算*/
public void computerSalary (String name) {
Salary salary = createSalary(name);
salary. computerSalary();
}
}
小巩很快就完成了设计,看到自己设计的薪资类,小巩心里很高兴,但同时又有了疑问:“听说这家公司很快要兼并很多公司,这样一来,它就有了很多的子公司,那客户端的条件判断岂不是也要写很多?代码也肯定越写越长了。”
刚想到这里,大拿的设计方案就送过来了,小巩一看,茅塞顿开:“原来可以这样设计啊,高手就是高手。”
大拿是这样来设计的:首先也是一个抽象的薪资类,然后子公司的薪资类都继承这个抽象的薪资类,这点和小巩设计的一样,但是大拿这里又多设计了一个工厂类,把具体产生薪资类的判断语言抽取到工厂类里,并且使用了Java的反射机制,而客户端则只负责具体的薪资计算。这样一来类的职责也清晰了,而且由于使用了Java的反射机制,代码也变少了。抽象薪资类的示意代码如下:
//******* Salary.java**************
package com.gongdan;
public interface Salary {
void computerSalary ();
}
河北子公司的薪资类示意代码如下:
//******* HeBeiSalary.java**************
package com.gongdan;
public class HeBeiSalary implements Salary {
public void computerSalary() {
System.out.println("开始计算河北子公司的薪资");
}
}
吉林子公司的薪资类示意代码如下:
//******* JiLinSalary.java**************
package com.gongdan;
public class JiLinSalary implements Salary {
public void computerSalary() {
System.out.println("开始计算吉林子公司的薪资");
}
}
产生薪资类对象的工厂类示意代码如下:
//******* SampleFactory.java**************
package com.gongdan;
public class SampleFactory {
/*根据参数创建不同的对象*/
public static Salary createSalary (String name) {
Class c = Class.forName(name);
Salary salary = (Salary)c.newInstance();
return salary;
}
}
这样客户端只负责具体的薪资计算而不需要判断要创建哪个子公司的薪资类了,客户端调用的示意代码如下:
//******* Client.java**************
package com.gongdan;
public class Client {
/*具体的薪资计算*/
public void computerSalary (String name) {
Salary salary = SampleFactory.createSalary(name);
salary. computerSalary();
}
}
说明 | ||
上述只是示意代码,实际的薪资计算程序要比这复杂。 |
小巩看完大拿的设计,心里自愧不如,马上问大拿:“大拿,你是如何思考才这样设计的啊?”
大拿说:“其实没什么,这是参考设计模式里面的简单工厂模式,随着设计经验的积累,你也会慢慢设计出更好的程序的,你先找些设计模式的书籍看看吧。”