我正在尝试创建一种Multi Strategy Builder
。我的意思是这个构建器应该是通用的,并且应该有不同的方法取决于实体类型。让我解释一下。
取决于实体我们需要有不同的方法。例子:
Builder<User> userBuilder;
userBuilder.withName(«Bob»);
userBuilder.withAge(17);
并且此构建器必须没有其他方法!
Builder<Account> accountBuilder;
accountBuilder.withCounry(«Fr»);
accountBuilder.withNumber(2846218354);
accountBuilder.withCode(«X34»);
我应该使用什么样的模式?以及如何组织我的设计?
答案 0 :(得分:4)
如果您要求单个Builder
类型不需要了解它所操作的实体的任何信息,那么Java就不能像您描述的那样轻松地完成。在Builder<User>
示例中,需要在编译时知道withName
和withAge
方法。
由于这些方法实际上并不存在,但需要动态添加,因此您必须编写自定义类加载器。链接Builder
类后,您无法更改它,并且因为在传入实体之前它不知道您想要什么方法,所以在您需要添加方法时更改为时已晚。
你可以通过使用反射来获得大部分。例如,您可以在Builder
中使用单个方法,例如with(String field, Class<?> c, Object value)
。然后,假设您正在构建的对象实例有一个名为“set __”的方法,您可以使用Method
类来调用传入的值的相应set方法。
这看起来像是:
Builder<Account> b = new Builder<>();
b.with("AccountNumber", String.class, "5897-1048-2949");
// this invokes "setAccountNumber" method on internal
// Account instance with "5897-1048-2949" cast to String
更好的想法是为您要构建的内容创建类:AccountBuilder
,UserBuilder
,等等。这更清晰,可能是Java中最好的,而不需要使用自定义类加载器等异国情调的解决方案。 (是的,你必须为每个人写下属性。)
但是,如果您决定需要进行大量构建,则可能需要考虑使其更容易实现的替代语言,例如Ruby或Elixir。动态方法不是Java的强项,并且试图绕过语言的限制只是为了实现特定的API通常是一个糟糕的想法。
答案 1 :(得分:3)
根据在Java中传递给它的类,通用接口不可能有不同的方法。这意味着Builder
接口可以具有:
withName
和withAge
方法withCountry
,withNumber
和withCode
种方法没有可以克服Java语言限制的设计模式。我建议的是使用通用构建器界面,如:
public interface Builder<T> {
T build();
}
然后为每个实体类型创建单独的子类:
public class UserBuilder implements Builder<User> {
public void withName(String name) {
// ...
}
public void withAge(int age) {
// ...
}
public User build() {
User user = new User();
user.setName(...);
user.setAge(...);
return user;
}
}
public class AccountBuilder implements Builder<Account> {
public void setCountry(String country) {
// ...
}
public void setNumber(String number) {
// ...
}
public void setCode(String code) {
// ...
}
public Account build() {
Account account = new Account();
account.setCountry(...);
account.setNumber(...);
account.setCode(...);
return account;
}
}
然后像
一样使用它UserBuilder userBuilder = new UserBuilder();
userBuilder.setName("John");
userBuilder.setAge(20);
User user = userBuilder.build();
AccountBuilder accountBuilder = new AccountBuilder();
accountBuilder.setCountry("UA");
accountBuilder.setNumber("333-22-1");
accountBuilder.setCode("123");
就是这样。使用Fluent Interface模式可以略微改善这一点,但无论如何,在Java中不可能实现它的工作方式与您的问题完全相同。
希望这会有所帮助......
答案 2 :(得分:1)
首先,添加动态方法不是很像java。
Builder是一种创造性模式,策略是行为式的。我不会在这里混淆它们。
Builder将创建给定TYPE的对象。您的用户和帐户是否具有相同的类型? IMO与其他设计模式书不同,GoF书非常有效地解释了一种对象的类型。请阅读讨论。鉴于代码片段,我不会说用户和帐户具有相同的类型。我会使用不同的构建器来构建用户和帐户的对象。类型讨论也将在战略中派上用场。