🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
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所示。 ![](https://box.kancloud.cn/2016-08-14_57b003726d5e3.jpg) 图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。