Showing posts with label PATTERNS. Show all posts
Showing posts with label PATTERNS. Show all posts

Saturday, July 3, 2010

The Observer Pattern

In today's post, I am going to discuss about the observer pattern. This is one of the most widely used patterns in most J2EE applications. I say this because of the inherent simplicity of this pattern and the the fact that it is highly possible that you are already implementing this pattern without actually being aware of it! This is something that certainly cannot be said about other patterns like the Visitor or the Factory pattern.

As I always do, this time as well, i am going to elaborate the usage of this pattern in a fictional - game like situation.

Lets imagine we are playing a horror game. Yea, this time i pick a horror game instead of the good ol FPS!

First, lets begin with a somewhat formal introduction to the pattern.

As the name suggests, the Observer pattern is basically used to associate an object A with a group of other objects that observe any changes in the properties of the object A, and perform some very critical, earth shattering tasks, based upon the change made to the properties of the object A.

Well, its like another way of talking about the event - event listener, model of programming.

There are primarily three major concerns in the Observer pattern.
1) The object being observed - The Observable object.
2) The objects that observe the observable object - The Observer objects.
3) A way to associate and invoke the Observable object with the Observers - The Delegate function.

To be concise - Observer Objects Observe Observable Objects.
That's 5 O's in one sentence!

There two are styles of implementing the Observer pattern - The Push model and The Pull model. These two models differ in the way in which the Observers and the Delegate function are designed. The observable object remains the same. I will elaborate both of these models later in the post and also discuss the pros and cons of both the techniques.

However, now its time to play some game.

The protagonist of our horror game features a very bold player named ScoobyDoo.
So, we create a basic player class with three instance variables :
name, xCoordnate, yCoordinate. Here is the class definition.

public class Player {
    
    private String name;
    private Integer xCooridinate;
    private Integer yCooridinate;

    public Integer getxCooridinate() {
        return xCooridinate;
    }

    public Integer getyCooridinate() {
        return yCooridinate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void moveForward(Integer steps){
        xCooridinate+=steps;
    }

    public void moveBackward(Integer steps){
        xCooridinate-=steps;
    }

    public void jump(Integer height){
        yCooridinate+=height;
    }

    public void fallTo(Integer height){
        yCooridinate=height;
    }
}

I have also added a function that allows the player to move forward and jump(i.e. move upward) and vice versa. These will be used to manipulate the xCoordinate and yCoordinate properties of our our Player.

Now, I don't think a game can be made scary without proper lighting and sound effects. But what makes a game scary is the appropriate timing of these effects.

Lets assume a scene where ScoobyDoo enters an empty room. As of now, the lights are bright and shining. The xCoordinate and yCoordinate of the player are initialized to 0 when the player enters the room.

Now what we want is that when ScoobyDoo is right in the middle of the room, i.e. approximately 10 steps into the room, the lights should suddenly begin to flicker.


Not only that, but we also want a scary sound to start playing in case ScoobDoo tries to act smart and tries to jump up to run out of the room.

Yea, it might sound as if I am being so mean by trying to scare the shit out of this dog, but hey, i am not to blame. I bet this dog would get scared of the sound of his own fart as well!

Okey, back to work.

What we need is a way to observe the coordinates of ScoobyDoo in the room and take appropriate actions when his coordinates cross a certain threshold.

So, here, the Observable object is the Player.

Before we begin we need to define a few interfaces that will be used to generically use and handle Observers and Observables.

Lets see the definition of these interface first.

public interface Observable {
    public void notifyObservers();
    public void addObserver(Observer o);
    public void removeObserver(Observer o);
}


public interface Observer {
    public void update(Object o);
}


Lets create Observers.

public class SoundEffectController implements Observer{

    private boolean isSoundPlaying = false;

    public void playSound(){
        System.out.println("Play an eerie sound");
        isSoundPlaying = true;
    }

    public void update(Object o) {
        if(o instanceof Integer){
            Integer yCoordiante = (Integer)o;
            if(yCoordiante>0 && isSoundPlaying== false){
                playSound();
            }
        }
    }

}



public class LightEffectController  implements Observer{

    private boolean isLightFlickering = false;

    public void flickerLights(){
        System.out.println("Flicker the lights");
        isLightFlickering = true;
    }

    public void update(Object o) {
        if(o instanceof Integer){
            Integer xCoordiante = (Integer)o;
            if(xCoordiante>10 && isLightFlickering==false){
                flickerLights();
            }
        }
    }

}


As you see, there are two observers. The SoundEffectController, and the LightEffectController.

The SoundEffectController is class that manages the sound effects of the room. The light effect controller is a class that manages the lighting effects of the room.

Now, what we need is a way to associate these observers with the events with which they are interested- the change in the xCoordinate and yCoordinate of the Player. This is where the delegate function comes into the picture.

The delegate functions's primary purpose is to pass on control to all the interested Observers upon the occurrence of any event in the Observable object. This is the core function in the observer pattern. It is this function that allows you to have 2 flavors of the Observer pattern. We will first see the Push Model of the observer pattern.

The delegate function is defined in the Observable object. In order to make the delegate function do useful things, the methods that cause a change in the properties of the object, need to invoke the delegate function. Also, the Observable class needs to maintain a list of observers.

In the Push model, the delegate function iterates over each of these observers and passes the relevant information to the Observer. The following code demonstrates the new implementation of the player class using the push model.
And now, here is the new definition of the Player class which now implements the Observable interface.

public class Player implements Observable{
    
    private String name;
    private Integer xCooridinate;
    private Integer yCooridinate;

    private List observers ;

    public Player(String name) {
        this.name = name;
        this.observers=new ArrayList();
    }


    public Integer getxCooridinate() {
        return xCooridinate;
    }

