标签 : Java与设计模式
建造者模式: 又称生成器模式, 能够将一个产品的内部表象与产品的生成过程切割开来, 从而能够使一个建造过程生成具有不同的内部表象的产品(将一个复杂对象的构建与它的表示分离, 使得同样的构建过程能够创建不同的表示). 这样用户仅仅需指定须要建造的类型就能够得到详细产品,而不须要了解详细的建造过程和细节.
- 与抽象工厂的差别: 在建造者模式中,角色分指导者(Director)与建造者(Builder): 用户联系指导者, 指导者指挥建造者, 最后得到产品. 建造者模式能够强制实行一种分步骤进行的建造过程.
实现
需求: 模仿宇宙飞船的建造过程 如果宇宙飞船有非常多零部件: 引擎、轨道舱、逃逸塔、各种小零件... 因此宇宙飞船的建造/装配非常复杂(须要非常好的生产/装配技术),而建造者模式能够将部件的建造与装配分开:
产品与部件
产品
AirShip
由多个零部件(Engine
/EscapeTower
/OrbitalModule
)组成:
/** * 目标对象 - 宇宙飞船 * (代表复杂对象, 拥有复杂的建造过程) * Created by jifang on 15/12/8. */public class AirShip { private Engine engine; private EscapeTower escapeTower; private OrbitalModule orbitalModule; public Engine getEngine() { return engine; } public void setEngine(Engine engine) { this.engine = engine; } public EscapeTower getEscapeTower() { return escapeTower; } public void setEscapeTower(EscapeTower escapeTower) { this.escapeTower = escapeTower; } public OrbitalModule getOrbitalModule() { return orbitalModule; } public void setOrbitalModule(OrbitalModule orbitalModule) { this.orbitalModule = orbitalModule; } @Override public String toString() { return "AirShip{" + "engine=" + engine + ", escapeTower=" + escapeTower + ", orbitalModule=" + orbitalModule + '}'; }}class Engine { private String description; public Engine(String description) { this.description = description; } @Override public String toString() { return "Engine{" + "description='" + description + '\'' + '}'; }}class EscapeTower { private String description; public EscapeTower(String description) { this.description = description; } @Override public String toString() { return "EscapeTower{" + "description='" + description + '\'' + '}'; }}class OrbitalModule { private String description; public OrbitalModule(String description) { this.description = description; } @Override public String toString() { return "OrbitalModule{" + "description='" + description + '\'' + '}'; }}
建造者(Builder)
Builder(
AirShipBuilder
)是为创建一个Product对象的各个部件指定的抽象接口, ConcreteBuilder(LowerAirShipBuilder
/HigherAirShipBuilder
)是详细的建造者, 实现Builder接口, 构造和装配各个部件.
/** * @author jifang * @since 16/8/17 下午2:13. */public interface AirShipBuilder { void builtEngine(); void builtEscapeTower(); void builtOrbitalModule(); AirShip getResult();}
生产低端飞船, 须要LowerAirShipBuilder
; 生产高端飞船, 就须要HigherAirShipBuilder
:
class LowerAirShipBuilder implements AirShipBuilder { private AirShip airShip = new AirShip(); @Override public void builtEngine() { System.out.println("\t\t构造低端引擎"); airShip.setEngine(new Engine("低端 - 引擎")); } @Override public void builtEscapeTower() { System.out.println("\t\t构造低端逃逸塔"); airShip.setEscapeTower(new EscapeTower("低端 - 逃逸塔")); } @Override public void builtOrbitalModule() { System.out.println("\t\t构造低端轨道舱"); airShip.setOrbitalModule(new OrbitalModule("低端 - 轨道舱")); } @Override public AirShip getResult() { return airShip; }}class HigherAirShipBuilder implements AirShipBuilder { private AirShip airShip = new AirShip(); @Override public void builtEngine() { System.out.println("\t\t构造高端引擎"); airShip.setEngine(new Engine("高端 - 引擎")); } @Override public void builtEscapeTower() { System.out.println("\t\t构造高端逃逸塔"); airShip.setEscapeTower(new EscapeTower("高端 - 逃逸塔")); } @Override public void builtOrbitalModule() { System.out.println("\t\t构造高端轨道舱"); airShip.setOrbitalModule(new OrbitalModule("高端 - 轨道舱")); } @Override public AirShip getResult() { return airShip; }}
指挥者(Director)
使用Director(
AirShipDirector
)控制建造过程, 也用它来隔离用户与建造过程的关联:
/** * @author jifang * @since 16/8/17 下午2:15. */public class AirShipDirector { /** * 确定一种稳定的构造过程 * * @param builder */ public static void construct(AirShipBuilder builder) { builder.builtEngine(); builder.builtEscapeTower(); builder.builtOrbitalModule(); }}
Client
全然不需知道详细的创建/装配过程, 仅仅需指定Builder:
public class Client { @Test public void client() { AirShipBuilder lowBuilder = new LowerAirShipBuilder(); // 构造低端飞船 AirShipDirector.construct(lowBuilder); AirShip lowShip = lowBuilder.getResult(); System.out.println(lowShip); AirShipBuilder highBuilder = new HigherAirShipBuilder(); // 同样的构造过程, 不同的Builder, 能够构造出不同的飞船 AirShipDirector.construct(highBuilder); AirShip highShip = highBuilder.getResult(); System.out.println(highShip); }}
实例-MyBatis中的建造者模式
MyBatis的
SqlSessionFactoryBuilder
是对SqlSessionFactory
建造过程的简单封装,他对建造者模式做了简化处理(仅仅有Builder
而无Director
),以减小编程复杂度:
/** * @author Clinton Begin */public class SqlSessionFactoryBuilder { public SqlSessionFactory build(Reader reader) { return build(reader, null, null); } public SqlSessionFactory build(Reader reader, String environment) { return build(reader, environment, null); } public SqlSessionFactory build(Reader reader, Properties properties) { return build(reader, null, properties); } public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); } public SqlSessionFactory build(InputStream inputStream, String environment) { return build(inputStream, environment, null); } public SqlSessionFactory build(InputStream inputStream, Properties properties) { return build(inputStream, null, properties); } public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }}
因为SqlSessionFactory
创建的SqlSession
须要支持非常多操作(如selectOne()
、selectList()
、update()
等), 因此SqlSessionFactory
的构造过程是非常复杂的(可參考SqlSessionManager
、DefaultSqlSessionFactory
实现),因此使用SqlSessionFactoryBuilder
作为Builder简化其构造过程,而且为其设置配置文件(mybatis-configuration.xml)作为Director来指导Builder的构造过程:
详细可參考博客:
小结
- 因为构建和装配的解耦, 不同的构建器, 同样的装配过程, 能够产生不同的产品,实现了更好的复用.因此经常使用于创建一些复杂的对象, 这些对象内部构建间的建造顺序一般是稳定的, 但内部的构建通常面临着复杂的变化. 如:
StringBuilder
的append()
;- JDBC的
PreparedStatement
;- JDOM的
DomBuilder
、SAXBuilder
;- MyBatis的
SqlSessionFactoryBuilder
.
參考: