打造智能建筑商

构建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 模式的替代,有时您想强迫用户在进行创建之前填充一些参数,在这种情况下,步骤构建器正在执行此工作,否则,当需要更开放的方法时比经典的建造者更适合您。

参考:从我们的JCG合作伙伴 Marco Castigliego(在“ 删除重复并修复不良名称”博客中) 构建智能构建器 。

翻译自: https://www.javacodegeeks.com/2013/05/building-smart-builders.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

结合BeautyEye开源UI框架实现的较美观的Java桌面程序

BeautyJavaSwingRobot 结合BeautyEye开源UI框架实现的较美观的Java桌面程序,主要功能就是图灵机器人和一个2345网站万年历的抓取。。。。   挺简单而且实用的一个项目,实现出来的效果也还不错。希望可以学到知识的小可爱不对应该是帅哥,可…

oracle外表日期,三步教会您掌握oracle外表(external table)

三步教会你掌握oracle外表(external table)外表(externaltable)就像普通的表对像一样,可以select等,只是它是只读的,数据库中只保存了表结构的描述,表数据却没有存放在数据库内,而是存放在了文件系统上。当用户想偶尔使…

【从入门到放弃】23种设计模式(1):设计模式综述

一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、单例模式(Singleton)、建造者模式…

Bootstrap警告框

前面的话 在网站中,网页总是需要和用户一起做沟通与交流。特别是当用户操作上下文为用户提供一些有效的警示框,比如说告诉用户操作成功、操作错误、提示或者警告等。在Bootstrap框架有一个独立的组件,实现类似的效果,这个组件被称…

python doctest测试

title: Python doctest测试 tags: Python --- doctest测试 python 提供了REPL(read-eval-print loop,读取、求值、输出的循环) 官方地址:https://docs.python.org/3/library/doctest.html """ This is the "e…

异步CDI事件

几天前,在我们的常规代码审查中,我的一位同事提出了一个问题,即如果可能,一次同时调用CDI观察者(这样的方法带有参数Observes的方法)会发生什么?用于不同的事件实例。 换句话说,在产…

oracle改了包怎么保存,Oracle存储过程、包、方法使用总结(推荐)

/***author:zhengwei*date:2017-04-28*desc:存储过程用法总结*/CREATE OR REPLACE PROCEDURE MYPROCEDURE(P_ID IN VARCHAR,P_STATUS OUT VARCHAR) --P_ID为输入参数 ,P_STATUS为输出参数AS---变量声明T_STATUS VARCHAR2(20);T_ID NUMBER;V_POSTYPE VARCHAR2(20);V_…

【2017级面向对象程序设计】第2次成绩排行

作业地址 https://edu.cnblogs.com/campus/fzu/OOP/homework/1864 评分标准 1) C 流程图 or 文字描述程序结构 5分C 类图 or 文字描述程序结构 5分2) 代码 共 10 分构造函数 :2 分析构函数 :2 分成员函数 显示当前所处楼层&#x…

css定位position

闲言碎语不多说,直接开写! 关于定位 我们可以使用css的position属性来设置元素定位类型,position的设置项如下: a、relative生成相对定位元素,元素所占据的文档流的位置不变(即元素不会脱离文档流&#x…

Spring Security登录

1.简介 本文将重点介绍使用Spring Security登录 。 我们将在前面的简单Spring MVC示例的基础上构建,因为这是设置Web应用程序和登录机制的必要部分。 2. Maven依赖 要将Maven依赖项添加到项目中,请参阅Spring Security with Maven文章 。 标准的spring-…

php运城,运城php培训

作用域:全局的request恳求   描绘:经过在Global中完成Application_Error办法,来到达侦听未经处置的异常   详细代码如下:sudo dtrace -qFn pid$target:Finding?Ray:Finding?Ray:r{ printf("%s\n", probefunc); } …

sql语句使用、说明及技巧

一、基础 1、说明:创建数据库CREATE DATABASE database-name 2、说明:删除数据库drop database dbname3、说明:备份sql server--- 创建 备份数据的 deviceUSE masterEXEC sp_addumpdevice disk, testBack, c:\mssql7backup\MyNwind_1.dat--- …

利用爬虫模拟网页微信wechat

1.登录页面,显示二维码 当我们打开网页微信时,会看到一个用于扫码登录的二维码,所以我们要模拟该页面给我们的页面也弄一个二维码 通过查看网页代码我们发现,这个二维码的标签为 这个src属性的最后一段每次访问都是不同的&#xf…

Bootstrap分页

前面的话 分页导航几乎在每个网站都可见,好的分页能给用户带来好的用户体验。本文将详细介绍Bootstrap分页 概述 在Bootstrap框架中提供了两种分页导航: ☑ 带页码的分页导航 ☑ 带翻页的分页导航 页码分页 带页码的分页导航,可能是最常见…

php 查询and or,php – SQL查询多个AND和OR不起作用

我有一个包含由双管分隔的值的单元格.我试图用以下内容搜索这个单元格的内容,(其中10是要搜索的数字)?,10%,?%和10我的查询似乎只返回10.没有其他变化.有人可以告诉我为什么它不起作用?提前谢谢了. (您在下面看到的SQL…

[codevs1213]解的个数 二分 + exgcd

题目← 扩欧,求不定方程解的个数 我们已经知道通解x0 x - (b/gcd(a,b))t,那只要知道有多少个t使x在题目给定的范围中就行了 但还有y 怎么办?求交集! 分别二分确定在x取值范围内合法的t的范围和在y取值范围内合法的t的范围 然后交…

爬取饿了么商铺信息

分析: 当我们访问https://www.ele.me/home/时,看看我们得到了什么 1.png我们发现所有的城市名称和他的经纬度,还有一个风流的男子 然后随机输入一些东西看看,进入某个地区看一看 在新的界面里我们看到了这样一条url: https://main…

html中的锚点

一、页面内跳转的锚点设置 页面内的跳转需要两步&#xff1a; 方法一&#xff1a; ①&#xff1a;设置一个锚点链接<a href"#miao">去找喵星人</a>&#xff1b;&#xff08;注意&#xff1a;href属性的属性值最前面要加#&#xff09; ②&#xff1a;在页…

linux基本命令du,Linux常用操作命令汇总

你还在为不知道Linux常用操作命令汇总而不知所措么?下面来是学习啦小编为大家收集的Linux常用操作命令汇总&#xff0c;欢迎大家阅读&#xff1a;Linux常用操作命令汇总1.ls 命令ls以默认方式显示当前目录文件列表服务器教程ls -a显示所有文件包括隐藏文件ls -l显示文件属性&a…

Maven部署到Nexus

1.概述 在上一篇文章中 &#xff0c;我讨论了Maven项目如何在本地安装尚未部署在Maven Central&#xff08;或任何其他大型且公共托管的存储库&#xff09;上的第三方jar。 该解决方案仅适用于小型项目&#xff0c;在这些项目中安装&#xff0c;运行和维护完整的Nexus服务器可能…