    public Integer getyCooridinate() {
        return yCooridinate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void moveForward(Integer steps){
        xCooridinate+=steps;
        notifyObservers();
    }

    public void moveBackward(Integer steps){
        xCooridinate-=steps;
        notifyObservers();
    }

    public void jump(Integer height){
        yCooridinate+=height;
        notifyObservers();
    }

    public void fallTo(Integer height){
        yCooridinate=height;
        notifyObservers();
    }

    //This is the core function that delegates the change in the state of the
    //Observable object to the observers
    public void notifyObservers() {
        for(Observer o:observers){
            if(o instanceof SoundEffectController){
                o.update(yCooridinate);
            }
            else{
                if(o instanceof LightEffectController){
                    o.update(xCooridinate);
                }
            }
        }
    }

    public void addObserver(Observer o) {
        this.observers.add(o);
    }

    public void removeObserver(Observer o) {
        this.observers.remove(o);
    }
}


Here is the Main class.

public class Main {
    public static void main(String[] args){
        Player myDog = new Player("ScoobyDoo");

        myDog.addObserver(new SoundEffectController());
        myDog.addObserver(new LightEffectController());

        myDog.moveForward(2);
        System.out.println("Nothing yet.");
        myDog.moveForward(3);
        System.out.println("Nothing yet.");

        myDog.moveForward(7);
        
        myDog.jump(3);
        
    }
}


On running the main program, you get the following output.

Nothing yet.
Nothing yet.
Flicker the lights
Play an eerie sound


As is seen in the above code, it is clearly evident that the delegate function - notifyObservers() is invoking a particular function on an Observer to notify it of the changes in state. On close examination, you would notice that the delegate function is not as flexible as we want it to be. This is because, the delegate needs to be aware of the data that each observer is interested in listening to, thereby making the delegate function a tad more complex than it should be. As time progresses and more observers want to be notified of the changes in the Observable object, the delegate function becomes more convoluted as it needs to be aware of the requirements of each type of observer. For example, there may be 'n' number of observers interested in the change in the x coordinate of the player, while there may be 'm' number of observers that may be interested in the change of 'y' coordinate of the player. There might also be 'l' number of observers that may be interested in both the x and y coordinate of the player. The problem certainly becomes harder to solve as the variety and number of observers increases with time.


This is where the pull model comes to the rescue. In the pull model, the delegate function sends the Observable object itself to the Observers. It then becomes the observer's responsibility to extract the the information in which they are interested, from the Observable object. In our case, this can be implemented as follows.

Change the code in notifyObservers() in the Player class to the following


public void notifyObservers() {
        for(Observer o:observers){
                o.update(this);
        }
    }


Change the update function in SoundEffectControler to the following

public void update(Object o) {
        if(o instanceof Player){
            Player p = (Player)o;
            Integer yCoordiante = p.getyCooridinate();
            if(yCoordiante>0 && isSoundPlaying== false){
                playSound();
            }
        }
    }


Change the update function in LightEffectController to the following

public void update(Object o) {
        if(o instanceof Player){
            Player p = (Player)o;
            Integer xCoordiante = p.getxCooridinate();
            if(xCoordiante>10 && isLightFlickering==false){
                flickerLights();
            }
        }
    }


On running the main program, you get the following output.

Nothing yet.
Nothing yet.
Flicker the lights
Play an eerie sound


As you can see from the above code, the complexity has now shifted from the delegate function to the Observer classes. It is now the Observer's responsibility to take extract the information and also perform typecasting to identify the object with which it is being notified.

When you decide to implement the observer pattern, you keep in mind a few things. The push model works great in areas where you have several components that build up a system, and some of these components act as observers to many different types of Observable objects. In this case, you would prefer to provide only a specific portion of information to the observer instead of the entire Observable object. This would greatly increase the decoupling of your Observer components from the Observable components thereby giving you the chance to use the same observer across multiple objects.

The pull model works great if your Observable object is already in place and you are designing components around this Observable object. If there are many observers, and each observer depends of different combinations of the properties of the Observable object. In this case, since the components are being designed with only a particular Observable class in mind, shifting the complexity to the Observer classes seems like a good idea. Each observer would extract the relevant information from a Observable perform necessary actions.

As is the case with all design pattern, the way you choose to implement it depends on multiple factors. Understanding how a particular implementation will impact your solution should be the key concern in deciding upon a particular implementation.


Happy Programming :)
Signing Off
Ryan

Tuesday, April 20, 2010

Implementing Dependency injection using Annotations

Today in this blog post I am going to elaborate a strategy to implement the Dependency Injection pattern using annotations in Java.

Since their introduction in Java 5, annotations have been widely debated. However, as powerful as they are, Annotations are here to stay. This post requires that the reader has basic knowledge of Annotations and a little bit of reflection. Annotations are extremely handy when used in conjunction with the Reflection API.

In the following examples, i will demonstrate a way to inject fields and methods into a class using annotations.
We will use annotations to indicate that the fields need to be injected.

I have a very simple class hierarchy- ParentClass and ChildClass. The ChildClass extends the ParentClass as indicated by the name.

Lets see the declaration of these basic classes.

ParentClass.java
package annotationExp.di2;

/**
 *
 * @author ryan
 */

class ParentClass {

    public void method() {
        System.out.println("Parent Class");
    }
}



ChildClass.java
package annotationExp.di2;

/**
 *
 * @author ryan
 */
class ChildClass extends ParentClass{

    public void method() {
        System.out.println("Child Class");
    }
}

As seen, there is nothing out of the ordinary in these classes.

Now lets create a class called SampleClass that contains a reference of a parent class.

SampleClass.java (Without any annotations)
import java.util.Date;

/**
 * This is the class that needs dependecy injection of
 * the implementation class of the ParentClass reference.
 * @author ryan
 */
class SampleClass {

    
    private ParentClass parentReference;

    private Date startDate;
    private Date endDate;

    public ParentClass getParentReference() {
        return parentReference;
    }

    public void setParentReference(ParentClass parentReference) {
        this.parentReference = parentReference;
    }

    public Date getEndDate() {
        return endDate;
    }

    public Date getStartDate() {
        return startDate;
    }

    
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }


    
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }
    
}

Now suppose, at runtime, we need to inject an object of the child class in the parent class reference. And also, we need the startDate and endDate fields to have default values.

If we were to implement this in the normal way, we would have to write the initialization code for the parentReference and the dates in the main class where we create the object of our SampleClass, by using getters and setters.


But since such a requirement may exist at several places, we may end up writing the same piece of code redundantly at all the places where such an initialization is required.

Let us now see how annotations can help us clean up this mess.

We first begin by declaring the annotations.

FieldInject.java
package annotationExp.di2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * This is a field level injector
 * @author ryan
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldInject {
}



DateInject.java
package annotationExp.di2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * This is a method level injector
 * @author ryan
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DateInject {int delay() default 0;}



As you can see, these annotations have been marked with a retention policy of RUNTIME because we need to inspect the annotations at runtime to inject the necessary values.

The annotation DateInject also specifies the parameter to indicate the offset number of days from the current date that should be used when calculating the date.


