首页 » 设计模式之禅(第2版) » 设计模式之禅(第2版)全文在线阅读

《设计模式之禅(第2版)》38.3 雇工模式

关灯直达底部

38.3.1 雇工合作

我是一个富豪(当然只是想象中的),家里有很多佣人,家务活基本上不用我动手,我只要动动口就可以了,在这里每个人都有不同分工,我可以指挥厨师把厨房弄干净,这是他的地盘;我可以指挥园丁把花园收拾干净、漂亮,这是他应该做的;我还可以让裁缝把我的衣服收拾干净。注意看,我这里列举出的三个对象(厨师、园丁、裁缝)都具有相同的功能:清洁。从另一方面说,厨房、花园、衣服都具有被清洁的特性,我们从这一例子入手,编写代码如代码清单38-32所示。

代码清单38-32 三个对象的被清洁特质

//可以被清洁的对象public interface Cleanable {     //被清洁     public void celaned;}//花园class Garden implements Cleanable{     public void celaned{  System.out.println(“花园被清洁干净”);     }}//厨房class Kitchen implements Cleanable{     public void celaned{  System.out.println(“厨房被清洁干净”);     }}//衣服class Cloth implements Cleanable{     public void celaned{  System.out.println(“衣服被清洁干净”);     }}  

三个对象(厨房、花园、衣服)的共同特征抽取出来,同时也需要把厨师、裁缝、园丁的共同特征也抽象出来。从我这个主人的角度看来,他们三者都是清洁者,只是输入的对象不同而已,如代码清单38-33所示。

代码清单38-33 抽象的清洁者

public class Cleaner {     //清洁     public void clean(Cleanable clean){  clean.celaned;     }}  

非常简单,就这么一个清洁者就可以厨师、园丁、裁缝。我们再编写一个场景类,描述一下发生了什么事,如代码清单38-34所示。

代码清单38-34 场景类

public class Client {     public static void main(String args) {  //厨师清洁厨房  Cleaner cookie = new Cleaner;  cookie.clean(new Kitchen);  //园丁清洁花园  Cleaner gardener = new Cleaner;  gardener.clean(new Garden);  //裁缝清洁衣服  Cleaner tailer = new Cleaner;  tailer.clean(new Cloth);     }}  

场景写完了,运行一下,就可以看到厨师打扫了厨房,园丁清洁了花园,裁缝清洁了衣服。代码很简单,但是诸位有没有发觉这和我们通常的分析是不同的。通常的做法是:既然厨师、园丁、裁缝都具有清洁的功能,那就定义一个接口描述三者的清洁功能,然后再定义三个类,分别代表厨师、园丁、裁缝实现这个接口。这是一种常用的解决办法,可以解决该问题,但今天我们从另外一个侧面进行分析,引出一个新的模式:雇工模式。

38.3.2 雇工模式的意图

雇工模式也叫做仆人模式(Servant Design Pattern),其意图是:

雇工模式是行为模式的一种,它为一组类提供通用的功能,而不需要类实现这些功能,它是命令模式的一种扩展[1]。

看看我们的例子,厨师、裁缝、园丁是一组类,都具有清洁的能力,但是我们却没实现,而是采用一种更优雅的方式来实现,这就是雇工模式。雇工模式的类图如图38-7所示。

图38-7 雇工模式通用类图

在类图中,IServiced是用于定义“一组类”所具有的功能,其示例代码如代码清单38-35所示。

代码清单38-35 通用功能

public interface IServiced {     //具有的特质或功能     public void serviced;}  

针对不同的服务对象具备不同的服务内容,也就是具体的功能实现IServiced接口即可,示例代码如代码清单38-36所示。

代码清单38-36 定义具体功能

public class Serviced1 implements IServiced {     public void serviced{       }}public class Serviced2 implements IServiced{     public void serviced{       }}  

功能定义完毕后,我们需要由一个雇工来执行这些功能。简单地说,就是需要有一个执行者,可以把一组功能聚集起来,示例代码如代码清单38-37所示。

代码清单38-37 雇工类

public class Servant {     //服务内容     public void service(IServiced serviceFuture){  serviceFuture.serviced;     }}  

在整个雇工模式中,所有具有IServiced功能的类可以实现该接口,然后由雇工类Servant进行集合,完成一组类不用实现通用功能而具有相应职能的目的。

38.3.3 最佳实践

在日常的开发过程中,我们可能已经接触过雇工模式,只是我们没有把它抽取出来,也没有汇编成册。或许大家已经看出这与命令模式非常相似,读者可以回顾第15章,会发现雇工模式是命令模式的一种简化,但它更符合我们实际的需要,更容易引入开发场景中。

[1]原文是A behavioral pattern used to offer some functionality to a group of classes without defining that functionality in each of them。