|
面向对象设计的一个重要分析方法是利用对象的职责来驱动设计。对象有了职责,才会成为具体拥有意识的对象,成为对象社区中可以独立完成,或者发出指令委派别的对象协作完成职责的一员。将对象看成是“具有职责的东西”。对象应该自己负责自己,而且应该清楚地定义职责。这就是对象设计的关键。好的软件设计者应该像牧羊人一般放牧自己的牛羊,只需要给它们一片丰沃的草地,它们就能自己觅食生活。
Rebecca认为:对象在履行职责时有3种选择,你可以任选其一:(1)亲自完成所有的工作。(2)请求其他对象帮忙完成部分工作(和其他对象协作)。(3)将整个服务请求委托给另外的帮助对象。在分析对象职责时,可以考虑“专家”模式,即信奉专业的事情交给专家来完成,既不互相推诿,却也不能越俎代庖。专家有其擅长的领域,如果把专家错放在他不熟悉的领域,不仅会降低工作效率,还可能引入潜在危机。所谓“尺有所长,寸有所短”,含义正在于此。
对象的能力总是有限的,正如我们不能将所有的鸡蛋放在一个篮子里,我们也不能将所有的职责交给“上帝”。这既避免单一功能点带来的风险,又能实现职责的分权。Christepher Alexander建议,在遇到设计问题时“尽量少用集权的机制”。软件设计同样如此。职责总是可大可小,面对复杂的职责行为,总是需要多个对象的协作才能完成,就像机器中的零部件,按部就班,各司其职。
让我们来设计一个数据分析器,它通过分析算法对输入数据进行分析,并将结果保存在输出集中。根据业务需求的不同,执行的分析算法也不相同。同时,为了提高分析性能,我们还需要采用多线程方式执行分析任务。从调用者的角度来看【即Martin Fowler提到的规约视角】,我们只关心分析需要的数据以及分析后的结果。那么,谁应该来承担分析的职责呢?毫无疑问,我们可以定义分析器对象来履行这一职责。此外,调用者其实并不会关心分析算法的实现以及分析的过程,他希望分析是易于执行的,这一愿望通过有效的封装完全可以满足。我们可以将分析的职责封装在DataAnalyzer类中,同时隐藏具体的分析算法。
public class Client {
public static void run(InputData input) {
DataAnalyzer analyzer = new DataAnalyzer();
AnalyticResult result = analyzer.analysis(input);
//做其它事情
//处理分析后的数据
handleOutput(analyzer.output(result));
}
}
public class DataAnalyzer {
public AnalyticResult analysis(InputData input) {}
public OutputData output(AnalyticResult result) {}
}
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。