Now, lets declare our sample class again, but this time we use annotations to indicate that we need certain methods and fields to be injected.

SampleClass.java (With Annotations)
import java.util.Date;

/**
 * This is the class that needs dependecy injection of
 * the implementation class of the ParentClass reference.
 * @author ryan
 */
class SampleClass {

    @FieldInject
    private ParentClass parentReference;

    private Date startDate;
    private Date endDate;

    public ParentClass getParentReference() {
        return parentReference;
    }

    public void setParentReference(ParentClass parentReference) {
        this.parentReference = parentReference;
    }

    public Date getEndDate() {
        return endDate;
    }

    public Date getStartDate() {
        return startDate;
    }

    @DateInject(delay=10)
    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }


    @DateInject
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }
    
}


Now lets write our main class that creates an object of SampleClass and also handles dependency injection by using a few methods.


TestDI.java

package annotationExp.di2;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;

/**
 * This class demonstrates handling dependency injection for annotations placed
 * methods and variables.
 * @author ryan
 */
public class TestDI {

    public static void main(String[] args) throws Exception{

        SampleClass sc = new SampleClass();

        /*
        * This function handles dependency injection(DI) for the given object.
        * In a framework,this can be handled by interceptors or preprocessors.
        */
        handleAnnotations(sc);

        /*
        * There is no need to initialize the parentReference as
        * it has already been initialized via dependency injection.
        * Hence we will not get a null pointer exception here
        * as long as the function that handles DI is executed and
        * the field is marked for DI.
        */
        sc.getParentReference().method();
        System.out.println("Start Date : "+sc.getStartDate());
        System.out.println("End Date : "+sc.getEndDate());

    }

    public static void handleAnnotations(T object) throws Exception
    {
        handleFieldAnnotations(object);
        handleMethodAnnotations(object);
    }


    public static  void handleFieldAnnotations(T object) throws Exception{
        Field[] fields = object.getClass().getDeclaredFields();
        handleFieldInject(fields, object);
        //handle other field level annotations one by one
    }

    public static  void handleMethodAnnotations(T object) throws Exception{
        Method [] methods = object.getClass().getMethods();
        handleDateInject(methods, object);
    }

    public static void handleDateInject(Method[] methods,T object) throws Exception{
       System.out.println("Method : "+methods.length);
        for (Method method : methods) {
            System.out.println("Method : "+method.getName());
            System.out.println("Annotations : "+method.getAnnotations().length);
            System.out.println("Is DateInject Present : "+method.isAnnotationPresent(DateInject.class));
            if (method.isAnnotationPresent(DateInject.class)) {
                Class[] parameterTypes = method.getParameterTypes();
                if(parameterTypes.length==1&&parameterTypes[0].equals(Date.class))
                {
                    Annotation[] annotations= method.getAnnotations();
                    DateInject annotation = method.getAnnotation(DateInject.class);
                    if(annotation.delay()==0)
                    {
                        method.invoke(object, new Object[]{new Date()});
                    }
                    else
                    {
                        int delay = annotation.delay();
                        Calendar c = Calendar.getInstance();
                        c.add(Calendar.DAY_OF_MONTH,delay);

                        method.invoke(object, new Object[]{c.getTime()});
                    }
                }
                else
                {
                    System.out.println("Method "+method.getName()+" : Cannot be injected with a Date");
                }
            }
        }
    }

    public static void handleFieldInject(Field[] elems,T object) throws Exception{
        System.out.println("Fields : "+elems.length);
        for (Field elem : elems) {
            System.out.println("Field : "+elem.getName());
            System.out.println("Annotations : "+elem.getAnnotations().length);
            System.out.println("Is Inject Present : "+elem.isAnnotationPresent(FieldInject.class));
            if (elem.isAnnotationPresent(FieldInject.class)) {
                if(elem.getType().equals(ParentClass.class))
                {
                    elem.setAccessible(true);
                    elem.set(object, new ChildClass());
                    System.out.println("Child class is set");
                }
            }
        }
    }

}


As can be seen in the main function, the task of handling the dependency injection has been delegated to a separate method that analyzes the annotations present on the SimpleClass and injects the necessary values into the fields.
In a framework like struts, you can easily use this feature to handle dependency injection in an interceptor and mark the fields in your struts action to be injected using annotations. This will also help in centralizing the point of object creation an open the doorway to ways of implementing other creational design patterns such as the AbstractFactory and FactoryMethod.

I hope this helps.

Happy Programming :)

Signing Off
Ryan

Sunday, January 31, 2010

The Chain Of Responsibility Pattern

Today, in this blog post, I am going to discuss about the chain of responsibility pattern. As the name suggests, the pattern deals with a chain of objects where each object is aware of the next object that needs to be called.

Lets see where this pattern can be used.

  1. When your request contains data that needs to be processed by different objects where each object deals with different parts of the requests.
  2. When your request contains data that needs to be processed at several levels and processing can be halted at any of the levels.
  3. When your request needs to be modified before reaching its final destination.


Lets elaborate on the concept using an example.

Scenario :

I will try to explain this pattern as well by taking an example of a game as I have been doing in my previous posts. Lets assume that we have a game with two players. Each player can attack the other player. When a playerq attacks player2 and vice versa, the victim player's health is reduced. Now the game isin't much fun until you have some extra features like a  'Shield' to protect the players.
Now suppose player1 has a shield that can absorb 30 percent of the damage of the attack. And player 2 has a Shield that can absorb 70 percent of the damage of the attack. But when a player attacks another player, how will the damage be absorbed by the shield??

So, here are our requirements.

  1. A player is not aware of the properties of the shield that protects him.
  2. A player is not aware of the number of shields that protect him.
  3. A player is not aware of the shields that protect the other player.
  4. A shield can be attached to any player.
  5. A shield absorbs the damage to the level set by its configuration.
  6. A shield is not aware whether the next object that will absorb the remaining damage is a shield or a player.


So, we have a candidate for the Chain of responsibility pattern.

Using the chain of responsibility pattern to solve the scenario

