我想知道我是否可以实现 Builder 设计模式,但没有从中派生具体构建器的接口/抽象类?我可以只有一个 builder 吗?
如果我只有一个concretebuilder和一个director,它仍然是builder设计模式吗?
更加具体:
我有一些对象想“组合”成一个复杂的对象。更准确地说,我有以下课程:
门墙房
我想从这些类中构建一个“世界”,即所有这些类组合起来给我一个世界。
谢谢
我想知道我是否可以实现 Builder 设计模式,但没有从中派生具体构建器的接口/抽象类?我可以只有一个 builder 吗?
如果我只有一个concretebuilder和一个director,它仍然是builder设计模式吗?
更加具体:
我有一些对象想“组合”成一个复杂的对象。更准确地说,我有以下课程:
门墙房
我想从这些类中构建一个“世界”,即所有这些类组合起来给我一个世界。
谢谢
是的,您绝对可以拥有一个简单的 WorldBuilder,其工作是创建一个由门、墙和房间组成的完全配置的世界。当您不想暴露部分构建且可能无效的 World 对象时,这非常有用。
假设构建器的用法是这样的:
WorldBuilder builder = new WorldBuilder();
// read the definition of a room from an XML file or other source.
// this is vastily simplified, you'd probably be iteration
// something like this:
//
// for each Room in file
// for each wall in room
// for each door in wall
//
roomId = readRoomId();
wallId = readWallId();
doorId = readDoorId();
destRoomId = readDestinationRoomId();
builder.AddRoom(roomId);
builder.AddWallToRoom(roomId, wallId, SIDE.NORTH);
builder.AddDoorToWall(wallId, DOORSTYLE.WOODEN | DOORSTYLE.LOCKED, destRoomId);
// etc, etc
World world = builder.makeWorld();
非构建器方法可能想要做这样的事情来连接两个房间对象:
Door door = new Door(roomOne, roomTwo);
但是,如果您像以前一样从文件中迭代每个房间,那么您将不会引用第二个房间,因为它甚至可能还没有到达。
另一种方法是只为每个对象提供其邻居或父对象的 ID,以便您获得此 ID,这允许您引用尚未加载的对象:
Door door = new Door(roomOneId, roomTwoId);
但是如果文件中有错误并且房间 2 从未定义过,那么 World 将是无效的。
Builder 可以处理正确构造、连接和验证 World 创建过程的所有细节,为想要创建世界的客户端代码提供灵活性,并释放复杂构造逻辑的 World 对象。
您可以将构建器模式与访问者模式结合起来:将某种数据树传递给构建器,每个构建器都实现一个accept(Visitor v)
方法,并让构建器遍历树,通过接受方法将每个节点传递回访问者。
如果我只有一个concretebuilder和一个director,它仍然是builder设计模式吗?
我不会在一开始就挂断这个问题。如果您的项目只需要构建一种类型的“世界”,并且您确实不需要多个构建器子类,那么使用导向器和单个具体构建器是一种有效的方法。而是专注于模式的精神——即将你的导演与世界应该如何构建的细节隔离开来。
一旦您的代码正常工作并且您对结果感到满意,请返回并查看您的主管和构建器的实际交互方式。然后考虑重构构建器以提取一个通用接口,以真正确定主管和构建器之间的合同。
我发现从工作的具体类中提取一个合理的接口要容易得多,然后尝试预先猜测这个接口可能是什么,并尝试同时开发接口和类。