在讲述这个模式之前,我们先看一个案例:建造小人(只需要建造的小人有头、身子、四肢即可)
public class DrawPeople extends JFrame { //DrawSee构造方法 public DrawPeople() { setBounds(0, 0, 500, 500);//窗体起始位置 setVisible(true);//窗体是否可见 setLayout(null); //窗体布局 setResizable(false);//窗体是否可进行拖动设置大小 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } // 获取专门用于在窗口界面上绘图的对象 Graphics jg = this.getGraphics(); // 绘制区域 paintComponents(jg); } //画一个人 public void paintComponents(Graphics g) { try { g.drawArc(150, 50, 30, 30, 0, 360);//画头 g.drawArc(145, 80, 40, 50, 0, 360);//画身子 g.drawLine(150, 80, 130, 130); g.drawLine(180, 80, 200, 130); g.drawLine(160, 130, 145, 180); g.drawLine(170, 130, 185, 180); } catch (Exception e) { e.printStackTrace(); } } } 测试方法 public class Test { public static void main(String[] args) { new DrawPeople(); } }
绘制结果如下图所示
那我现在需要绘制一个比较瘦的人,怎么办?
正常程序员都会想:这还不简单,把这个类复制一份,把绘制参数改下不就行了。
那万一复制的时候少复制了一行,让小人缺胳膊少腿怎么办?
这对一个人来说可是巨大的损失,谁都不想让身体残缺不全。这个问题怎么解决呢?
下面介绍建造者模式:http://www.runoob.com/design-pattern/builder-pattern.html
将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
那怎么用建造者模式呢?
以画小人为例,我们需要画头、身体、左手、右手、左脚、右脚,所以我们先定义一个抽象的建造人的类,把这个过程稳定住,不让任何人遗忘当中的任何一步。
public interface PersonBuilder { public abstract void buildHead(); public abstract void buildBody(); public abstract void buildArmLeft(); public abstract void buildArmRight(); public abstract void buildLegLeft(); public abstract void buildLegRight(); }
然后我们需要建造一个胖的人,就让这个胖子类取继承这个抽象类,那就必须去重写这些抽象方法了,否则编译器也不让你通过。
public class PersonFatBuilder extends JFrame implements PersonBuilder{ private Graphics g; public PersonFatBuilder() { setBounds(0, 0, 500, 500);//窗体起始位置 setVisible(true);//窗体是否可见 setLayout(null); //窗体布局 setResizable(false);//窗体是否可进行拖动设置大小 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } // 获取专门用于在窗口界面上绘图的对象 this.g = this.getGraphics(); // 绘制游戏区域 paintComponents(this.g); } @Override public void buildHead() { g.drawArc(150, 50, 30, 30, 0, 360);//画头 } @Override public void buildBody() { g.drawArc(145, 80, 40, 50, 0, 360);//画身子 } @Override public void buildArmLeft() { g.drawLine(150, 80, 130, 130); } @Override public void buildArmRight() { g.drawLine(180, 80, 200, 130); } @Override public void buildLegLeft() { g.drawLine(160, 130, 145, 180); } @Override public void buildLegRight() { g.drawLine(170, 130, 185, 180); } }
瘦子类也是用类似的代码去实现这个类就可以了。
但现在只是保证胖子类拥有了头身手脚方法,但依然无法保证这些方法一定会被调用,怎么办?
我们还缺少建造者模式中一个重要的类,指挥者(Director),用它来控制建造过程,也用它来隔离用户与建造过程的关联。
public class PersonDirector { private PersonBuilder pb; //用户告诉指挥者,我需要什么样的小人 public PersonDirector(PersonBuilder pb){ this.pb = pb; } //根据用户的选择建造小人 public void createPerson(){ pb.buildHead(); pb.buildBody(); pb.buildArmLeft(); pb.buildArmRight(); pb.buildLegLeft(); pb.buildLegRight(); } }
测试方法
public class Test { public static void main(String[] args) { PersonFatBuilder pfb = new PersonFatBuilder(); PersonDirector pd = new PersonDirector(pfb); pd.createPerson(); } }
PersonDirector类的目的就是根据用户的选择来一步步建造小人,而建造的过程在指挥者这里完成,用户就不需要知道了,而且,每个建造过程都是一定要做的,保证了建造流程的正确性,这样,缺胳膊少腿的情况就不会出现了。
做个比喻:Builder像是图纸,PersonFatBuilder是具体的施工人员,PersonDirector就是个监工,保证施工过程正确有序。