In this scenario, in order to implement the chain of responsibility pattern, we are going to create an interface called 'Damageable'. The interface declares a function - int absorb(int damageValue). The purpose of the function is to absorb a damage and return the damage that could not be absorbed. Both our Player class and our Shield class implement this interface and hence both of them are Damageable objects. The player class saves as its instance variable, the next damageable object to which it can pass on the damage before it can process the damage itself. The shild object also stores a similar variable in its instance variable the informs it of the next object in the chain that can absorb the damage. In the 'absorb' method of the Player class, the player checks if there is any damageable object in its chain that can process the damage. If there is such an object, the player delegates the process of absorbing the damage to the next damageable object in the chain. This continues until the chain returns with the actual value of the damage that can be processed by the player, for which the player calls the 'reduceHealth' method.

The following code example demonstrates an implementation of the above scenario using the chain of responsibility pattern in Java.

Damageable.java

public interface Damageable {
    //Returns the damageValue that it could not absorb.
    public int absorb(int damageValue);
}


Player.java

public class Player implements Damageable{
    private int health;
    private Damageable nextDamageableObject;
    private String name;

    public Player() {
        health=100;
    }

    public int reduceHealth(int value) {
        System.out.println("Health Before Reducing : "+ health);
        if(value<=health)
        {
            health-=value;
            value=0;
        }
        System.out.println("Health After Reducing : "+ health);
        return value;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public void setNextDamageableObject(Damageable nextDamageableObject) {
        this.nextDamageableObject = nextDamageableObject;
    }

    public Damageable getNextDamageableObject() {
        return nextDamageableObject;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
    public int absorb(int damageValue) {
        if(nextDamageableObject!=null)
        {
            damageValue = nextDamageableObject.absorb(damageValue);
        }
        //After all the damageable objects have absorbed the damage,
        //reduce the player's health by the specified amount
        System.out.println("Finaly Attempting To Reduce "+ this.getName() + "'s health by "+damageValue);
        return reduceHealth(damageValue);
    }


    public void attack(Player p,int damageValue)
    {
        p.absorb(damageValue);
    }
}
Shield.java
public class Shield implements Damageable{
    private int damageAbsorbPercent;
    private Damageable nextDamageableObject;
    private String name;

    public Shield(int damageAbsorbPercent, Damageable nextDamageableObject, String name) {
        this.damageAbsorbPercent = damageAbsorbPercent;
        this.nextDamageableObject = nextDamageableObject;
        this.name = name;
    }

    
    public int getDamageAbsorbPercent() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Damageable getNextDamageableObject() {
        return nextDamageableObject;
    }

    public void setNextDamageableObject(Damageable nextDamageableObject) {
        this.nextDamageableObject = nextDamageableObject;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    

    public int absorb(int damageValue) {
        int absobedValue = (damageValue* damageAbsorbPercent)/100;
        damageValue = damageValue-absobedValue;
        System.out.println(this.name + " absorbed damage % (" + damageAbsorbPercent +")");
        
        //The shield passes on the damage to the next damageable object in the chain.
        if(nextDamageableObject!=null)
        {
            damageValue = nextDamageableObject.absorb(damageValue);
        }
        return damageValue;
    }
}
Game.java
public class Game {
    private Player player1;
    private Player player2;

    public Game() {
    }

    public Player getPlayer1() {
        return player1;
    }

    public void setPlayer1(Player player1) {
        this.player1 = player1;
    }

    public Player getPlayer2() {
        return player2;
    }

    public void setPlayer2(Player player2) {
        this.player2 = player2;
    }
    
}
Main.java
public class Main {
    public static void main(String[] args)
    {
        Game game=new Game();
        Player player1 = new Player();
        Player player2 = new Player();

        player1.setName("Player 1");
        player2.setName("Player 2");

        Shield s1=new Shield(30, null, "Normal Shield1");
        Shield s2=new Shield(70, null, "Power Shield");

        player1.setNextDamageableObject(s1);
        player2.setNextDamageableObject(s2);

        player1.attack(player2, 30);
        System.out.println("\n");
        player2.attack(player1, 30);


        //Now add another shiled to the player1
        Shield s3=new Shield(30, player1.getNextDamageableObject(), "Normal Shield2");
        player1.setNextDamageableObject(s3);
        System.out.println("\nAdded Another Shiled to player1 which absorbs 30 percent damage");

        player1.attack(player2, 30);
        System.out.println("\n");
        player2.attack(player1, 30);
    }
}

Following is the output that I get on my console when I run the main program.

Power Shield absorbed damage % (70)
Finaly Attempting To Reduce Player 2's health by 9
Health Before Reducing : 100
Health After Reducing : 91


Normal Shield1 absorbed damage % (30)
Finaly Attempting To Reduce Player 1's health by 21
Health Before Reducing : 100
Health After Reducing : 79

Added Another Shiled to player1 which absorbs 30 percent damage
Power Shield absorbed damage % (70)
Finaly Attempting To Reduce Player 2's health by 9
Health Before Reducing : 91
Health After Reducing : 82


Normal Shield2 absorbed damage % (30)
Normal Shield1 absorbed damage % (30)
Finaly Attempting To Reduce Player 1's health by 15
Health Before Reducing : 79
Health After Reducing : 64


Signing Off
Ryan

Saturday, January 30, 2010

The Command Pattern

Today, in this post I am going tot talk about the command pattern and implement it in Java. The command pattern is a behavioral pattern whose primary objective is to decouple the sender from the receiver in such a way that the sender is not even aware of the type of the receiver of the command.

So, lets see where this pattern can be used.

The command pattern can be used in situations where you need a perform a given task on a number of objects of different types. But in each of these objects, not only is the implementation dependent on the type of the object, but also the functionality is completely different from the other objects.

Lets illustrate with the help of an example.

Sample Scenario :

As in my other posts, I will try to explain the scenario by means of examples of a game.
I believe that many of us have played First Person Shooter(FPS) games where you go on a mission and clear each level by destroying several enemies by using ruthless gunpower (and sometimes good strategies as well). One thing that is common among most of the FPS is that you have a number of weapons and each one of them has a primary attack and a secondary attack. The primary attack and secondary attack are characteristic features of that specific weapon. But when you fire the weapon, all you do is click your left mouse button for primary attack and click your right mouse button for secondary attack. What happens when you click on the left/right mouse button is something that is weapon specific.

Now, lets map this scenario to the command pattern. The following requirements are clearly visible from the situation.
  1. The client(yourself), issues two types of commands - primary attack, secondary attack.
  2. Each weapon has different types of attack mechanisms that it can perform.
  3. For each weapon, you need to associate your primary attack and secondary attack to one of the predefined attack mechanisms of your weapon.

You need to decouple the sender's commands i.e. the primary attack and secondary attack command from knowing the actual attack mechanism being executed. This gives you the ability to associate the primary attack command with a different mechanism in the future. for example, if the user chooses to make his left click function as the right click and the right click function as the left click.

Here is a sample description of my game components.
I have 2 weapons in my game. The Plasma Gun and the Shotgun. The Plasma Gun has 2 modes of attack - normal fire and blast fire. The Shotgun has 2 modes of attack - Single shot attack, and dual shot attack. Initially, what I want to do is to make one of these mechanisms the primary attack and secondary attack for each weapon.

Let's see how this could have been done without the command pattern and the problems that would arise.

Firstly, you would declare a base class called Weapon, that would have 2 functions- primary attack and secondary attack. Then, you would subclass the Weapon class and create 2 new classes - Shotgun and PlasmaGun that would override the primary attack and secondary attack functions. Your client would create objects of the weapons and call the primary attack and secondary attack functions on the objects and the code for your weapon specific functionality would execute.

That's pretty simple eh?

Oh, but wait! What if I want to swap my mouse functions?? i.e. The left click becomes the right click? Or what if one fine day in the future I decide that each gun has 5 attack mechanisms, but the user has to select which mechanism can be activated by which input- right click or left click. Os suppose you have added a new  gun with a new attack mechanism and want to associate it with the middle click. What will you do then?? Will you add new methods to your Weapon class?? Will you use several boolean flags to determine what function will be called when? Or worse of all, will you resort to complex techniques such as reflection?

The issue here is that you certainly don't want your client want to know what changes have been made at the level of your Weapon classes. And also, you don't want your classes to be aware of the type of command issued by the client. i.e. the weapons should not be aware whether the client is issuing a primary attack command or a secondary attack command.

The Command Pattern to the rescue!

The command pattern decouples the client from the destination by acting as a middleman and converting the client request to the appropriate destination request. In the code that follows, I will demonstrate how to achieve this functionality. Lets first discuss what the code will do.

Firstly, I will create my Shotgun and PlasmaGun classes without the need of implementing any superclasses or superinterfaces for this scenario. The Shotgun class will have 2 mehtods- one to fire a single shot, and another to fire a dual shot. Similarly the PlasmaGun will have 2 methods - One for normal fire and the other for a blast fire. These classes are not aware of the concept of a primary attack and secondary attack.

Now, I will create a Command interface that has one method- execute(). Then I create classes that implement the Command interface, one class for each command issued to a gun. i.e. Primary/Seconday Attack for shotgun, and primary/seconday attack for PlasmaGun. So, 4 command classes. All these command classes have a private instance of the gun over which they will execute. In the execute function, we will call the appropriate function of the gun classes.

The beauty of this approach is that the Gun classes do not know what is a primary or a secondary attack, and the client does not need to know what is the exact method that will be called when is issues the primary and secondary attack command.

The problem with this approach is that the for each type of command, we will have to create new command classes. This can considerably increase the classes that you may need to manage and can become a problem if you have several such functionalities, However, being a design pattern, it is not bound to suit the requirement for all scenarios. So, its up to u to decide when and where the command pattern will be useful in your project.

Following is the implementation of the above scenario using the Command pattern in Java.


PlasmaGun.java

public class PlasmaGun {
    public boolean firePlasmaShot()
    {
        System.out.println("Plasma Fire : Normal");
        return true;
    }

    public boolean firePlasmaBlast()
    {
        System.out.println("Plasma Fire : Blast");
        return true;
    }
}


ShotGun.java

public class ShotGun {

    public boolean fireSingleShot() {
        System.out.println("ShotGun Fire : Single");
        return true;
    }

    public boolean fireTripleShot() {
        System.out.println("ShotGun Fire : Triple");
        return true;
    }
}


Command.java

public interface Command {
    public void execute();
}



PlasmaGunNormalFireCommand.java

public class PlasmaGunNormalFireCommand implements Command{
    private PlasmaGun gun;

    public PlasmaGunNormalFireCommand(PlasmaGun gun) {
        this.gun = gun;
    }

    public void execute() {
        gun.firePlasmaShot();
    }
}



PlasmaGunBlastFireCommand.java

public class PlasmaGunBlastFireCommand implements Command{
    private PlasmaGun gun;

    public PlasmaGunBlastFireCommand(PlasmaGun gun) {
        this.gun = gun;
    }

    public void execute() {
        gun.firePlasmaBlast();
    }
}



ShotGunSingleShotCommand.java

public class ShotGunSingleShotCommand implements Command{
    private ShotGun gun;

    public ShotGunSingleShotCommand(ShotGun gun) {
        this.gun = gun;
    }

    public void execute() {
        gun.fireSingleShot();
    }
}



ShotGunTripleShotCommand.java

public class ShotGunTripleShotCommand implements Command{
    private ShotGun gun;

    public ShotGunTripleShotCommand(ShotGun gun) {
        this.gun = gun;
    }

    public void execute() {
        gun.fireTripleShot();
    }
}



WeaponControl.java


public class WeaponControl {
    private Command primaryAttackCommand, secondaryAttackCommand;

    public WeaponControl(Command primaryAttackCommand, Command secondaryAttackCommand) {
        this.primaryAttackCommand = primaryAttackCommand;
        this.secondaryAttackCommand = secondaryAttackCommand;
    }

    public void primaryAttack()
    {
        primaryAttackCommand.execute();
    }

    public void secondaryAttack()
    {
        secondaryAttackCommand.execute();
    }
}


Main.java

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        ShotGun sg=new ShotGun();
        ShotGunSingleShotCommand sgSingleShotCmd= new ShotGunSingleShotCommand(sg);
        ShotGunTripleShotCommand sgTripleShotCmd = new ShotGunTripleShotCommand(sg);

        PlasmaGun pg=new PlasmaGun();
        PlasmaGunNormalFireCommand pgNormalFireCmd= new PlasmaGunNormalFireCommand(pg);
        PlasmaGunBlastFireCommand pgBlastFireCmd = new PlasmaGunBlastFireCommand(pg);

        WeaponControl shotGunControl=new WeaponControl(sgSingleShotCmd, sgTripleShotCmd);
        WeaponControl plasmaGunControl=new WeaponControl(pgNormalFireCmd, pgBlastFireCmd);

        shotGunControl.primaryAttack();
        plasmaGunControl.secondaryAttack();

        shotGunControl.secondaryAttack();
        plasmaGunControl.primaryAttack();

    }

}


Signing Off
Ryan

Thursday, January 28, 2010

The Visitor Pattern

The visitor pattern is one of those patterns that seems to be quite perplexing in the beginning, but is quite useful as well. It took me the longest to understand this pattern as compared to others, mainly because of the drawbacks that this pattern has and due to the various ways in which it can be implemented. In this post, I will try to keep things simple and implement it in a way that I feel, will make it easier to understand.

Let's first see where this pattern can be used.
Suppose that you have a class that for which you have already defined a number of methods. But you observe that similar methods exist in other classes as well, but with subtle differences. Usually, this can be implemented by means of inheritance wherein you keep the common functionality in the superclass and override the necessary methods only in cases where you need to.

Now suppose you already have a set if similar classes. But due to some business requirement, you need to add a certain set of functionality to all those classes. What would you do in the normal approach? Add a method to each of those classes? Ok, you would. But suppose, such requirements keep coming and these requirements are not intended to be permanent. For example, suppose you need a given functionality in the current release of your product, but somehow, you don't feel the need to have that functionality to become the core part of your classes because in the next release, they might become irrelevant.

In my opinion, the Visitor pattern lets you create a fall back mechanism in your classes for exactly the above mentioned scenario. Following are the steps that you can follow :


