38.3 雇工模式
38.3 雇工模式
38.3.1 雇工合作
我是一个富豪(当然只是想象中的),家里有很多佣人,家务活基本上不用我动手,我只要动动口就可以了,在这里每个人都有不同分工,我可以指挥厨师把厨房弄干净,这是他的地盘;我可以指挥园丁把花园收拾干净、漂亮,这是他应该做的;我还可以让裁缝把我的衣服收拾干净。注意看,我这里列举出的三个对象(厨师、园丁、裁缝)都具有相同的功能:清洁。从另一方面说,厨房、花园、衣服都具有被清洁的特性,我们从这一例子入手, 编写代码如代码清单38-32所示。
代码清单38-32 三个对象的被清洁特质
1 | //可以被清洁的对象 |
三个对象(厨房、花园、衣服)的共同特征抽取出来,同时也需要把厨师、裁缝、园丁的共同特征也抽象出来。从我这个主人的角度看来,他们三者都是清洁者,只是输入的对象不同而已,如代码清单38-33所示。
代码清单38-33 抽象的清洁者
1 | public class Cleaner { |
三个对象(厨房、花园、衣服)的共同特征抽取出来,同时也需要把厨师、裁缝、园丁的共同特征也抽象出来。从我这个主人的角度看来,他们三者都是清洁者,只是输入的对象不同而已,如代码清单38-33所示。
代码清单38-33 抽象的清洁者
1 | public class Cleaner { |
非常简单,就这么一个清洁者就可以厨师、园丁、裁缝。我们再编写一个场景类,描述一下发生了什么事,如代码清单38-34所示。
代码清单38-34 场景类
1 | public class Client { |
场景写完了,运行一下,就可以看到厨师打扫了厨房,园丁清洁了花园,裁缝清洁了衣服。代码很简单,但是诸位有没有发觉这和我们通常的分析是不同的。通常的做法是:既然厨师、园丁、裁缝都具有清洁的功能,那就定义一个接口描述三者的清洁功能,然后再定义三个类,分别代表厨师、园丁、裁缝实现这个接口。这是一种常用的解决办法,可以解决该问题,但今天我们从另外一个侧面进行分析,引出一个新的模式:雇工模式。
38.3.2 雇工模式的意图
雇工模式也叫做仆人模式(Servant Design Pattern),其意图是:
雇工模式是行为模式的一种,它为一组类提供通用的功能,而不需要类实现这些功能, 它是命令模式的一种扩展[^1]。
看看我们的例子,厨师、裁缝、园丁是一组类,都具有清洁的能力,但是我们却没实现,而是采用一种更优雅的方式来实现,这就是雇工模式。雇工模式的类图如图38-7所示。
代码清单38-35 通用功能
1 | public interface IServiced { |
针对不同的服务对象具备不同的服务内容,也就是具体的功能实现IServiced接口即可, 示例代码如代码清单38-36所示。
代码清单38-36 定义具体功能
1 | public class Serviced1 implements IServiced { |
功能定义完毕后,我们需要由一个雇工来执行这些功能。简单地说,就是需要有一个执行者,可以把一组功能聚集起来,示例代码如代码清单38-37所示。
代码清单38-37 雇工类
1 | public class Servant { |
在整个雇工模式中,所有具有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。