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。