  1. Declare your class to implement a Visitable interface and implement a method in your classses that accepts a Visitor as an argument.
  2. Create concrete Visitor class that knows about group of classes for which it has to provide the new functionality. It does this by declaring overloaded methods, having the same name but taking in arguments that correspond to the classes for which you want to add the functionality.
  3. In the visitor method of your class, dispatch control to the appropriate method of your visitor class by passing 'this' as the argument. Or you can also pass control to the visitor class, which determines which method needs to be called based upon the type of argument it receives


Lets see an example.

Scenario :
I have a game which has a player. A player can carry 2 weapons. A player can accumulate points in a game. I have 2 types of weapons - ShotGun and a MagicWand. Every weapon has a primary and a secondary attack mechanism which is implemented by each weapon in a weapon specific way. A Shotgun's secondary attack is can be enabled or disabled at any point in the game by setting a boolean property on the Shotgun. A MagicWand has a power level which can be increased/decreased as the game progresses.

Now suppose that you have made all the remaining components of the game. And the game is functioning. Now, all of a sudden, you wake up one morning and decide to add three new features to your game:

  • The shotgun's secondary attack is enabled when the player reaches level 2 or higher
  • The MagicWand's power level is increased by 2 points at the beginning of each level.
  • The player is to be given level clearance bonus points at each level.


So, how do you implement it??

Approach 1 : The normal approach
Create a method called upgrade(int level) in your Player and Weapon class. Override the upgrade in the subclasses to upgrade the specific weapons. The problem with this approach is that for each such new business requirement, you will end up expanding the functionality of your core classes. However the inherent simplicity of this technique will play a vital role in choosing this technique. I believe that one can prefer this technique over the Visitor Pattern Based approach especially if the classes will require the functionality as a core functionality. But if thats not the case, then you certainly don't want to clutter your classes with business logic.

Approach 2 : Helper classes
This approach is pretty obvious. Create a helper class that does all the dirty work for you. You can implement it in any way you find suitable. I am not going to elaborate on this because the possibilities are far too many to be discussed here. So, that's left completely up to you.

Approach 3 : Visitor Pattern
This is by far the most complicated approach of the three approaches, but all the more extensible. In the following examples, observe carefully how I try to use the Visitor Pattern to implement the business requirement of my scenario. There are two core interfaces. One is the Visitor interface, that declares a single method called visit(Visitable visitable). The other is the Visitable interface that declares an accept(Visitor visitor) method. The classes of my domain, namely Player and Weapon, implement this interface. When a Visitable object is visited by a visitor, it accepts it and gives control to the visitor to execute the new functionality for that object by passing itself as an argument to the visit method of the visitor. My concrete visitor class is the LevelUpgradeVsitor that will provide the functionality to upgrade the objects passed to it.
Enough with that talking. Lets see some code now babay..

Visitor.java

public interface Visitor {
    public void visit(Visitable visitable);
}


Visitable.java

public interface Visitable {
    public void accept(Visitor visitor);
}

Weapon.java

public interface Weapon extends Visitable{
    public void primaryAttack();
    public void secondaryAttack();
}

Player.java

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author ryan
 */
public class Player implements Visitable{
    private List <Weapon> weapons;
    private int points;

