建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
概述
当系统准备为用户提供一个内部结构复杂的对象时,就可以使用生成器模式,使用该模式可以逐步地构造对象,使得对象的创建更具弹性。生成器模式的关键是将一个包含有多个组件对象的创建分成若干个步骤,并将这些步骤封装在一个称作生成器的接口中。
适用性
1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2.当构造过程必须允许被构造的对象有不同的表示时。
参与者
1.Builder 为创建一个Product对象的各个部件指定抽象接口。
2.ConcreteBuilder 实现Builder的接口以构造和装配该产品的各个部件。 定义并明确它所创建的表示。 提供一个检索产品的接口。
3.Director 构造一个使用Builder接口的对象。
4.Product 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
建造者模式的结构与使用
模式的结构中包括四种角色:
•产品(Product)
•抽象生成器(Builder)
•具体生成器(ConcreteBuilder)
•指挥者(Director)
模式的UML类图
实战部分
【例1】:创建含有按钮、标签和文本框组件的容器。不同用户对容器有不同的要求,比如某些用户希望容器中只含有 按钮和标签,某些用户希望容器只含有按钮和文本框等。另外用户对组件在容器中的顺序位置也有不同的要求,比如某些用户要求组件在容器中从左至右的排列顺序 是按钮、标签、文本框,而某些用户要求从左至右的排序时标签、文本框、按钮。
模式的结构的描述与使用
1.产品(Product): PanelProduct.java
import javax.swing.*; public class PanelProduct extends JPanel{ JButton button; JLabel label; JTextField textField; }
2.抽象生成器(Builder): Builer.java
import.javax.swing.*; public interface Builder{ public abstract void buildButton(); public abstract void buildLabel(); public abstract void buildTextField(); public abstract JPanel getPanel(); }
3.具体生成器(ConcreteBuilder)_1 : ConcreteBuilderOne.java
import javax.swing.*; public class ConcreteBuilderOne implements Builder{ private PanelProduct panel; ConcreteBuilderOne(){ panel=new PanelProduct(); } public void buildButton(){ panel.button=new JButton("按钮"); } public void buildLabel(){ panel.label=new JLabel("标签"); } public void buildTextField(){ } public JPanel getPanel(){ panel.add(panel.button); panel.add(panel.label); return panel; } }
3.具体生成器(ConcreteBuilder)_2 : ConcreteBuilderTwo.java
import javax.swing.*; public class ConcreteBuilderTwo implements Builder{ private PanelProduct panel; ConcreteBuilderTwo(){ panel=new PanelProduct(); } public void buildButton(){ panel.button=new JButton("button"); } public void buildLabel(){ } public void buildTextField(){ panel.textField=new JTextField("textField"); } public JPanel getPanel(){ panel.add(panel.textField); panel.add(panel.button); return panel; } }
4.指挥者(Director): Director.java
import javax.swing.*; public class Director{ private Builder builder; Director(Builder builder){ this.builder=builder; } public JPanel constructProduct(){ builder.buildButton(); builder.buildLabel(); builder.buildTextField(); JPanel product=builder.getPanel(); return product; } }
5.应用 Application.java
import javax.swing.*; public class Application{ public static void main(String args[]){ Builder builder=new ConcreteBuilderOne(); Director director=new Director(builder); JPanel panel=director.constructProduct(); JFrame frameOne=new JFrame(); frameOne.add(panel); frameOne.setBounds(12,12,200,120); frameOne.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frameOne.setVisible(true); builder=new ConcreteBuilderTwo(); director=new Director(builder); panel=director.constructProduct(); JFrame frameTwo=new JFrame(); frameTwo.add(panel); frameTwo.setBounds(212,12,200,120); frameTwo.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frameTwo.setVisible(true); } }
【例2】:构建一个男人的类,使得构建和表示分离
类图如下所示:
Builder
public interface PersonBuilder { void buildHead(); void buildBody(); void buildFoot(); Person buildPerson(); }
ConcreteBuilder
public class ManBuilder implements PersonBuilder { Person person; public ManBuilder() { person = new Man(); } @Override public void buildHead() { person.setHead("建造男人的头"); } @Override public void buildBody() { person.setBody("建造男人的身体"); } @Override public void buildFoot() { person.setFoot("建造男人的脚"); } @Override public Person buildPerson() { return person; } }
Director
public class PersonDirector { public Person constructPerson(PersonBuilder pb) { pb.buildHead(); pb.buildBody(); pb.buildFoot(); return pb.buildPerson(); } }
Product
public class Person { private String head; private String body; private String foot; public String getHead() { return head; } public void setHead(String head) { this.head = head; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getFoot() { return foot; } public void setFoot(String foot) { this.foot = foot; } } public class Man extends Person { }
Test
public class Test { public static void main(String[] args) { PersonDirector pd = new PersonDirector(); Person person = pd.constructPerson(new ManBuilder()); System.out.println(person.getBody()); System.out.println(person.getFoot()); System.out.println(person.getHead()); } }
生成器模式的优点
•生成器模式将对象的构造过程封装在具体生成器中,用户使用不同的具体生成器就可以得到该对象的不同表示。
•可以更加精细有效地控制对象的构造过程。生成器将对象的构造过程分解成若干步骤,这就使得程序可以更加精细,有效地控制整个对象的构造。
•生成器模式将对象的构造过程与创建该对象类解耦,使得对象的创建更加灵活有弹性。
•当增加新的具体生成器时,不必修改指挥者的代码,即该模式满足开-闭原则。