Joshua Bloch的Effective Java描述了一个Builder模式,可用于构建具有多个可选定制参数的对象.他为Builder函数建议的命名约定,"模拟在Ada和Python中找到的命名可选参数",似乎不符合Java的标准命名约定.Java函数往往依赖于使用动词来启动函数,然后依靠基于名词的短语来描述它的作用.Builder类只有该函数定义的变量的名称.
Java标准库中是否有使用Builder模式的API?我想在继续使用之前,将本书中的建议与核心Java库集中的实际实现进行比较.
我想看看Builder模式在现实世界的应用程序/ API中是如何使用的.我发现的例子包括比萨饼,蛋糕,汽车等等(加上GoF书中的解析器示例).
你能否告诉我这个模式在实际应用程序/ API中的一些用法,最好是来自C++,.NET或PHP的世界(因为那些是我熟悉的语言).
谢谢.
例如,如果我有一个构建器,那么我可以像这样创建对象:
Node node = NodeBuilder()
.withName(someName)
.withDescription(someDesc)
.withData(someData)
.build();
Run Code Online (Sandbox Code Playgroud)
如何确保在构建方法之前已经设置了用于构建对象的所有变量?
例如:
Node node = NodeBuilder()
.withName(someName)
.build();
Run Code Online (Sandbox Code Playgroud)
不是一个有用的节点,因为尚未设置描述和数据.
我使用构建器模式的原因是因为没有它,我需要很多构造函数的组合.例如,可以通过获取Field对象来设置名称和描述,并且可以使用文件名设置数据:
Node node = NodeBuilder()
.withField(someField) //Sets name and description
.withData(someData) //or withFile(filename)
.build(); //can be built as all variables are set
Run Code Online (Sandbox Code Playgroud)
否则将需要4个构造函数(字段,数据),(字段,文件名),(名称,描述,数据),(名称,描述,文件名).当需要更多参数时会变得更糟.
这些"方便"方法的原因是因为必须构建多个节点,因此它可以节省大量重复的行,如:
Node(modelField.name, modelField.description, Data(modelFile)),
Node(dateField.name, dateField.description, Data(dateFile)),
//etc
Run Code Online (Sandbox Code Playgroud)
但是在某些情况下,需要使用非来自文件的数据构建节点,和/或名称和描述不基于字段.也可能有多个节点共享相同的值,因此不是:
Node(modelField, modelFilename, AlignLeft),
Node(dateField, someData, AlignLeft),
//Node(..., AlignLeft) etc
Run Code Online (Sandbox Code Playgroud)
你可以有:
LeftNode = NodeBuilder().with(AlignLeft);
LeftNode.withField(modelField).withFile(modelFilename).build(),
LeftNode.withField(dateField).withData(someData).build()
Run Code Online (Sandbox Code Playgroud)
所以我认为我的需求与构建器模式非常匹配,除了构建不完整对象的能力.由于上述原因,"在构造函数中放置必需参数并具有可选参数的构建器方法"的正常建议不适用于此处.
实际问题:如何在编译时调用构建之前确保已设置所有参数?我正在使用C++ 11.
(在运行时,我可以为每个参数设置一个标志位,并声明所有标志都在构建中设置)
或者是否有一些其他模式来处理大量的构造函数组合?
模板模式在基类中提供算法,其步骤可以在派生类中进行修改.在Builder模式中,具体构建器公开了用于构建从Director类调用的产品的方法.
我知道使用这些模式的目的有所不同.模板模式是一种行为模式,它改变模板中的一个或多个步骤,而构建器模式是创建模式.
除了上述差异外,还有其他差异吗?
构建器模式中的director不是模板模式中的基本模板.具体的构建器在模板模式中的行为类似于可替换的步骤吗?
有人可以澄清一下.谢谢.
当我在界面构建器中创建新的xib时,Interface Builder Document(Versioning)开发参数默认为xCode 4.1
无论如何都要将其默认为xCode 4.2 - 我问的原因是我最近更改了一个项目以使用IOS 5和4.2 - 该项目最初是在4.1中创建的,当我创建一个新的xib并将视图的大小设置为"表单"它产生了一个警告:
属性不可用:表单表模拟指标在Xcode 4.2之前不可用.