    public Player()
    {
        weapons=new ArrayList <Weapon>();
    }

    public List <Weapon> getWeapons() {
        return weapons;
    }

    public void setWeapons(List <Weapon> weapons) {
        this.weapons = weapons;
    }

    public boolean addWeapon(Weapon w)
    {
        weapons.add(w);
        return true;
    }

    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
        
        for(Weapon w: weapons)
        {
            w.accept(visitor);
        }
    }

}

ShotGun.java

public class ShotGun implements Weapon{

    private boolean dualShotEnabled;

    public ShotGun()
    {
        dualShotEnabled=false;
    }

    public void setDualShotEnabled(boolean dualShotEnabled) {
        this.dualShotEnabled = dualShotEnabled;
    }

    public boolean isDualShotEnabled() {
        return dualShotEnabled;
    }
    

    public void primaryAttack() {
        System.out.println("ShotGun : SingleShot");
    }

    public void secondaryAttack() {
        if(dualShotEnabled)
        {
            System.out.println("ShotGun : DualShot");
        }
    }

    public void accept(Visitor visitor) {
        
        visitor.visit(this);
    }

}


MagicWand.java

public class MagicWand implements Weapon{
    private int powerLevel;

    public void setPowerLevel(int powerLevel) {
        this.powerLevel = powerLevel;
    }

    public int getPowerLevel() {
        return powerLevel;
    }
    

    public void primaryAttack() {
        System.out.println("Magic Wand(Power level : "+powerLevel+") : Primary Attack.");
    }

