创建型模式之--创建者模式
Posted ~无关风月~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建型模式之--创建者模式相关的知识,希望对你有一定的参考价值。
1、变化是永恒的
制作奔驰、宝马的车辆模型,汽车的启动、停止、喇叭声音、引擎声音 先后顺序由客户控制。
每个车都是一个产品。
在CarModel中我们定义了一个setSequence方法, 车辆模型的这几个动作要如何排布, 是在这个ArrayList中定义的。 然后run()方法根据sequence定义的顺序完成指定的顺序动作。
车辆模型抽象类
public abstract class CarModel
/**
* 汽车启动顺序
*/
private List<String> sequence = new ArrayList<>();
/**
* 汽车启动
*/
protected abstract void start() ;
/**
* 汽车停止
*/
protected abstract void stop();
/**
* 汽车响铃
*/
protected abstract void alarm();
/**
* 汽车引擎响
*/
protected abstract void engineBoom();
/**
* 汽车启动
*/
final public void run()
for (String funcName : this.sequence)
if (funcName.equalsIgnoreCase("start"))
this.start();
else if (funcName.equalsIgnoreCase("stop"))
this.stop();
else if (funcName.equalsIgnoreCase("alarm"))
this.alarm();
else if (funcName.equalsIgnoreCase("enginBoom"))
this.engineBoom();
/**
* 设置启动顺序
* @param sequence
*/
public void setSequence(List<String> sequence)
this.sequence = sequence;
奔驰模型
public class BenzModel extends CarModel
/**
* 汽车启动
*/
@Override
protected void start()
System.out.println("奔驰车开跑");
/**
* 汽车停止
*/
@Override
protected void stop()
System.out.println("奔驰车停车");
/**
* 汽车响铃
*/
@Override
protected void alarm()
System.out.println("奔驰车响喇叭");
/**
* 汽车引擎响
*/
@Override
protected void engineBoom()
System.out.println("奔驰车引擎声");
抽象汽车组装者
public abstract class CarBuilder
/**
* 设置顺序
* @param sequence
*/
public abstract void setSequence(List<String> sequence);
/**
* 得到模型
* @return
*/
public abstract CarModel getCarModel();
奔驰车组装者
public class BMWBuilder extends CarBuilder
private BMWModel bmwModel = new BMWModel();
/**
* 设置顺序
*
* @param sequence
*/
@Override
public void setSequence(List<String> sequence)
this.bmwModel.setSequence(sequence);
/**
* 得到模型
*
* @return
*/
@Override
public CarModel getCarModel()
return this.bmwModel;
导演类
负责按照指定顺序生产模型
public class Director
private List<String> sequence = new ArrayList<>();
private BenzBuilder benzBuilder = new BenzBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder();
public BenzModel getABenzModel()
this.sequence.clear();
this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(this.sequence);
return (BenzModel)this.benzBuilder.getCarModel();
public BMWModel getCBMWModel()
this.sequence.clear();
this.sequence.add("alarm");
this.sequence.add("start");
this.sequence.add("stop");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel)this.bmwBuilder.getCarModel();
场景类
生产A 类型的奔驰车100万辆,C类型的宝马车200万辆
public class Client
public static void main(String[] args)
Director director = new Director();
for (int i = 0; i < 100; i++)
director.getABenzModel().run();
for (int i = 0; i < 200; i++)
director.getCBMWModel().run();
2、建造者模式定义
建造者模式(Builder Pattern)也叫做生成器模式。
Separate the construction of a complex object from its representation so that the same construction precess can create different representaions.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
4个角色:
-
Product产品类
通常是实现了模板方法模式, 也就是有模板方法和基本方法。 -
Builder抽象创建者
规范产品的组建,一般是由子类实现。 -
ConcreteBuilder具体创建者
实现抽象类定义的所有方法, 并且返回一个组建好的对象。 例子中的BenzBuilder和BMWBuilder就属于具体建造者。 -
Director导演类
负责安排已有模块的顺序, 然后告诉Builder开始建造, 在上面的例子中就是我们的老大, ××公司找到老大, 说我要这个或那个类型的车辆模型, 然后老大就把命令传递给我, 我和我的团队就开始拼命地建造, 于是一个项目建设完毕了。
通用源代码
Product类
通常它是一个组合或继承(如模板方法模式) 产生的类
public class Product
public void doSomething()
//独立业务处理
抽象建造者
public abstract class Builder
//设置产品的不同部分, 以获得不同的产品
public abstract void setPart();
//建造产品
public abstract Product buildProduct();
setPart方法是零件的配置, 什么是零件? 其他的对象, 获得一个不同零件, 或者不同的装配顺序就可能产生不同的产品。
具体建造者
public class ConcreteProduct extends Builder
private Product product = new Product();
//设置产品零件
public void setPart()
/*
* 产品类内的逻辑处理
*/
//组建一个产品
public Product buildProduct()
return product;
注意:如果有多个产品类就有几个具体的建造者, 而且这多个产品类具有相同接口或抽象类。
导演类
public class Director
private Builder builder = new ConcreteProduct();
//构建不同的产品
public Product getAProduct()
builder.setPart();
/*
* 设置不同的零件, 产生不同的产品
*/
return builder.buildProduct();
3、建造者模式的应用
建造者模式的优点
封装性
使用建造者模式可以使客户端不必知道产品内部组成的细节, 如例子中我们就不需要关心每一个具体的模型内部是如何实现的, 产生的对象类型就是CarModel。
建造者独立, 容易扩展
BenzBuilder和BMWBuilder是相互独立的, 对系统的扩展非常有利。
便于控制细节风险
由于具体的建造者是独立的, 因此可以对建造过程逐步细化, 而不对其他的模块产生任何影响。
建造者模式的使用场景
- 相同的方法, 不同的执行顺序, 产生不同的事件结果时, 可以采用建造者模式。
- 多个部件或零件,都可以装配到一个对象中, 但是产生的运行结果又不相同时, 则可以使用该模式。
- 产品类非常复杂, 或者产品类中的调用顺序不同产生了不同的效能, 这个时候使用建造者模式非常合适。
- 在对象创建过程中会使用到系统中的一些其他对象, 这些对象在产品对象的创建过程中不易得到时, 也可以采用建造者模式封装该对象的创建过程。 该种场景只能是一个补偿方法, 因为一个对象不容易获得, 而在设计阶段竟然没有发觉, 而要通过创建者模式柔化创建过程, 本身已经违反设计的最初目标。
建造者模式的注意事项
建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大不同的地方, 虽然同为创建类模式, 但是注重点不同。
建造者模式最主要的功能是基本方法的调用顺序安排, 也就是这些基本方法已经实现了, 通俗地说就是零件的装配, 顺序不同产生的对象也不同; 而工厂方法则重点是创建, 创建零件是它的主要职责, 组装顺序则不是它关心的。
建造者模式中还有一个角色没有说明, 就是零件, 建造者怎么去建造一个对象? 是零件的组装, 组装顺序不同对象效能也不同, 这才是建造者模式要表达的核心意义, 而怎么才能更好地达到这种效果呢? 引入模板方法模式是一个非常简单而有效的办法。
Builder模式
- 创建一个名为ThisClassBuilder的内部静态类,并具有和实体类形同的属性(称为构建器)。
- 在构建器中:对于目标类中的所有的属性和未初始化的final字段,都会在构建器中创建对应属性。
- 在构建器中:创建一个无参的default构造函数。
- 在构建器中:对于实体类中的每个参数,都会对应创建类似于setter的方法,只不过方法名与该参数名相同。 并且返回值是构建器本身(便于链式调用)。
- 在构建器中:一个build()方法,调用此方法,就会根据设置的值进行创建实体对象。
- 在构建器中:同时也会生成一个toString()方法。
- 在实体类中:会创建一个builder()方法,它的目的是用来创建构建器。
@Builder
public class User
private final Integer code = 200;
private String username;
private String password;
// 编译后:
public class User
private String username;
private String password;
User(String username, String password)
this.username = username; this.password = password;
public static User.UserBuilder builder()
return new User.UserBuilder();
public static class UserBuilder
private String username;
private String password;
UserBuilder()
public User.UserBuilder username(String username)
this.username = username;
return this;
public User.UserBuilder password(String password)
this.password = password;
return this;
public User build()
return new User(this.username, this.password);
public String toString()
return "User.UserBuilder(username=" + this.username + ", password=" + this.password + ")";
将对象的创建与表示相分离,用户不用关心它的内在是什么样的。只需要知道传给他什么参数。在一些有很多参数的产品类中使用该模式,可以避免我们在构造函数中传入大量的默认参数来赋值的尴尬。
如果我们给 User 类每一个参数都设置一个set方法,这样会增加Person类的功能和职责。违反了单一原则,不利于后期的维护。Builder模式更符合封装的原则,不对外公开属性的写操作!
以上是关于创建型模式之--创建者模式的主要内容,如果未能解决你的问题,请参考以下文章