For sharing my view on stuff and ideas which at least I believe are worthwhile

Chain of Creation

Allow me to propose a new creational design pattern “Chain of Creation”, as the name suggests the pattern is inspired by well known Behavioral pattern “Chain of Responsibility”. The Chain of Creation pattern delegates the task of creating the most suitable instance for processing a set of data to a group of related classes. Each of these classes is unaware of the capabilities of other classes in the chain and is only aware of its own capabilities in handling the data.  The only common link in these classes is the data that is passed between them, the data is passed along until an object which is capable of handling the data is created or the length of chain is exhausted in which case a null is returned.

Applicability

Chain of Creation can be used when

  • Without specifying explicitly you want to create an instance of class from several possible implementing classes based on available data.
  • A class can’t anticipate which kind of object it must create.
  • You want to encapsulate the capability of each class in the class itself so that it can be reused.
  • You want to be able to modify the set of related creational classes that are capable of handling data dynamically at run time.

Consequences of the Chain of Creation

  • The main purpose for this pattern is to reduce dependency between creator and created object.
  • The class made aware of its capabilities and hence can be reused.
  • Any changes to the capabilities of a class does not have impact other classes.

The example below provides a sample implementation for Chain of Creation pattern. The objective is to create a terrain from possible types available and then let the chain of classes provide most suitable vehicle for the terrain.

Terrain.java

package pattern.coc;

public interface Terrain {

	public boolean hasRoads();

	public boolean isRugged();

	public boolean isSandy();

}

City.java

package pattern.coc;

public class City implements Terrain {

	public String getName() {
		return "New Delhi";
	}

	public boolean hasRoads() {
		return true;
	}

	public boolean isRugged() {
		return false;
	}

	public boolean isSandy() {
		return false;
	}
}

Desert.java

package pattern.coc;

public class Desert implements Terrain {

	public String getName() {
		return "Thar Desert";
	}

	public boolean hasRoads() {
		return false;
	}

	public boolean isRugged() {
		return true;
	}

	public boolean isSandy() {
		return true;
	}
}

Forest.java

package pattern.coc;

public class Forest implements Terrain {

	public String getName() {
		return “Sariska Forest”;
	}

	public boolean hasRoads() {
		return false;
	}

	public boolean isRugged() {
		return true;
	}

	public boolean isSandy() {
		return false;
	}
}

Vehicle.java

package pattern.coc;

public interface Vehicle {

	public String getName();

	public void ignition();

	public void accelerate();

	public void brake();

	public void turnOff();
}

Creator.java

package pattern.coc;

public abstract class Creator {

	private Creator successor;

	public Vehicle create(Terrain terrain) {
		if (successor != null)
			return successor.create(terrain);
		else // no suitable creator found
			return null;
	}

	public void setSuccessor(Creator c) {
		this.successor = c;
	}
}

Car.java

package pattern.coc;

public class Car implements Vehicle {

	private static class CarCreator extends Creator {

		public Vehicle create(Terrain terrain) {

			if (!terrain.isRugged() && !terrain.isSandy() && terrain.hasRoads())
				return new Car();
			else
				return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new CarCreator();
	}

	public String getName() {
		return "Car";
	}

	public void ignition() {
		System.out.println("Car ignition");
	}

	public void accelerate() {
		System.out.println("Car accelerated");
	}

	public void brake() {
		System.out.println("Car brake");
	}

	public void turnOff() {
		System.out.println("Car engine off");
	}
}

Jeep.java

package pattern.coc;

public class Jeep implements Vehicle {

	private static class JeepCreator extends Creator {

		public Vehicle create(Terrain terrain) {

			if (terrain.isRugged() && !terrain.isSandy() && !terrain.hasRoads())
				return new Jeep();
			else
				return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new JeepCreator();
	}

	public String getName() {
		return "Jeep";
	}

	public void ignition() {
		System.out.println("Jeep ignition");
	}

	public void accelerate() {
		System.out.println("Jeep accelerated");
	}

	public void brake() {
		System.out.println("Jeep brake");
	}

	public void turnOff() {
		System.out.println("Jeep engine off");
	}
}

AVT.java

package pattern.coc;

public class AVT implements Vehicle {

	private static class AVTCreator extends Creator {

		public Vehicle create(Terrain terrain) {

		if (terrain.isRugged() && terrain.isSandy() && !terrain.hasRoads())
			return new AVT();
		else
			return super.create(terrain);
		}
	}

	public static Creator getCreator() {
		return new AVTCreator();
	}

	public String getName() {
		return “All-terrain Vehicle”;
	}

	public void ignition() {
		System.out.println(“AVT ignition”);
	}

	public void accelerate() {
		System.out.println(“AVT accelerated”);
	}

	public void brake() {
		System.out.println(“AVT brake”);
	}