    public void secondaryAttack() {
        System.out.println("Magic Wand(Power level : "+powerLevel+") : Secondary Attack.");
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

LevelUpgradeVisitor.java -- The implementation of the Visitor Pattern. You can have many such visitors based upon different business requirements.

public class LevelUpgradeVisitor implements Visitor{

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }
    
    public void visit(Visitable visitable) {
        
        if(visitable instanceof Player)
        {
            upgrade((Player)visitable);
            System.out.println("Player Upgraded");
        }
        else
        {
            
            if(visitable instanceof ShotGun)
            {
                upgrade((ShotGun)visitable);
                System.out.println("ShotGun Upgraded");
            }
            else
            {
                
                if(visitable instanceof MagicWand)
                {
                    upgrade((MagicWand)visitable);
                    System.out.println("MagicWand Upgraded");
                }
            }
        }
    }

    public void upgrade(Player p)
    {
        int bonus=level*100;
        System.out.println("Adding Level Bonus For Player : "+ bonus);
        p.setPoints(p.getPoints()+bonus);
    }

    public void upgrade(ShotGun s)
    {
        if(level>=2)
        {
            s.setDualShotEnabled(true);
        }
    }

    public void upgrade(MagicWand m)
    {
        if(level>=2)
        {
            m.setPowerLevel(m.getPowerLevel()+2);
        }
    }
}

Game.java

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author ryan
 */
public class Game implements Visitable{
    private Player player1;
    private int level;
    
    public Game() {}


    public Player getPlayer1() {
        return player1;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    
    public void setPlayer1(Player player1) {
        this.player1 = player1;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
        player1.accept(visitor);
    }

}


Main.java

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Game game=new Game();
        LevelUpgradeVisitor luv = new LevelUpgradeVisitor();

        Player p=new Player();
        ShotGun sg=new ShotGun();
        MagicWand mw= new MagicWand();
        

        //Initialize the Player's values
        p.setPoints(10);
        p.addWeapon(sg);
        p.addWeapon(mw);

     
        //Lets Initialize the game.
        game.setPlayer1(p);
        game.setLevel(1);

        
        
        System.out.println("Before Level Upgrade");
        System.out.println("Initial Level "+game.getLevel());
        System.out.println("Initial Player Points : " + game.getPlayer1().getPoints());
        game.getPlayer1().getWeapons().get(0).primaryAttack();
        game.getPlayer1().getWeapons().get(0).secondaryAttack();
        game.getPlayer1().getWeapons().get(1).primaryAttack();
        game.getPlayer1().getWeapons().get(1).secondaryAttack();



        //Upgrade Level
        game.setLevel(2);
        luv.setLevel(game.getLevel());
        game.accept(luv);


        System.out.println("\n\nAfter Level Upgrade");
        System.out.println("New Level "+game.getLevel());
        System.out.println("New Player Points : " + game.getPlayer1().getPoints());
        game.getPlayer1().getWeapons().get(0).primaryAttack();
        game.getPlayer1().getWeapons().get(0).secondaryAttack();
        game.getPlayer1().getWeapons().get(1).primaryAttack();
        game.getPlayer1().getWeapons().get(1).secondaryAttack();


    }

}



Please not that in in order to keep things simple, I have used a simple if-else structure to determine the appropriate method to be invoked. This could also have been done using reflection in fewer lines of code. But  I thought it would unnecessarily complicate things for an introductory article as our motive here is to learn about the pattern rather that learn about the pros and cons of using reflection to implement this pattern. If you have better ideas to implement this scenario using this patter, please comment. I'd love to learn a new way to do stuff. But I sincerely hope that the example is lucid enough to help you understand the objective of this pattern. Cheers!


Signing Off
Ryan

Tuesday, January 26, 2010

The Decorator Pattern

Patterns.. Patterns.. Patterns! Patterns have become something that surround us everywhere. Well, not everywhere in the real world, but definitely so in the world of Programing Languages.

Today, in this post, I am going to write about the Decorator Pattern. And of course, i will implement it in source code using Java. Doing a simple search on Google tells you that one of the best examples of this pattern's implementation is the classes of the package java.io. BufferedReader, BufferedWriter, FileReader, FileWriter etc etc, are all examples of using the decorator pattern.

So, What is the decorator pattern?
The decorator pattern, as its name suggests, is a pattern that lets you decorate an 'object' by adding or removing certain features. Note that I emphasize the word 'object'. Lets see why.

I assume that the reader of this post is aware of the concept of inheritance and its implementation in Java.

Now lets illustrate the concept by an example. Most of us might have played computer games ryt? There are many games that let 2 or more players play at the same time against several computer players(called Bots). Bots are similar to computer players, but they differ in the way they play because the computer handles their gameplay. And most of the times, we find that bots have a few different features as compared to human players.For example, a bot has a skill level/difficulty level, whereas a human player may have experience points. And both might have common features 'health' etc etc.

So, if we were to model this scenario using OOPS, one possible way would be to create a base class called Player with attributes common to all Player's like 'health', and functions like 'play()' and 'reduceHealth(). Now we can have a class called 'HumanPlayer' that extends the Player class and adds features like 'experience points', overrides the play() method and the reduceHealth() method.

We can also have a class 'Bot' that extends the 'Player' class that overrides the play() and reduceHealth() functions and attributes like skillLevel.

We can have a Game class that has a list of players, and a list of Bots.

Its pretty simple till now ryt? The game begins by initializing the player list with player objects and the Bot list with Bot objects. Everyone plays and everyone is happy.

But if games were so simple, they wouldn't be so much fun now, would they? Lets try do add a new feature to our game. Lets suppose that when a human player interacts with a certain object in the game landscape, he becomes a power player such that for any kind of attack that he receives by the bots, his health is reduced by only 1 unit instead of being reduced by several units and inflicted by the bots. (Note : The game is responsible for handling the duration of the powerplay.)