我可以通过将属性检查器中的"文档版本"下拉列表更改为4.2来修复警告

我想知道何时应该使用将来的构建器。例如,如果我要发出http请求并在列表视图中显示结果,则一旦打开视图,我是否必须使用future构建器或仅构建ListViewBuilder类似的构建器:
new ListView.builder(
itemCount: _features.length,
itemBuilder: (BuildContext context, int position) {
...stuff here...
}
Run Code Online (Sandbox Code Playgroud)
而且,如果我不想构建列表视图,而是想要构建一些更复杂的东西(例如圆形图表),是否应该使用Future Builder?
希望它足够清楚!
考虑一下Bloch的Builder模式的逐字副本(对C#的语法进行了更改):
public class NutritionFacts
{
public int ServingSize { get; private set; }
public int Servings { get; private set; }
public int Calories { get; private set; }
...
public class Builder
{
private int ServingSize { get; set; }
private int Servings { get; set; }
private int Calories { get; set; }
public Builder(int servingSize, int servings)
{
ServingSize = servingSize;
Servings = servings;
}
public Builder Calories(int calories)
{ Calories = calories; return this; }
public …Run Code Online (Sandbox Code Playgroud) 我在JavaWorld上发现了这篇文章,其中Allen Holub解释了Getters/Setters的替代方法,它保留了隐藏对象实现的原则(他的示例代码也可以在下面找到).
它解释了类Name/ EmployeeId/ Money应该有一个构造函数接受一个字符串 - 原因是如果你输入它int,然后需要将它改为a long,你将不得不修改类的所有用途,并且你不需要这种模式.
我想知道:这不是简单地将问题转移到解析String被抛出的参数吗?例如,如果所有使用EmployeeId(从中接收Exporter)的代码解析String成一个int,并且突然开始导出long值,则需要完全修改使用的数量......如果你开始解析long它可能就好了改为a double(即使这对id没有意义)......如果你不能确定要解析什么String,你就无法实现任何东西.
除了这个问题,我还有另一个问题:我意识到这篇文章已有七年多的历史了,所以有人能指出我最近关于OO设计的一些概述,特别是关于getter/setter和实现隐藏辩论的想法吗?
public class Employee
{ private Name name;
private EmployeeId id;
private Money salary;
public interface Exporter
{ void addName ( String name );
void addID ( String id );
void addSalary ( String salary ); …Run Code Online (Sandbox Code Playgroud) 我有一个在特定高度和特定温度下运行的模拟:
interface IGeneratable
{
string Name { get; }
void Generate();
}
interface ISimulation : IGeneratable
{
int Height { get; }
int Temperature { get; }
}
Run Code Online (Sandbox Code Playgroud)
的Generate()用于模拟典型的过程包括多个步骤:
void Generate()
{
Step1();
Step2();
Step3();
}
Run Code Online (Sandbox Code Playgroud)
现在,用户可以指定多个高度和/或多个温度.
在这种情况下,产生多个模拟(子模拟),每个高度/温度组合一个.
interface IMultiSimulation : IGeneratable
{
ISimulation[] SubSimulations { get; }
}
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,子模拟的Generate()方法与Step1,Step2,Step3顺序不同:
Step2()仅需要对所有子模拟执行一次,而不是每个温度执行一次(即每次多次模拟一次).Step1() 首先为所有子模拟预先计算.一般注意事项
IStep其中,实现IGeneratable.因此,模拟可以返回例如步骤列表.我一直在尝试使用装饰模式,但没有成功.
我正在寻找一个适当的模式,其可扩展的解决方案可以处理单个模拟的生成以及多个模拟.
谢谢.