Java 23种设计模式之建造者模式
建造者模式
定义:可以将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
适用场景
- 隔离复杂对象的创建和使用,相同的方法,不同执行顺序,产生不同事件结果
- 多个部件都可以装配到一个对象中,但产生的运行结果不相同
- 产品类非常复杂或者产品类因为调用顺序不同而产生不同作用
- 初始化一个对象时,参数过多,或者很多参数具有默认值
- Builder模式不适合创建差异性很大的产品类
- 产品内部变化复杂,会导致需要定义很多具体建造者类实现变化,增加项目中类的数量,增加系统的理解难度和运行成本
需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
以下是HumanBuilder的简单实现
普通Human对象
package com.demo.Builder;
public class Human {
private String head;
private String body;
public Human() {
}
public Human(String head, String body) {
this.head = head;
this.body = body;
}
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public String toString() {
return "Human{" +
"head='" + head + '\'' +
", body='" + body + '\'' +
'}';
}
}
HumanFactory接口
package com.demo.Builder;
public interface HumanFactory {
Human build(Human human);
}
HumanFactoryBuilder对象
package com.demo.Builder;
public class HumanFactoryBuilder {
private String head;
private String body;
final HumanFactory humanFactory = null;
public HumanFactoryBuilder() {
}
public HumanFactoryBuilder setHead(String head) {
this.head=head;
return this;
}
public HumanFactoryBuilder setBody(String body) {
this.body=body;
return this;
}
public HumanFactory build() {
return build(this);
}
private static HumanFactory build(HumanFactoryBuilder builder){
String head = builder.head;
String body = builder.body;
HumanFactory humanFactory =
(builder.humanFactory != null)? builder.humanFactory
: (vo) -> new Human("tou","shenti");
return (vo)->{
Human human = humanFactory.build(vo);
if (head!=null){
human.setHead(head);
}
if (body!=null){
human.setBody(body);
}
return human;
};
}
}
测试代码:
HumanFactory human = new HumanFactoryBuilder().setHead("头").setBody("身体").build();
System.out.println(human);
代码结果:com.demo.Builder.HumanFactoryBuilder$$Lambda$2/1607521710@16b98e56
复杂对象的构建如google的线程对象建造器ThreadFactoryBuilder
package com.google.common.util.concurrent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtIncompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.CheckReturnValue;
/ **
* ThreadFactory构建器,提供以下功能的任意组合:
* <ul>
* <li>是否应将线程标记为{@linkplain Thread#setDaemon守护程序}线程
* <li> {@ linkplain ThreadFactoryBuilder#setNameFormat命名格式}
* <li>一个{@linkplain Thread#setPriority线程优先级}
* <li>一个{@linkplain Thread#setUncaughtExceptionHandler未捕获的异常处理程序}
* <li> {@ linkplain ThreadFactory#newThread支持线程工厂}
* </ ul>
* <p>如果没有提供支持线程工厂,则使用默认的支持线程工厂,就像
*调用{@code setThreadFactory(} {@ link Executors#defaultThreadFactory()} {@ code}}。
*
* @作者Kurt Alfred Kluever
* @从4.0开始
* /
@CanIgnoreReturnValue
@GwtIncompatible
public final class ThreadFactoryBuilder {
private String nameFormat = null;
private Boolean daemon = null;
private Integer priority = null;
private UncaughtExceptionHandler uncaughtExceptionHandler = null;
private ThreadFactory backingThreadFactory = null;
/ **
*创建一个新的{@link ThreadFactory}构建器。
* /
public ThreadFactoryBuilder() {}
/ **
*设置在命名创建的线程({@link Thread#setName})时使用的命名格式
*使用此ThreadFactory。
*
* @param nameFormat兼容{@link String#format(String,Object ...)}的格式String,
*将提供唯一的整数(0、1等)作为单个参数。 该整数将
*对于ThreadFactory的构建实例是唯一的,并将按顺序分配。 对于
*例如,{@ code“ rpc-pool-%d”}将生成类似{@code“ rpc-pool-0”}的线程名称,
* {@code“ rpc-pool-1”},{@ code“ rpc-pool-2”}等。
* @返回此生成器模式
* /
public ThreadFactoryBuilder setNameFormat(String nameFormat) {
String unused = format(nameFormat, 0); // fail fast if the format is bad or null
this.nameFormat = nameFormat;
return this;
}
/ **
*是否为使用此ThreadFactory创建的新线程设置守护进程。
*
* @param守护程序,用此ThreadFactory创建的新线程是否将成为守护程序线程
* @返回此生成器模式
* /
public ThreadFactoryBuilder setDaemon(boolean daemon) {
this.daemon = daemon;
return this;
}
/ **
*为使用此ThreadFactory创建的新线程设置优先级。
*
* @param priority使用此ThreadFactory创建的新线程的优先级
* @返回此生成器模式
* /
public ThreadFactoryBuilder setPriority(int priority) {
// Thread#setPriority() already checks for validity. These error messages
// are nicer though and will fail-fast.
checkArgument(
priority >= Thread.MIN_PRIORITY,
"Thread priority (%s) must be >= %s",
priority,
Thread.MIN_PRIORITY);
checkArgument(
priority <= Thread.MAX_PRIORITY,
"Thread priority (%s) must be <= %s",
priority,
Thread.MAX_PRIORITY);
this.priority = priority;
return this;
}
/ **
*为使用该ThreadFactory创建的新线程设置{@link UncaughtExceptionHandler}。
*
* @param uncaughtExceptionHandler使用创建的新线程的未捕获异常处理程序
*这个ThreadFactory
* @返回此生成器模式
* /
public ThreadFactoryBuilder setUncaughtExceptionHandler(
UncaughtExceptionHandler uncaughtExceptionHandler) {
this.uncaughtExceptionHandler = checkNotNull(uncaughtExceptionHandler);
return this;
}
/ **
*为使用此ThreadFactory创建的新线程设置背景{@link ThreadFactory}。 线程数
*将通过在此支持{@link ThreadFactory}上调用#newThread(Runnable)来创建。
*
* @param backingThreadFactory支持{@link ThreadFactory},它将在执行期间委派给
*线程创建。
* @返回此生成器模式
*
* @查看更多执行者
* /
public ThreadFactoryBuilder setThreadFactory(ThreadFactory backingThreadFactory) {
this.backingThreadFactory = checkNotNull(backingThreadFactory);
return this;
}
/ **
*使用在构建过程中提供的选项返回新的线程工厂。 后
*构建,仍然可以更改用于构建ThreadFactory和/或的选项
*重新构建。 状态在已构建实例之间不共享。
*
* @返回完全构建的{@link ThreadFactory}
* /
@CheckReturnValue
public ThreadFactory build() {
return build(this);
}
private static ThreadFactory build(ThreadFactoryBuilder builder) {
final String nameFormat = builder.nameFormat;
final Boolean daemon = builder.daemon;
final Integer priority = builder.priority;
final UncaughtExceptionHandler uncaughtExceptionHandler = builder.uncaughtExceptionHandler;
final ThreadFactory backingThreadFactory =
(builder.backingThreadFactory != null)
? builder.backingThreadFactory
: Executors.defaultThreadFactory();
final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;
return new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = backingThreadFactory.newThread(runnable);
if (nameFormat != null) {
thread.setName(format(nameFormat, count.getAndIncrement()));
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
if (uncaughtExceptionHandler != null) {
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
}
return thread;
}
};
}
private static String format(String format, Object... args) {
return String.format(Locale.ROOT, format, args);
}
}