Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Builder design pattern - No abstract class/interface

I wonder if I can implement the Builder design pattern but without having a interface/abstract-class from which i derive concrete builders ? Can I just have one builder ?

If I just have a concretebuilder and a director is it still the builder design pattern ?

To be more specific:

I have some object that I want to "put together" to a complex object. Being more precise I have the following classes:

Door Wall Room

I want to build a "World" out of these classe, that is all these classes combined gives me a world.

Thanks

like image 743
mrjasmin Avatar asked Sep 20 '12 20:09

mrjasmin


3 Answers

You could combine the builder pattern with the visitor pattern: Pass some kind of data tree to the builder, each of which implements an accept(Visitor v) method, and have the builder walk the tree passing each node back into the visitor via the accept method.

like image 31
Bohemian Avatar answered Sep 30 '22 00:09

Bohemian


Yes, absolutely you can have a simple WorldBuilder whos job is to create a fully configured world comprised of Doors, Walls, and Rooms. This is a very useful when you don't want to have a partially built, and possibly invalid, World object exposed.

Let's say the usage of the builder is like this:

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();

A non-builder approach might want to do something like this to connect two rooms objects:

Door door = new Door(roomOne, roomTwo);

But if you were iterating each room from a file as before then you won't have a reference to the second room because it may not have even been reached yet.

An alternative approach is to give each object just the ID of its neighbors or parent so you get this instead, which allows you to refer to an object that has not been loaded yet:

Door door = new Door(roomOneId, roomTwoId);

But if there was an error in the file and room 2 was never defined then the World would be invalid.

The Builder can take care of all of the details of properly constructing, connecting, and validating the World creation process, granting flexibility to client code that wants to create the world, and releaving the World object of complex construction logic.

like image 166
tcarvin Avatar answered Sep 30 '22 00:09

tcarvin


If I just have a concretebuilder and a director is it still the builder design pattern ?

I would not get hung up on this question at the outset. If your project only requires one type of "world" to be built and you really don't need multiple builder subclasses, then using a director and a single concrete builder is a valid approach. Focus instead on the spirit of the pattern - namely isolating your director from the details of how the world should be built.

Once your code is working and you are happy with the results, go back and review how your director and builder really interact. Then consider refactoring the builder to extract a common interface to really nail down the contract between the director and the builder.

I find it's much easier to extract out an sensible interface from a working concrete class, then to try to guess up front what this interface might be and try to develop the interface and the class at the same time.

like image 32
Guido Simone Avatar answered Sep 29 '22 23:09

Guido Simone