构建API时,您应该始终考虑谁将使用它。 当API简单易用时,用户就会感到满意。 当用户满意时,每个人也都会满意。 但是出色的可用性并非总是容易实现的。 有一些模式对此有所帮助,在这篇文章中,我将重点介绍经典的构建器模式,以及如何使用步进构建器模式对其进行增强,以构建没有大脑接口,易于使用且不会出错的对象 。 因此,让我们开始绘制一些上下文,我们有2个域对象代表连接到某个远程或本地服务器的用户配置。 当需要远程凭据时,在本地时。
package com.marco.sbp;
public class UserConfiguration {private final String name;private ServerDetails serverDetails;public UserConfiguration(String name) {this.name = name;}public void setServerDetails(ServerDetails serverDetails) {this.serverDetails = serverDetails;}public String getName() {return name;}public ServerDetails getServerDetails() {return serverDetails;}
}
package com.marco.sbp;
public class ServerDetails {private final String host;private String user;private String password;public ServerDetails(String host) {this.host = host;}public void setUser(String user) {this.user = user;}public void setPassword(String password) {this.password = password;}public String getHost() {return host;}public String getUser() {return user;}public String getPassword() {return password;}
}
我们希望使用两种不同的技术(经典的构建器模式和步骤构建器模式)来抽象上述对象的构造。
经典的构建器模式非常简单,它使用诸如onLocalHost,onRemoteHost等正确命名的方法来掩盖UserConfiguration和ServerDetails的创建。
package com.marco.sbp.builder;
import com.marco.sbp.ServerDetails;
import com.marco.sbp.UserConfiguration;
public class ClassicBuilder {private String name;private String host;private String user;private String password;public ClassicBuilder(String name){this.name = name;}public ClassicBuilder onLocalHost(){this.host = "localhost";return this;}public ClassicBuilder onRemoteHost(String remoteHost){this.host = remoteHost;return this;}public ClassicBuilder credentials(String user, String password){this.user = user;this.password = password;return this;}public UserConfiguration build(){UserConfiguration userConfiguration = new UserConfiguration(name);ServerDetails serverDetails = new ServerDetails(host);serverDetails.setUser(user);serverDetails.setPassword(password); userConfiguration.setServerDetails(serverDetails);return userConfiguration;}
}
步骤构建器模式仍在使用智能名称来构造对象,但是仅在需要使用接口和适当的封装时才公开这些方法。
package com.marco.sbp.builder;
import com.marco.sbp.ServerDetails;
import com.marco.sbp.UserConfiguration;/** "Step Builder" */
public class StepBuilder {public static NameStep newBuilder() {return new Steps();}private StepBuilder() {}public static interface NameStep {/*** @param name* unique identifier for this User Configuration* @return ServerStep*/ServerStep name(String name);} public static interface ServerStep {/*** The hostname of the server where the User Configuration file is stored will be set to "localhost".* * @return BuildStep*/public BuildStep onLocalhost();/*** The hostname of the server where the User Configuration file is stored.* * @return CredentialsStep*/public CredentialsStep onRemotehost(String host);}public static interface CredentialsStep {/*** Username required to connect to remote machine Password required to connect to remote machine* * @return BuildStep*/public BuildStep credentials(String user, String password);}public static interface BuildStep {/*** @return an instance of a UserConfiguration based on the parameters passed during the creation.*/public UserConfiguration build();}private static class Steps implements NameStep, ServerStep, CredentialsStep, BuildStep {private String name;private String host;private String user;private String password;public BuildStep onLocalhost() {this.host = "localhost";return this;}public ServerStep name(String name) {this.name = name;return null;}public CredentialsStep onRemotehost(String host) {this.host = host;return this;}public BuildStep credentials(String user, String password) {this.user = user;this.password = password;return this;}public UserConfiguration build() {UserConfiguration userConfiguration = new UserConfiguration(name);ServerDetails serverDetails = new ServerDetails(host);serverDetails.setUser(user);serverDetails.setPassword(password); userConfiguration.setServerDetails(serverDetails);return userConfiguration;}}
}
现在让我们看一下两个构建器的用户体验。 经典构建器将使用用户配置的名称来构造,然后它将公开其所有方法,从而使用户过于自由,无法选择下一步。
例如,一个不小心的用户可能最终将UserConfiguration设置为localhost,而无需身份验证,仍然传递用户名和密码。
这令人困惑,并且可能导致运行时异常。
这些是用户可以最终得到的UserConfigurations的一些可能组合,其中一些是正确的,很多是错误的:
步骤构建器有一个完全不同的故事,这里仅显示了当时的一个步骤:
如果不需要凭据,则不会公开它们,只有在确保对象状态一致且完整时才提供build()方法:
使用此模式只能构建2个可能的UserConfigurations,它们既有意义又对用户清楚。
结论
步骤构建器模式不是经典Bloch 模式的替代,有时您想强迫用户在进行创建之前填充一些参数,在这种情况下,步骤构建器正在执行此工作,否则,当需要更开放的方法时比经典的建造者更适合您。
翻译自: https://www.javacodegeeks.com/2013/05/building-smart-builders.html