设计模式学习(四):建造者模式
2023-02-18 16:35:21 时间
设计模式学习(四):建造者模式
作者:Grey
原文地址:
建造者模式
建造者模式是创建型模式。
我们在对一个实体类进行属性的 get 或 set 的时候,可以通过封装一些常用的构造方法来简化实体类的构造。
比如 Effective Java 中举到到这个例子
// Effective Java 3th examples
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
其中 Builder 就是一个内部类,用于构造 NutritionFacts 的必要信息,外部调用 NutritionFacts 的构造方法时候,可以这样使用:
NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
构造器模式也适用于类层次结构。抽象类有抽象的 Builder ,具体类有具体的 Builder 。Effective Java中还有一个例子, 假设我们抽象出一个披萨类,各种各样的披萨均可以继承披萨这个抽象类来实现自己的具体类型的披萨。
Pizza抽象类如下:
import java.util.*;
// Effective Java 3th examples
public abstract class Pizza {
public enum Topping {HAM, MUSHROOM, ONION, PEPPER, SAUSAGE}
final Set<Topping> toppings;
abstract static class Builder<T extends Builder<T>> {
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
public T addTopping(Topping topping) {
toppings.add(Objects.requireNonNull(topping));
return self();
}
abstract Pizza build();
// Subclasses must override this method to return "this"
protected abstract T self();
}
Pizza(Builder<?> builder) {
toppings = builder.toppings.clone(); // See Item 50
}
}
其中的 Builder 方法是抽象的,所以子类需要实现具体的 Builder 策略,
一种披萨的具体实现 NyPizza
import java.util.Objects;
public class NyPizza extends Pizza {
public enum Size {SMALL, MEDIUM, LARGE}
private final Size size;
public static class Builder extends Pizza.Builder<Builder> {
private final Size size;
public Builder(Size size) {
this.size = Objects.requireNonNull(size);
}
@Override
public NyPizza build() {
return new NyPizza(this);
}
@Override
protected Builder self() {
return this;
}
}
private NyPizza(Builder builder) {
super(builder);
size = builder.size;
}
}
另一种披萨的具体实现 Calzone
public class Calzone extends Pizza {
private final boolean sauceInside;
public static class Builder extends Pizza.Builder<Builder> {
private boolean sauceInside = false; // Default
public Builder sauceInside() {
sauceInside = true;
return this;
}
@Override
public Calzone build() {
return new Calzone(this);
}
@Override
protected Builder self() {
return this;
}
}
private Calzone(Builder builder) {
super(builder);
sauceInside = builder.sauceInside;
}
}
我们在具体调用的时候,可以通过如下方式:
NyPizza pizza = new NyPizza.Builder(SMALL).addTopping(SAUSAGE).addTopping(ONION).build();
Calzone calzone = new Calzone.Builder().addTopping(HAM).sauceInside().build();
实际应用有非常多,很多组件都提供这样的构造方式,比如 OkHttp Client 的构造方法:
public static OkHttpClient create(long connectTimeOut) {
return new OkHttpClient().newBuilder().connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT)).connectTimeout(connectTimeOut, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).retryOnConnectionFailure(true).followRedirects(true).followSslRedirects(true).hostnameVerifier((s, sslSession) -> true).cookieJar(new CookieJar() {
private List<Cookie> cookies;
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
this.cookies = cookies;
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
if (cookies != null) {
return cookies;
}
return Collections.emptyList();
}
}).build();
}
建造者模式的主要应用
- JDK 中的 Calender
Calendar calendar = new Calendar.Builder().build();
-
MyBatis 中
CacheBuilder.build()
和SqlSessionFactoryBuilder.build()
-
Spring 中
BeanDefinitionBuilder.getBeanDefinition()
方法
UML 和 代码
更多
参考资料
相关文章
- 1秒启动Web Server
- 中心化交易所如何用Merkle Tree实现资产储备证明
- 揭秘GaussDB(for Redis):全面对比Codis
- 梦幻联动!金蝶&华为云面向大企业发布数据库联合解决方案
- 面对锁等待难题,数仓如何实现问题的秒级定位和分析
- 技术生态两手抓,打造面向未来的企业级领先数据库
- 看我如何连夜自建网站背刺我的求职对手们
- GaussDB拿下的安全认证CC EAL4+究竟有多难?
- 华为云开发者官网首页焕新升级,赋能开发者云上成长
- 从元宇宙、地产数字化到呼叫中心,华为云携手伙伴共创新价值
- 云享·人物丨造梦、探梦、筑梦,三位开发者在华为云上的寻梦之旅
- 华为云区块链三大核心技术国际标准立项通过
- 云小课|帮您高效快速上传组件至私有依赖库
- 一文详解GaussDB(DWS) 的并发管控和内存管控
- MemArts :高效解决存算分离架构中数据访问的组件
- 论文复现|Panoptic Deeplab(全景分割PyTorch)
- 动手实践丨基于ModelAtrs使用A2C算法制作登月器着陆小游戏
- 云小课|云小课带您快速了解LTS可视化查看
- Karmada跨集群优雅故障迁移特性解析
- 学会二阶思维,你就能像巴菲特一样思考了