Now, there are 2 approaches to implement this feature.



  1. The Normal Approach : Subclass the HumanPlayer class and override the reduceHealth() method in the subclass. When the player in the game ineracts with the object that gives him a power play, create a new object of this subclass, and initialize it with the values in the already existing HumanPlayer object and use this new subclassed object in your game.

    Now, the problem with this approach is that when you create a subclass for a given scenario, you are adding another node in the inheritance hierarchy that lets you create a whole new bunch of objects that behave differently for a given scenario. Suppose you have 20 such scenarios, you will have to create 20 subclasses in the hierarchy just to give 20 different powers to your Human players. This doesn't make much sense when you realize that you will always be using the features of the already existing HumanPlayer in your game for each subclassed object that you create. Waste of precious memory? Ya, you guessed right. So, what do we do? This is where the decorator pattern comes to the rescue.

  2. The Decorator Pattern Approach : If we observe the requirements carefully, we can see that the what we actually need to do is to decorate the player, who has managed to get a power play by interacting with a game object; with a differently implementation of the reduceHealth() method. Notice that I only need to decorate a single object at runtime, the object that will use power play.

    So, what we need to do is to create a new class called PowerPlayer that subclasses the Player class and overrides the implementation of the reduceHealth() for the power play mode. This class is initialized with an instance of a Player to which it delegates other responsibilities.

    Note that we can also choose to subclass the HumanPlayer class. But that can create a restriction in the game when in the future, you decide to enable even bots to have a power play. In that case you would have to duplicate the reduceHealth() code for the Bot.

    Maybe you never want to do such a thing. Maybe you might have to. The decision of the class that you choose to subclass is a design decision and is based upon your foresight and requirements.

    Since this is just an example, and in order to keep it simple, I will subclass the HumanPlayer.

    By subclassing the HumanPlayer, now what I can have in my game is a feature that allows several HumanPlayer objects to coexist but only a single HumanPlayer object to be a power player as determined by the game. Had I chosen to subclass the Player class, I could have had any player- bots or human players, to be able to possess a power play feature by 'decorating' selected player objects with the PowerPlay feature.


Here is the implementation. The only difference here is that I am going to have only one player and several bots, just to keep it simple and not confuse game logic with the logic of implementing the decorator class. The PowerPlayer is my decorator class in this example. But please note that this is only a demonstration of concepet. And it might not be feasible in all situations to apply this pattern. Nor is it an example of how one should implement this in a game. So, just read the code, and have some fun enjoying the beauty of the Decorator pattern.

Player.java

public abstract class Player{
    private int health;

    public abstract boolean play();
    public boolean reduceHealth(int value) {
        health-=value;
        System.out.println("Health reduced By : "+ value);
        return true;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }
}


Bot.java

public class Bot extends Player{

    private int skillLevel;

    @Override
    public boolean play() {
        System.out.println("Bot (With Skill Level : "+ skillLevel + ") Is Ready To Play");
        //Code that implements how a bot plays
        return true;
    }

    public int getSkillLevel() {
        return skillLevel;
    }

    public void setSkillLevel(int skillLevel) {
        this.skillLevel = skillLevel;
    }

    @Override
    public boolean reduceHealth(int value) {
        //The health of bots reduces slowly as compared to players.
        setHealth(getHealth()-(value-1));
        System.out.println("Health reduced By : "+ value);
        return true;
    }

    public boolean attackPlayer(Player p,int healthReductionValue)
    {
        p.reduceHealth(healthReductionValue);
        return true;
    }
}


HumanPlayer.java

public class HumanPlayer extends Player{
    private int experiencePoints;
    

    public int getExperiencePoints() {
        return experiencePoints;
    }

    public void setExperiencePoints(int experiencePoints) {
        this.experiencePoints = experiencePoints;
    }

    
    
    @Override
    public boolean play() {
        System.out.println("Player (With Experience Points : "+ experiencePoints + ") Is Ready To Play");
        //Code that implements how a human player plays
        return true;
    }

    @Override
    public boolean reduceHealth(int value) {
        setHealth(getHealth()-value);
        System.out.println("Health reduced By : "+ value);
        return true;
    }
}


PowerPlayer.java -- The Decorator Class

public class PowerPlayer extends HumanPlayer{
    private HumanPlayer player;

    public PowerPlayer(HumanPlayer player) {
        this.player = player;
    }

    
    @Override
    public boolean play() {
        System.out.println("Power Player");
        player.play();
        return true;
    }

    @Override
    public boolean reduceHealth(int value) {
        //Power Player's health reduces very slowly
        value=1;
        System.out.println("Setting Health Reduction Value To : "+ value);
        player.reduceHealth(value);
        return true;
    }

    public Player getPlayer() {
        return player;
    }

}


Game.java


public class Game {
    private Player player1;
    private List <Bot> bots;

    public Game() {
        bots=new ArrayList();
    }


    public Player getPlayer1() {
        return player1;
    }

    public void setPlayer1(Player player1) {
        this.player1 = player1;
    }

    public List <Bot> getBots() {
        return bots;
    }

    public void setBots(List <Bot> bots) {
        this.bots = bots;
    }
    
    public void addBots(Bot bot) {
        bots.add(bot);
    }

}


Main.java


public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Game game=new Game();
        HumanPlayer hp=new HumanPlayer();
        Bot b1=new Bot();
        Bot b2=new Bot();

        //Initialize the Player's values
        hp.setExperiencePoints(10);
        hp.setHealth(100);

        //Initialize the bots values.
        //b1 is a powerful bot because it has a high skill level
        b1.setHealth(100);
        b1.setSkillLevel(10);

        //b2 is a weak bot because it has a low skill level
        b1.setHealth(100);
        b2.setSkillLevel(5);

        //Lets Start the game.
        game.setPlayer1(hp);
        game.addBots(b1);
        game.addBots(b2);
        hp.play();
        b1.play();
        b2.play();

        System.out.println("Initial Player Health : " + game.getPlayer1().getHealth());

        //Let him take a few attacks by the bots
        b1.attackPlayer(game.getPlayer1(), 8);
        b1.attackPlayer(game.getPlayer1(), 4);

        System.out.println("Player Health : " + game.getPlayer1().getHealth());


        
        //Now suppose the player picks up an artifact that
        //allows him to become a power player
        //Note that this Power Play option should be available for a
        //fixed duration, determined by the game. e.g. 30 seconds
        //This is how it 'can' be implemented
        System.out.println("\nStarting Power Play Mode");
        PowerPlayer pp=new PowerPlayer(hp);
        game.setPlayer1(pp);

        //Now let the game continue
        //And let the player receive some attacks by the bots
        b1.attackPlayer(game.getPlayer1(), 8);
        b1.attackPlayer(game.getPlayer1(), 20);
        System.out.println("Player Health : " + game.getPlayer1().getHealth());


        //After 30 seconds, remove the power player settings
        //This is a possible implementation
        System.out.println("\nEnding Power Play Mode");
        game.setPlayer1(pp.getPlayer());
        System.out.println("Player Health : " + game.getPlayer1().getHealth());

        //Now let the game continue
        //And let the player receive some attacks by the bots
        b1.attackPlayer(game.getPlayer1(), 8);
        b1.attackPlayer(game.getPlayer1(), 20);

        System.out.println("Player Health : " + game.getPlayer1().getHealth());

        //Finally How you end the game is up to you!
    }

}



Signing Off
Ryan