« An example of the Extension Objects pattern | Inicio | An example of the Command Pattern ( the Java Version ) »

An example of the Extension Objects pattern ( the java version )

Do you remember Professor Coupling?. Do you remember his evil plans to conquer the world?.

Today, we’ll see how the Extension Objects pattern ( or “how to change the interface that a class implements at runtime” ) has helped Professor Coupling. It won’t be an easy task, because this is a complex pattern, but who said that being an evil genius was easy?.

If you remember the last post, Professor Coupling designed a cloning machine that was able to clone any given animal, without knowing it’s race ( or type ), just delegating the creation details to the animal itself.

So that’s the point where our story starts today. Professor Coupling has cloned yet ten thousand sheeps, and nine thousand cows ( he said something like “that’s the exact number I need, muhahahahahahhhhaaaaaa” ). But suddenly, he realizes that he is going to need a lot of sheeps, yes, and a lot of cows, but not all the sheeps nor all the cows will have the same role. Why?. Well, conquering the world is not easy. You need to organize things very well. You need a plan ( an evil plan ).

And Professor Coupling has a plan. He wants to train some of the sheeps, and some of the cows, as his army. He wants them to kill, without asking questions ( sorry for the violence, that’s what happens when you are crazy ). But he also wants some of the sheeps and cows to work in the factories, building weapons. And he also needs some of those sheeps and cows working in the countryside, growing vegetables to feed his army ( remember, Professor Coupling is crazy, but the is not an idiot ). He needs to assign different roles to the clones he has created.

soldierSheep.jpg
A SoldierSheep. No comment.

[Note]. Just to keep the different posts separated, each one showing an example of a pattern and only a pattern, I will start writing the Sheep and Cow classes from scratch. But, Professor Coupling will just add the new code to those classes.

So, the evil genius starts to think: “Right, I have a class that represents a Sheep. And now I need a sheep that behaves like a soldier, and another one that behaves like a peasant, and the same with the cows.”. That sounds like extending the functionality of a class, doesn’t it. That’s exactly the same that Professor Couple thinks. Brilliant!!!. “I will write a SoldierSheep class that extends Sheep, and another class, PeasantSheep, that also extends Sheep” ( insert five minutes of hysterical laughs here ).

But before starting writing code, Professor Coupling notices that maybe that’s not the best solution, because anytime he wants to assign a new role to a Sheep, he will have to write a new subclass ( for instance, an EngineerSheep, or a MaitreSheep,… ). And he doesn’t know in advance which roles he will need to assign to a sheep. It all depends of what he needs in the future. He wants to support the addition of unforeseen interfaces to the Sheep class ( isn’t he a genius? ).

He also notices that this approach has another weak point. He will not be able to re-assign a role. If he creates a SoldierSheep, that will be a SoldierSheep forever, no matter if he needs it to grow onions ( he is crazy, remember, sometimes he has very strange ideas ).

He also notices another subtle weak point. A SoldierSheep and a Sheep are exactly the same: sheeps. The only difference is that one of them has a particular behaviour, but in essence, they are the same.

Professor Coupling is crazy, but he’s not an idiot ( I know, I know, you knew that ). So, he believes he has found enough weak points in his initial idea to start searching google for another solution.

peasantSheep.jpg
A PeasantSheep. Believe it or not, it's enjoying its spare time gardening!

And after a few attempts, he finds a book (Pattern Languages of Program Design, Volume 3, Addison-Wesley, 1998. ), where Erich Gamma ( yes, one of the GoF authors ) wrote a chapter about the Extension Objects pattern.

This pattern intents to anticipate the extension of an object’s interface in the future ( that means: new interfaces can be added to a class at runtime ).

So he starts reading, and laughing, And the more he reads, the more he laughs!!.

The idea is quite simple. A class ( Sheep ) will be able to change the interface it implements at runtime, selecting that interface from a collection of objects ( the Extension Objects ). Each one of those objects will encapsulate one of the roles ( SoldierSheep, PeasantSheep,… ). ( At this moment, Professor Coupling has been laughing for nearly twenty minutes!! ).

How will the Sheep class select the interface to implement?. And how will the Cow class do it?. Well, both classes will implement the following interface:

public interface ISubject { public Role getExtension( String extName ); }

The Sheep also implements an interface to encapsulate the actions it implements as an animal ( eat, moving the legs and arms… )

public interface IBasicActions { public void moveArms( ); public void moveLegs( ); public void eat( ); }

So, the Sheep class will be

