建造者模式
-
建造者模式:也叫作生成器模式,将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示(Separate the construction of a complex object from its representation so that the same construction process can create different representations)。
-
建造者模式中有4个角色,其通用类图如下:
-
-
Product产品类:通常是实现了模板方法模式,也就是有模板方法和基本方法。通常以抽象类和具体类(类图中省略了抽象类)。参考详细例子中的BenzModel和BMWModel类。
- Builder抽象建造者:规范产品的组建,定义抽象方法,一般由具体的构建子类实现。详细例子中的CarBuilder就属于抽象建造者。
- ConcreteBuilder具体建造者:实现抽象类定义的所有方法,并且返回一个组建好的对象。参见详细例子中的BenBuilder和BMWBuilder。
- Director导演类:负责安排已有模板的顺序,然后传递给Builder开始建造。
- 建造者的通用源码如下:
-
public class Product { private void doSomething(){ //产品的业务处理 } } public abstract class Builder { //设置产品的不同部分,以获得不同的产品 public abstract void setPart(); //建造产品 public abstract Product buildProduct(); } public class ConcreteBuilder extends Builder{ private Product product = new Product(); @Override public void setPart() { // TODO Auto-generated method stub //产品类内部的逻辑处理 } @Override public Product buildProduct() { // TODO Auto-generated method stub return product; } } public class Director { private Builder builder = new ConcreteBuilder(); public Product getProduct(){ builder.setPart(); return builder.buildProduct(); } }
- 详细例子的通用类图和源码如下:
-
public abstract class CarModel { private ArrayList<String> sequence = new ArrayList<String>(); protected abstract void start(); protected abstract void alarm(); protected abstract void stop(); final public void run(){ for(int i = 0; i < sequence.size(); i++){ String actionName = sequence.get(i); if(actionName.equalsIgnoreCase("start")){ this.start(); }else if(actionName.equalsIgnoreCase("stop")){ this.stop(); }else if(actionName.equalsIgnoreCase("alarm")){ this.alarm(); } } } final public void setSequence(ArrayList<String> sequence){ this.sequence = sequence; } } public class BenzModel extends CarModel{ @Override protected void start() { // TODO Auto-generated method stub System.out.println("奔驰车启动"); } @Override protected void alarm() { // TODO Auto-generated method stub System.out.println("奔驰车鸣笛"); } @Override protected void stop() { // TODO Auto-generated method stub System.out.println("奔驰车停止"); } } public class BMWModel extends CarModel{ @Override protected void start() { // TODO Auto-generated method stub System.out.println("宝马车启动"); } @Override protected void alarm() { // TODO Auto-generated method stub System.out.println("宝马车鸣笛"); } @Override protected void stop() { // TODO Auto-generated method stub System.out.println("宝马车停止"); } } public abstract class CarBuilder { protected abstract void setSequence(ArrayList<String> sequence); protected abstract CarModel getCarModel(); } public class BenzBuilder extends CarBuilder{ private BenzModel benz = new BenzModel(); @Override protected void setSequence(ArrayList<String> sequence) { // TODO Auto-generated method stub benz.setSequence(sequence); } @Override protected CarModel getCarModel() { // TODO Auto-generated method stub return this.benz; } } public class BMWBuilder extends CarBuilder{ private BMWModel bmw = new BMWModel(); @Override protected void setSequence(ArrayList<String> sequence) { // TODO Auto-generated method stub bmw.setSequence(sequence); } @Override protected CarModel getCarModel() { // TODO Auto-generated method stub return this.bmw; } } public class Director { private ArrayList<String> sequence = new ArrayList<String>(); private BenzBuilder benz = new BenzBuilder(); private BMWBuilder bmw = new BMWBuilder(); public BenzModel getBenzModel(){ this.sequence.clear(); this.sequence.add("start"); this.sequence.add("stop"); benz.setSequence(sequence); return (BenzModel)benz.getCarModel(); } public BMWModel getBMWModel(){ this.sequence.clear(); this.sequence.add("start"); this.sequence.add("alarm"); this.sequence.add("stop"); this.bmw.setSequence(sequence); return (BMWModel)this.bmw.getCarModel(); } } public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Director director = new Director(); director.getBenzModel().run(); director.getBMWModel().run(); } }
-
建造者模式的优点
- 封装性:使用建造者模式可以使客户端不必知道产品内部组成的细节,如例子中我们不必关系每一个具体的模型内部是如何实现的,产生的对象类型就是CarModel。
- 建造者独立,容易扩展,BenzBuilder和BMWBuilder相互独立,有利于系统扩展。
- 便于控制细节风险,由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。
-
建造者模式的使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果,可以采用建造者模式;
- 多个部件或零件都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式;
- 产品类非常复杂,或者产品类中的顺序不同产生不同的效能,则可以使用建造者模式;
- 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身就违反了设计的最初目标。
-
最佳实践
本文中列举的实例,通过将建造者模式和模板方法模式进行结合,就是一个对建造者模式很好的扩展实践。