Design patterns 增强构建器-对构建器进行子类化或创建构建器装饰器?
我正在设计一个新的应用程序,并考虑以下问题Design patterns 增强构建器-对构建器进行子类化或创建构建器装饰器?,design-patterns,Design Patterns,我正在设计一个新的应用程序,并考虑以下问题 背景信息 我将有一个名为HouseBuilder的builder类来构建House类型的对象。建造商将提供以下方法: buildRoof() buildWindow() buildDoor() 等等, getHouse() 在客户机代码中,我通常会使用以下生成器类: HouseBuilder builder = new HouseBuilder(); House house = builder.buildRoof().buildWindow().
背景信息 我将有一个名为HouseBuilder的builder类来构建House类型的对象。建造商将提供以下方法:
- buildRoof()
- buildWindow()
- buildDoor()
- 等等,
- getHouse()
HouseBuilder builder = new HouseBuilder();
House house = builder.buildRoof().buildWindow().buildWindow().buildDoor().getHouse();
HouseBuilder builder = new CottageBuilder();
House house = builder.buildCottage().getHouse();
这是正在使用的生成器设计模式的经典示例
问题 在客户端代码中,我需要构建一个特定类型的房子,比如说一个小屋。每次我需要一个新的构建块时,从基本的构建块构建小屋(如上面的示例中所示)似乎都有很多不必要的重复代码 因此,我将创建一个新的构建器类,比如CottageBuilder,它将允许如下内容:
HouseBuilder builder = new HouseBuilder();
House house = builder.buildRoof().buildWindow().buildWindow().buildDoor().getHouse();
HouseBuilder builder = new CottageBuilder();
House house = builder.buildCottage().getHouse();
我不确定设计CottageBuilder的最佳方法是什么。我想到两个选择:
- 让CottageBuilder成为房屋建筑商的子类,并在Build小屋方法中使用父类的方法
- 让CottageBuilder接受一个HouseBuilder实例,并在Build小屋方法中调用它的方法(无论如何,我都会让CottageBuilder子类化HouseBuilder,以获得多态性行为——因此我会让CottageBuilder成为HouseBuilder周围的装饰者)
请注意,我的构建者实际上并不是要构建房屋对象,而是来自不同域的对象。我决定不通过描述目标域来污染这个问题,而是建立这个类比,在我看来,这个类比非常适合原始问题。一个“构建者”通常通过一系列步骤来构建对象,例如您的示例中的
房屋构建者。您的CottageBuilder
实际上不是一个建筑商,而是一个返回特定类型房屋的“工厂”。因此,我将有一个HouseFactory
类,其中包含用于创建不同类型房屋的静态方法:
public class HouseFactory {
public static House createCottage() {
HouseBuilder builder = new HouseBuilder();
// use builder to build cottage
return builder.getHouse();
}
// more methods for other types of houses
}
CottageBuilder
是否总是建造相同类型的房子,或者是否可以像HouseBuilder
那样进行进一步定制?总是建造相同类型的房子。我正在寻找一种创建小屋的捷径的最佳方法,而不是每次我需要新的小屋时都从基本的建筑块中创建。听起来不错,谢谢!不过,我不会让CreateChattle方法是静态的,而是让HouseFactory接受HouseBuilder的实例作为构造函数参数。测试、重用等应该更容易。@DušanRychnovský:我通常避免使用静态类,但这是一个可以接受的用例,因为createbutch
只是一个实用方法——正如您前面提到的,“创建小屋的快捷方式”,而不是重复代码。如果你真的觉得有必要测试这个方法,那么你应该把它重构成更小的可测试的部分。