public class Sheep implements ISubject, IBasicActions { private SoldierRole soldierRole; private PeasantRole peasantRole; public Sheep( ) { System.out.println( "I'm a sheep" ); } public Role getExtension( String extName ) { Role returnValue = null; if( extName.equals( "SoldierRole" ) ) { if( soldierRole == null ) { returnValue = new SoldierRole( this ); } else { returnValue = soldierRole; } } if( extName.equals( "PeasantRole" ) ) { if( peasantRole == null ) { returnValue = new PeasantRole( this ); } else { returnValue = peasantRole; } } return returnValue; } public void moveArms( ) { // movement implementation System.out.println( "the sheep moves one arm" ); } public void moveLegs( ) { // movement implementation System.out.println( "the sheep moves one leg" ); } public void eat( ) { // implements the way sheeps eat System.out.println( "munch. munch" ); } }

Notice how that class implements the getExtension method, choosing the class it should return from a collection of roles ( that are instance variables ). And the roles?

Here’s the base Role ( I have not implemented anything, but any common functionality to all the roles should be implemented here ).

public abstract class Role { }

So, the SoldierRole:

public class SoldierRole extends Role implements ISoldierActions { private IBasicActions subject; public SoldierRole( IBasicActions subject ) { this.subject = subject; System.out.println( "SoliderBehaviour created" ); } public void destroy( ) { //Specific behaviour System.out.println( "Soldier interface. destroy" ); //Use some of the animal's methods subject.eat( ); } public void moveTo( ) { //Specific behaviour System.out.println( "Soldier Interface. moveTo" ); //Use some of the animal's methods subject.moveLegs( ); } }

And the PeasantRole:

public class PeasantRole extends Role implements IPeasantActions { private IBasicActions subject; public PeasantRole( IBasicActions subject ) { this.subject = subject; System.out.println( "PeasantBehaviour created" ); } public void driveTo( ) { //Specific behaviour System.out.println( "I drive to " ); //Use some of the animal's methods subject.moveArms( ); subject.moveLegs( ); } public void doGardening( ) { //Specific behaviour System.out.println( "OK, gardening" ); //Use some of the animal's methods subject.moveArms( ); } }

Both classes ( SoldierRole and PeasantRole ) implement two different interfaces ( ISoldierActions and IPeasantActions ). Those are the interfaces that the Sheep class will seem to implement.

Look:

public class ProfessorCoupling { public static void main( String[ ] args ) { Sheep sheep = new Sheep( ); ISoldierActions soldierSheep = ( ISoldierActions ) sheep.getExtension( "SoldierRole" ); soldierSheep.destroy( ); IPeasantActions peasantSheep = ( IPeasantActions ) sheep.getExtension( "PeasantRole" ); peasantSheep.doGardening( ); } }

( Insert thirty minutes of hysterical laughs here ). But, hey!!. Wait!!. Professor Coupling has noticed a little problem ( well, it’s not a problem, really, it’s a “difficult solution” ).

The Sheep class knows its extensions ( the roles ). Those extensions are stored in instance variables, so there’s no way to add or remove extensions at runtime.

So he decides to refactor his Sheep class. This class will no longer store its possible extensions in instance variables, but it will manage a collection ( a HashMap, an Object ) that will store them. So, it will be possible to add or remove extensions whenever it’s needed. ( you wouldn’t believe how he’s laughing now ).

So, he refactors the ISubject interface:

public interface ISubject { public Role getExtension( String extName ); public void addExtension( String extName, Role extension ); public void removeExtension( String extName ); }

And the Sheep class ( I don't like the way I've implemented the collection, using an object, but ... )

import java.util.HashMap; public class Sheep implements ISubject, IBasicActions { private HashMap rolesCol; public Sheep( ) { System.out.println( "I'm a sheep" ); rolesCol = new HashMap( ); } public Role getExtension( String extName ) { return ( Role ) rolesCol.get( extName ); } public void addExtension( String extName, Role extension ) { rolesCol.put( extName, extension ); } public void removeExtension( String extName ) { rolesCol.remove( extName ); } public void moveArms( ) { // movement implementation System.out.println( "the sheep moves one arm" ); } public void moveLegs( ) { // movement implementation System.out.println( "the sheep moves one leg" ); } public void eat( ) { // implements the way sheeps eat System.out.println( "munch. munch" ); } }

And Professor Coupling can do something like:

public class ProfessorCoupling { public static void main( String[ ] args ) { Sheep sheep = new Sheep( ); sheep.addExtension( "SoldierRole", new SoldierRole( sheep ) ); ISoldierActions soldierSheep = ( ISoldierActions ) sheep.getExtension( "SoldierRole" ); soldierSheep.destroy(); sheep.removeExtension( "SoldierRole" ); sheep.addExtension( "PeasantRole", new PeasantRole( sheep ) ); IPeasantActions peasantSheep = ( IPeasantActions ) sheep.getExtension( "PeasantRole" ); peasantSheep.doGardening( ); } }

So, the clones created by the cloning machine are able to change the way we look at them at runtime ( first they can be soldiers, then they can be peasants, then whatever role Professor Coupling wants ). He has kept the Sheep abstraction unpolluted with operations that are specific to a client. He could have done so subclassing, defining the client operations in those subclasses, but that will create a hierarchy too difficult to manage.

The next Professor Coupling’s adventure will be easier to follow, I promise. Even evil geniuses need some vacations!.

[Important note]. Some self-criticism. The code that retrieves the roles won’t pass any quality check. Using a string as a key value to set and get those roles is very dangerous.

Comentarios

These articles are great!!!

I am studying design patterns right now, so it is great timing of your part.

Keep 'em coming!

The unique way in which the concept was presented makes it both easy and interesting to read. But it would really be great if you could also give the class diagram.