问题描述
在学习设计模式时,我发现了 Builder 模式的不同实现。一些实现使用接口/抽象类来表示构建器,其他实现只使用静态类。 哪一种是实现构建器设计模式的正确方法?
下面是一个使用抽象类 (ComputerBuilder) (Source) 的实现
public class LaptopBuilder : ComputerBuilder
{
Computer computer;
public LaptopBuilder()
{
computer = new Computer("Laptop");
}
public override void BuildOS()
{
//Todo
}
public override void BuildDevice()
{
//Todo
}
public Computer ComputerType
{
get { return computer; }
}
}
public class DesktopBuilder : ComputerBuilder
{
Computer computer;
public DesktopBuilder()
{
computer = new Computer("Desktop");
}
public override void BuildOS()
{
//Todo
}
public override void BuildDevice()
{
//Todo
}
public Computer ComputerType
{
get { return computer; }
}
}
下面是另一个实现,既不使用抽象类也不使用接口,而是使用静态类。 (Source)
public class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter,and NO setter to provde immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "User: "+this.firstName+","+this.lastName+","+this.age+","+this.phone+","+this.address;
}
public static class UserBuilder
{
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName,String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
validateUserObject(user);
return user;
}
private void validateUserObject(User user) {
//Do some basic validations to check
//if user object does not break any assumption of system
}
}
}
解决方法
如果您真的阅读了second article,您可能会注意到它很早就指出
“我想说明的是,我将在本文中讨论的构建器模式与 GangOfFour“设计模式”一书中提到的略有不同。” (作者重点)
稍后,他或她写道:
“对我来说,构建器模式更像是 fluent interface。”
注意小限定符,对我来说。
这应该告诉您,您看到的不是模式的“规范”表示,而是一种变体。
也就是说,这些表示是 variations of the same underlying idea。
寻找表达概念的替代方式是可以的。我们应该小心,不要将四人帮的书提升到无懈可击的状态。
,对我来说(双关语)Builder 是 GoF 模式的最佳示例,自该书出版以来已得到改进。我相信是来自 Effective Java 的 Josh Bloch 的版本普及了静态方法;但是有些源自博客文章的版本比 GoF 版本更有用和/或更简单。
当我回顾 GoF 的书时,我从来没有重读过 Builder 一章,因为有更好的选择。当然,您必须决定哪种选择更适合您。