我们的框架提供了某种" log"对象;它实际上代表了我们遗留的C / C ++代码中的遗留结构。今天我开始编写一个帮助器类,它使用构建器模式来允许更现代的方法来创建这样的日志对象。
但有一个问题,我不确定答案是正确的:
基本上这些日志对象有一些属性是必需的&#34 ;;因此,遵循构建器模式,您必须将这些参数指定为我的新构建器类的ctor的参数。然后构建器有一些方法来配置"可选属性&#34 ;;当然还有一种方法" build()"这将发出一个日志对象,其中包含所收集值的摘要。
但现在我想知道:我是否应该关心人们是否会重新使用相同的构建器对象?那么,我应该有一个" reset()"清除所有可选参数的方法;或者防止不止一次调用build()? 或者最好不要担心不是全部?
答案 0 :(得分:2)
无需重置,只需继续允许使用相同的构建器对象生成新对象。开发人员可以创建一个新构建器,以避免重复使用先前设置的内容。此外,Twitter4j有这样的东西(并且是开源的),如果你想看看事情应该如何运作(见http://twitter4j.org/en/configuration.html):
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("*********************")
.setOAuthConsumerSecret("******************************************")
.setOAuthAccessToken("**************************************************")
.setOAuthAccessTokenSecret("******************************************");
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
答案 1 :(得分:2)
我是否应该关心人们是否会重复使用相同的构建器对象?
你想要观察副作用,但我认为这就是你问的原因,因为你知道人/代码会在建造者中留下垃圾。
那么,我应该有一个" reset()"清除所有可选参数的方法;
我认为如果你传递一个构建器,清理的责任应该在使用者身上(将构建器作为输入的函数或类)。这样我们就不会造成副作用。例如:
public class SomeClass {
public SomeClass(Log.Builder builder){
builder.tag("SomeClass"); //bad, we caused a side effect
//someone class forgets to set the tag
//later, then they get this tag
log = builder.build();
}
}
一种解决方案是提供复制构造函数:
public class SomeClass {
public SomeClass(Log.Builder builder){
Log.Builder localBuilder = new Log.Builder(builder); //copy constructor being used.
localBuilder.tag("SomeClass"); //only applies to the local builder
log = localBuilder.build();
} //builder is as it was before the call, no side effect
}
您甚至可以使用副本致电SomeClass
,这样您就不需要关心它是否实现了无副作用:
Log.Builder defaults = new Log.Builder(...whatever...).tag("notag");
new SomeClass(new Log.Builder(defaults));
new SomeClass2(new Log.Builder(defaults));
要进一步锁定它,你可以拥有一个界面Log.ReadOnlyBuilder
,它没有设置器,并且真的只适合构建或创建副本:
public class Log {
public interface ReadOnlyBuilder {
Builder copy();
Log build();
}
public static class Builder implements ReadOnlyBuilder {
Builder tag(String tag){
...
}
}
}
public class SomeClass {
public SomeClass(Log.ReadOnlyBuilder builder){
log = builder.copy().tag("SomeClass").build();
} //builder is as it was before the call, no side effect
}
我喜欢这个,因为消费者的责任不会引起副作用,但它通过类型和界面得到强制执行。此外,如果他们不需要设置任何字段,他们可以只使用readonly构建器,我们不必为了以防万一而制作副本。
P.S。我不认为可选和必需是你想要决定重置什么和设置什么的分界点。我认为复制构造函数应该只将构建器中的每个字段复制到新构建器。但是你可以随意开发copy
方法/构造函数。
答案 2 :(得分:0)
我发现在这种情况下有用的东西,当构建器被多次重复使用并且可能存在一些剩余的数据重叠时,是要在构建器类中构建未初始化的对象,并保留初始化对构建器实例的责任。这样,构建的对象不关心(或知道)以前构建的会话中的垃圾剩余,如果它需要相同的可选数据,构建器也知道重新初始化该数据。