	public void turnOff() {
		System.out.println(“AVT engine off”);
	}
}

Client.java

package pattern.coc;

public class Client {

	public static void main(String args[]) {

		Desert terrain = new Desert();
		Creator creator = Car.getCreator();
		Creator jeep = Jeep.getCreator();
		Creator avt = AVT.getCreator();
		creator.setSuccessor(jeep);
		jeep.setSuccessor(avt);

		Vehicle v = creator.create(terrain);
		System.out.println("Driving in " + terrain.getName() + " using " + v.getName());

		v.ignition();
		v.accelerate();
		v.brake();
		v.turnOff();
	}
}
About these ads

Comments on: "Chain of Creation" (6)

  1. So what you have is a chain of factories, each one delegating to the other if it doesn’t feel it can create something to match the requirements (in this case, the appropriate vehicle for a terrain).

    The most obvious shortfall I see is in how you each factory in the chain knows if it is the best solution for the requirements. Your example has three different attributes for the terrain; how do we know which vehicle is the best fit? It is subjective. The implementor must carefully link the different factories together to fit what he sees as the reasonable set of choices. I could imagine these subjective criteria changing a lot, which would require changing lots of code.

    If we look at the problem you are trying to solve as, “given a handful of criteria, how do I figure out what object is the best fit”, we see the solution is not linear as your pattern assumes, but (for lack of a better term) a “voting” thing.

    Using your example, each vehicle subclass might be assigned a different weight to how well they match the different requirements. I would think a better solution might be to have the subclasses register with some central factory that used a pluggable engine for weighing the criteria and judging which subclass to use. This would have the added benefit of allowing several developers work in parallel designing their subclasses, instead of contention on both the design and the implementation of the chain you describe.

    Or am I completely off-base?

    • Bobman thanks for your feedback. The most obvious shortfall pointed by you i.e. “each factory in the chain knows if it is the best solution for the requirements” is actually the strength of the pattern. Whole point of the pattern is that each component knows if it’s the best solution for the requirement and presents an instance of itself accordingly.

      Handling of decision criterion by class itself, linear search and careful creation of chain by implementer is something that has been used by chain of responsibility pattern all along. The individual criterion’s may not change as frequently as you imagine and even if it changes, only the class implementing the criterion will be impacted.

      The idea is to move away from central control logic which encapsulates the capability of all the classes and takes a decision on behalf of those classes, with central control if capability of class changes the control logic is impacted and needs to be updated. To make it clearer let’s take a real world example

      Central Control: I let my manager know my capabilities and availability in advance, when a job comes in my manager decides if I am the right fit for the job and assign it to me.

      Chain of creation: I let my manager know if I am interested in job, my manager forwards me job requirement and I decide if I am the best fit, if not interested I forward to the next person I am aware of.

      Also, I do not feel that this pattern would cause contention at design or implementation, a developer implementing a car should not be interested on how a developer working on AVT or jeep are designing/implementing their classes, these are independent pieces of functionality and should not be dependent on each other.

      Use of weighted criterion rather than a specific one would just be a special case of the design pattern which can be easily implemented by putting some logic in Creator class. I hope I was able to provide a satisfactory response to the points raised by you.

      • I think that in the right context it would will be the right solution. But in the essence of this pattern are the “Chain of Responsability” and the “Factory”. I don’t see why we would create a new name just for a combination of existing patterns. If it start to happen every time, it will be very hard to keep a catalog for that :)

        Best regards.

  2. I think it’s a reinvention of a pattern, since it seem very similar to the Builder-Pattern (btw: I agree with Bobman).

    Replace this code:
    Desert terrain = new Desert();
    Creator creator = Car.getCreator();
    Creator jeep = Jeep.getCreator();
    Creator avt = AVT.getCreator();
    Vehicle v = creator.create(terrain);

    with this:
    CarBuilder creator = new CarBuilder();
    // creator.setDefaultCarType(new CarCreator()); // just in case no other creator will do the job
    creator.addCarType(new JeepCreator());
    creator.addCarType(new AVTCreator());
    Desert terrain = new Desert();
    Vehicle v = creator.buildCarForTerrain(terrain);

    The Builder itself can be held responsible for the chaining (simple list instead of chaining) and for selecting a correct model (see below, using “calculateFitness(…)”). The Builder itself can be replaced if necessary (e.g. to select randomly, to select by list, to select by fitness, …).

    public interface Creator {
    /** return a fitness-double 0..1, 0=worst, 1=best) */
    public double calculateFitness(Terrain terrain);
    /** create a vehicle */
    public Vehicle create();
    }

    PS: I omit most of the code, since one might image it, won’t it?

  3. intresting. can you post a class diagram to show the escence of what you are proposing?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Tag Cloud

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: