使用构建器模式的一些常见的、真实的例子是什么?它能给你买什么?为什么不直接使用工厂模式?
当前回答
我一直不喜欢Builder模式,因为它笨拙、突兀,而且经常被缺乏经验的程序员滥用。这是一个模式,只有当你需要从一些需要后初始化步骤的数据组装对象时才有意义(即,一旦收集了所有的数据-对它做一些事情)。相反,在99%的时间里,构建器只是用来初始化类成员。
在这种情况下,最好是在类中声明withXyz(…)类型setter,并让它们返回对自身的引用。
考虑一下:
public class Complex {
private String first;
private String second;
private String third;
public String getFirst(){
return first;
}
public void setFirst(String first){
this.first=first;
}
...
public Complex withFirst(String first){
this.first=first;
return this;
}
public Complex withSecond(String second){
this.second=second;
return this;
}
public Complex withThird(String third){
this.third=third;
return this;
}
}
Complex complex = new Complex()
.withFirst("first value")
.withSecond("second value")
.withThird("third value");
现在我们有了一个整洁的单一类,它管理自己的初始化,做的工作与构建器几乎相同,只是它要优雅得多。
其他回答
/// <summary>
/// Builder
/// </summary>
public interface IWebRequestBuilder
{
IWebRequestBuilder BuildHost(string host);
IWebRequestBuilder BuildPort(int port);
IWebRequestBuilder BuildPath(string path);
IWebRequestBuilder BuildQuery(string query);
IWebRequestBuilder BuildScheme(string scheme);
IWebRequestBuilder BuildTimeout(int timeout);
WebRequest Build();
}
/// <summary>
/// ConcreteBuilder #1
/// </summary>
public class HttpWebRequestBuilder : IWebRequestBuilder
{
private string _host;
private string _path = string.Empty;
private string _query = string.Empty;
private string _scheme = "http";
private int _port = 80;
private int _timeout = -1;
public IWebRequestBuilder BuildHost(string host)
{
_host = host;
return this;
}
public IWebRequestBuilder BuildPort(int port)
{
_port = port;
return this;
}
public IWebRequestBuilder BuildPath(string path)
{
_path = path;
return this;
}
public IWebRequestBuilder BuildQuery(string query)
{
_query = query;
return this;
}
public IWebRequestBuilder BuildScheme(string scheme)
{
_scheme = scheme;
return this;
}
public IWebRequestBuilder BuildTimeout(int timeout)
{
_timeout = timeout;
return this;
}
protected virtual void BeforeBuild(HttpWebRequest httpWebRequest) {
}
public WebRequest Build()
{
var uri = _scheme + "://" + _host + ":" + _port + "/" + _path + "?" + _query;
var httpWebRequest = WebRequest.CreateHttp(uri);
httpWebRequest.Timeout = _timeout;
BeforeBuild(httpWebRequest);
return httpWebRequest;
}
}
/// <summary>
/// ConcreteBuilder #2
/// </summary>
public class ProxyHttpWebRequestBuilder : HttpWebRequestBuilder
{
private string _proxy = null;
public ProxyHttpWebRequestBuilder(string proxy)
{
_proxy = proxy;
}
protected override void BeforeBuild(HttpWebRequest httpWebRequest)
{
httpWebRequest.Proxy = new WebProxy(_proxy);
}
}
/// <summary>
/// Director
/// </summary>
public class SearchRequest
{
private IWebRequestBuilder _requestBuilder;
public SearchRequest(IWebRequestBuilder requestBuilder)
{
_requestBuilder = requestBuilder;
}
public WebRequest Construct(string searchQuery)
{
return _requestBuilder
.BuildHost("ajax.googleapis.com")
.BuildPort(80)
.BuildPath("ajax/services/search/web")
.BuildQuery("v=1.0&q=" + HttpUtility.UrlEncode(searchQuery))
.BuildScheme("http")
.BuildTimeout(-1)
.Build();
}
public string GetResults(string searchQuery) {
var request = Construct(searchQuery);
var resp = request.GetResponse();
using (StreamReader stream = new StreamReader(resp.GetResponseStream()))
{
return stream.ReadToEnd();
}
}
}
class Program
{
/// <summary>
/// Inside both requests the same SearchRequest.Construct(string) method is used.
/// But finally different HttpWebRequest objects are built.
/// </summary>
static void Main(string[] args)
{
var request1 = new SearchRequest(new HttpWebRequestBuilder());
var results1 = request1.GetResults("IBM");
Console.WriteLine(results1);
var request2 = new SearchRequest(new ProxyHttpWebRequestBuilder("localhost:80"));
var results2 = request2.GetResults("IBM");
Console.WriteLine(results2);
}
}
我一直不喜欢Builder模式,因为它笨拙、突兀,而且经常被缺乏经验的程序员滥用。这是一个模式,只有当你需要从一些需要后初始化步骤的数据组装对象时才有意义(即,一旦收集了所有的数据-对它做一些事情)。相反,在99%的时间里,构建器只是用来初始化类成员。
在这种情况下,最好是在类中声明withXyz(…)类型setter,并让它们返回对自身的引用。
考虑一下:
public class Complex {
private String first;
private String second;
private String third;
public String getFirst(){
return first;
}
public void setFirst(String first){
this.first=first;
}
...
public Complex withFirst(String first){
this.first=first;
return this;
}
public Complex withSecond(String second){
this.second=second;
return this;
}
public Complex withThird(String third){
this.third=third;
return this;
}
}
Complex complex = new Complex()
.withFirst("first value")
.withSecond("second value")
.withThird("third value");
现在我们有了一个整洁的单一类,它管理自己的初始化,做的工作与构建器几乎相同,只是它要优雅得多。
在前面的回答(双关语)的基础上,有一个很好的现实例子,就是Groovy对Builders的内置支持。
使用Groovy的MarkupBuilder创建XML 使用Groovy的StreamingMarkupBuilder创建XML Swing构建器 SwingXBuilder
请参阅Groovy文档中的构建器
对于多线程问题,我们需要为每个线程构建一个复杂的对象。对象表示正在处理的数据,并且可以根据用户输入进行更改。
我们能用工厂代替吗?是的
为什么我们没有呢?我想建造者更有意义。
工厂用于创建具有相同基本类型的不同类型的对象(实现相同的接口或基类)。
构建器一遍又一遍地构建同一类型的对象,但是构造是动态的,因此可以在运行时更改它。
我在自制消息库中使用了builder。库核心从线路接收数据,用Builder实例收集数据,然后,一旦Builder确定它已经获得了创建Message实例所需的一切,Builder. getmessage()就使用从线路收集的数据构造消息实例。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap