链接地址:http://www.xx566.com/detail/108.html
一直以来,在程序员这个领域,每到找工作的季节,我们总能在企业招聘的简章中看到:熟练使用常用设计模式、精通设计模式之类的字眼,每次看到这些信息,心 里总会一咯噔,似乎设计模式离自己好远,这种高大上的东西自己怎么可能熟练使用甚至精通,其实不然,在平常的工作和学习中,我们可能已经使用到了多种设计 模式,只是没有对其进行详细的剖析和理解,所以总会有些茫然,现在,我们就来一点点开始设计模式的学习和揭秘。
最近在重读EffectiveJava的时候,看到了建造者模式(Builder Pattern),决定先从它开始学习。建造者模式的英文定义为:Separate the construction of a complex object from its representation so that the same construction process can create different representations。意思就是把一个复杂对象的构造和它的表示分开,这样同样的构造过程就可以创建不同的表示。
翻译过来有点不太懂,举个例子:就是建房子时候,把建房子的过程(设计图纸啊什么的)和房子的组件(铁门啊铁窗铁锁链)分开,目的就是为了解耦合(又一个高大上的词汇),下面举一个现实中的例子,可能更好理解,本篇的代码也是对其的实现。
我 (HouseOwner)现在要建造一所房子(House),于是我找了个包工头(WorkerLeader),工头手下有两个工人(WorkerA 和 WorkerB),我们签订了合同,他负责指挥两个工人共建造两个房间(RoomA 和 RoomB),同时完成后负责验收和交付房屋,工头指挥WorkerA建造RoomA,指挥WorkerB建造RoomB。
下面我们把上面的故事通过代码来实现,首先是房屋对象,有roomA和roomB,房屋对象由于是唯一的,这里使用了单例(更多单例请参阅:三种方式实现类的单例),代码如下:
package javase.builder; /** * 房屋本身 * * @Package javase.builder * @ClassName: House * @author Realfighter * @date 2014-7-24 下午01:58:12 */ public enum House { INSTANCE; boolean roomA;// A屋 boolean roomB;// B屋 /** * 建造RoomA * * @Title: setRoomA * @author Realfighter * @date 2014-7-24 下午02:01:28 void */ public void setRoomA(boolean roomA) { this.roomA = roomA; } /** * 建造RoomB * * @Title: setRoomB * @author Realfighter * @date 2014-7-24 下午02:02:14 void */ public void setRoomB(boolean roomB) { this.roomB = roomB; } public boolean getRoomA() { return roomA; } public boolean getRoomB() { return roomB; } }
其次,由于WorkerA和WorkerB的工作相同,但是工作内容不同,我们首先抽象出一个工作接口,如下:
package javase.builder; /** * 工作接口 * * @Package javase.builder * @ClassName: Worker * @author Realfighter * @date 2014-7-24 下午02:04:53 */ public interface Worker { /** * 建造Room * * @Title: buildRoom * @author Realfighter * @date 2014-7-24 下午02:04:42 void */ public void buildRoom(); /** * 交付Room * * @Title: deliverRoom * @author Realfighter * @date 2014-7-24 下午02:32:32 * @return boolean */ public boolean deliverRoom(); }
然后需要寻找一个合适的包工头对象帮助建造房屋,包工头负责命令工人和交付房屋,代码如下:
package javase.builder; /** * 包工头 * * @Package javase.builder * @ClassName: Leader * @author Realfighter * @date 2014-7-24 下午01:56:24 */ public class Leader { /** * 命令工人 * * @Title: order * @author Realfighter * @date 2014-7-24 下午02:51:27 * @param worker * void */ public void order(Worker worker) { worker.buildRoom(); worker.deliverRoom(); } /** * 验收交付房屋 * * @Title: deliverHouse * @author Realfighter * @date 2014-7-24 下午02:51:36 * @return House */ public House deliverHouse() { if (House.INSTANCE.getRoomA() && House.INSTANCE.getRoomB()) { return House.INSTANCE; } return null; } }
之后包工头就需要寻找两个工人分别开始建造了,工人负责建造room和交付room,代码如下:
package javase.builder; /** * 工人实例A * * @Package javase.builder * @ClassName: WorkerA * @author Realfighter * @date 2014-7-24 下午01:58:24 */ public class WorkerA implements Worker { /** * 建造RoomA * * @Title: buildRoomA * @author Realfighter * @date 2014-7-24 下午02:11:04 */ public void buildRoom() { House.INSTANCE.setRoomA(true); } /** * 交付RoomA * * @Title: deliverRoomA * @author Realfighter * @date 2014-7-24 下午02:11:12 * @return */ public boolean deliverRoom() { return House.INSTANCE.roomA; } }
package javase.builder; /** * 工人实例B * * @Package javase.builder * @ClassName: WorkerB * @author Realfighter * @date 2014-7-24 下午01:58:24 */ public class WorkerB implements Worker { /** * 建造RoomB * * @Title: buildRoom * @author Realfighter * @date 2014-7-24 下午02:11:04 */ public void buildRoom() { House.INSTANCE.setRoomB(true); } /** * 交付RoomB * * @Title: deliverRoom * @author Realfighter * @date 2014-7-24 下午02:11:12 * @return */ public boolean deliverRoom() { return House.INSTANCE.roomB; } }
时间一分一秒的过去,终于有一天,房屋主人来找包工头了,代码如下:
package javase.builder; /** * 房屋主人,负责接收房子 * * @Package javase.builder * @ClassName: HouseOwner * @author Realfighter * @date 2014-7-24 下午01:51:44 */ public class HouseOwner { /** * @Title: main * @author Realfighter * @date 2014-7-24 下午01:51:34 * @param args * void */ public static void main(String[] args) { // 找一个包工头 Leader leader = new Leader(); // 包工头找两个工人 Worker workerA = new WorkerA(); Worker workerB = new WorkerB(); // 包工头指挥两个工人 leader.order(workerA); leader.order(workerB); // 包工头将验收后的房屋交付屋主人 leader.deliverHouse(); } }
到此,建造者模式已经实现完成,有没有很简单,最后我们来看一下此模式的通用类图:
不难发现,本例中的Leader类似于上图中的Director,Worker抽象类类似于Builder接口,House则类似于 Product,WorkerA和WorkerB都是ConcreteBuilder,现在回头再看,设计模式其实并不复杂,只要做到了理解,很快就能熟 练应用了。