设计模式——建造者模式 2019-09-27

引言

之前在家看两个小外甥玩轨道车,拆开包装,一堆小零件,兄弟两一个拼桥梁、弯道、路标,一个装车、搭立交、组装上下坡。不一会儿轨道就全拼好了,两兄弟用代表自己的车子在轨道上追逐,玩的很开心。我看了下轨道车包装,根据使用零件多少不同,组拼顺序不同,摆放不同可以创建不同的轨道和街道,有椭圆形的,上下立交式的,单层的……

忽然想到用程序来表述玩轨道车的流程,如果用类图描述轨道车的玩法,可以简单表示为:

分为两个部分:

红色为轨道车的各个部件,Road规定了轨道车可以有 坡度、弯道、桥梁、路标、汽车、立交这几个部分;

蓝色部分为建造不同的轨道,环形轨道(AnnularBuilder)和立交轨道(InterchangeBuilder)。

Road为模板方法的变形形式,轨定轨道车的部件和各个部件的组装顺序,实现如下:

public abstract class Road { //坡度 protected abstract void slope(); //弯道 protected abstract void curve(); //桥梁 protected abstract void bridge(); //路标 protected abstract void guide(); //汽车 protected abstract void car(); //立交 protected abstract void interchange(); private List<String> list = new ArrayList<>(); final public void create() throws InvocationTargetException, IllegalAccessException { Method[] methods = this.getClass().getDeclaredMethods(); for (String method : list) { for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(method)) { methods[i].invoke(this, null); } } } } final public void setList(List<String> methods){ this.list = methods; }}

组装轨道车的部件实现方法:

public class TrackRoad extends Road { //坡度 @Override protected void slope() { System.out.println("建造上下坡……"); } //弯道 @Override protected void curve() { System.out.println("建造曲线车道……"); } //桥梁 @Override protected void bridge() { System.out.println("建造桥梁……"); } //路标 @Override protected void guide() { System.out.println("放置公路路标……"); } //汽车 @Override protected void car() { System.out.println("建造汽车……"); } //立交 @Override protected void interchange() { System.out.println("建造立交……"); }}

抽象创建轨道车类Builder定义了轨道车的组装部件和获取组装的轨道车

public abstract class Builder { /** * 不同部件的创建 */ public abstract void setPart(List<String> methods); /** * 建造轨道 */ public abstract TrackRoad buildRoad() throws InvocationTargetException, IllegalAccessException;}

具体轨道车玩法建造类(立交轨道车):

public class InterchangeBuilder extends Builder { private TrackRoad road = new TrackRoad(); @Override public void setPart(List<String> methods) { this.road.setList(methods); } @Override public TrackRoad buildRoad() { return this.road; }}

如果想创建一个立交轨道,可以这么创建:

InterchangeBuilder interchangeBuilder = new InterchangeBuilder();List<String> interMethods = new ArrayList<>();interMethods.add("slope");interMethods.add("bridge");interMethods.add("guide");interMethods.add("interchange");interMethods.add("car");interchangeBuilder.setPart(interMethods);interchangeBuilder.buildRoad().create();

建造上下坡……建造桥梁……放置公路路标……建造立交……建造汽车……

引入导演类

坡度、弯道、桥梁、路标、汽车、立交不同组装方式可以构造不同的轨道,为了方便支持的很多不同的轨道,可以增加个导演类(Director)。

导演类封装立交轨道和环形轨道的实现,对外提供直接获取的方法:

public class Director { private List<String> steps = new ArrayList<>(); private InterchangeBuilder interchangeBuilder = new InterchangeBuilder(); private AnnularBuilder annularBuilder = new AnnularBuilder(); public TrackRoad getInterchangeBuilder(){ System.out.println("===========================建造立交车道==========================="); this.steps.clear(); this.steps.add("slope"); this.steps.add("bridge"); this.steps.add("guide"); this.steps.add("interchange"); this.steps.add("car"); this.interchangeBuilder.setPart(this.steps); return this.interchangeBuilder.buildRoad(); } public TrackRoad getAnnularBuilder(){ System.out.println("===========================建造曲线车道===========================");     this.steps.clear(); this.steps.add("curve"); this.steps.add("bridge"); this.steps.add("guide"); this.steps.add("car"); this.annularBuilder.setPart(this.steps); return this.annularBuilder.buildRoad(); }}

客户端不关注如何实现,只需要拿来即用(可玩):

public void testDerictor() throws InvocationTargetException, IllegalAccessException { Director director = new Director(); director.getAnnularBuilder().create(); director.getInterchangeBuilder().create(); }

其实这就是建造者模式,由导演类决定如何构建具体的对象(产品)。

建造者模式

定义

  将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

通用类图

四要素

建造者模式中有以下4个角色:

Product产品类

通常是实现模板方法模式(有模板方法和基本方法的类),例子里的TrackRoad(轨道)就属于产品类。

Builder抽象建造者

规范产品的组建,一般是抽象类,约定功能由子类去实现具体的建造方法,对应例子里的Builder。

ConcreteBuilder具体建造者

实现抽象建造者的所有方法。例子里的InterchangeBuilder和AnnularBuilder就是具体轨道的建造者。

Director导演类

封装具体建造者,提供简单易用的构建产品类方法。

总结

优点

封装性:将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。

建造者独立,容易扩展:增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。

缺点

建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

使用场景

相同的方法,不同的执行顺序,产生不同的事件结果时多个部件或零件都可以装配到一个对象中,但是产生的运行结果又不相同时产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能, 1, 0, 9);

Copyright © 2019 博猫游戏登录 All Rights Reserved
马力
地址:内蒙古自治省包头市 青年11街坊
全国统一热线:15231099844