建造者模式
2015-12-20 17:43
162 查看
建造者模式
标签 : 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的构造过程:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:mybatis/mapper/*DAO.xml"/> <property name="typeAliases" value="com.feiqing.domain.User"/> <property name="configLocation" value="classpath:mybatis/mybatis-configuration.xml"/> </bean>
小结
由于构建和装配的解耦, 不同的构建器, 相同的装配过程, 可以产生不同的产品,实现了更好的复用.因此常用于创建一些复杂的对象, 这些对象内部构建间的建造顺序通常是稳定的, 但内部的构建通常面临着复杂的变化. 如:
StringBuilder的
append();
JDBC的
PreparedStatement;
JDOM的
DomBuilder、
SAXBuilder;
MyBatis的
SqlSessionFactoryBuilder.
参考:
大话设计模式
《JAVA与模式》之建造模式
高淇讲设计模式
SqlSessionFactory实例的产生过程
相关文章推荐
- LINUX 下LAMP之yum方法部署环境
- ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别
- WordPress设置圆形旋转头像的方法
- Repository模式
- poj3258River Hopscotch【二分】
- java学习笔记-foreach与iterator
- WordPress让文本小工具支持简码
- 修改WordPress后台登录地址,提高安全性
- 卡特兰数
- 奇虎360退出美国股市 12月再曝拟私有化
- Linux id 命令
- WordPress用键盘左右方向键来查看上一篇和下一篇文章
- hdoj--1237--简单计算器(栈模拟)
- 浙江理工校赛
- 嵌入式ARM 中断 IRQ代码编写 基于S5pv210
- PHP的异步并行网络扩展swoole如何使用
- Mysql高并发优化
- git subproject commit xxxxxxxxxxxxxxxxxxxxx -dirty
- hdoj--1237--简单计算器(栈模拟)
- WordPress后台添加友情链接管理功能