Lab 4: Design Patterns

Introduction

Download and create a project with this archive: tp4-start-en.zip This is an almost complete correction of the previous lab. Take time to check that all abstractions are present (from SeTD3y1314).

Exercise 1: Fixing the simulator (Observer pattern)

You have noticed that there is a Launcher class that contain the main method. You can use it to run the simulator. If you do, you will quickly find out that it does not really work. Your task is therefore to try to fix it.

Hint: remember the observer pattern.

Exercise 2: Fixing the resize (Observer pattern)

There is one more problem with the application. Try to resize the window. Again, your task is to fix it.

Hint: look at the JPanel#addComponentListener()

Exercise 3: Factory for the creatures (Factory pattern and Abstract factory pattern)

Now adding one creature at the time might be slightly annoying so you should try to make a factory CreatureFactory that can create a set of creatures at once. It should be given the dimension of the simulation plane, the number of creature to create. Let's start by having all creatures black (or any other color to your liking). Think about what you will have to do in order to create a different creature types?

TIP Hint: use the following code as for a CreatureFactory class in the package creatures. Fill the TODOs.

package creatures;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;

public class CreatureFactory {
   
   protected static CreatureFactory _singleton;

    public static void init(double inMaxSpeed) {

        if (_singleton != null) {
            throw new RuntimeException("CreatureFactory already created by " 
              + _singleton.getClass().getName());
        } else {
             _singleton = new CreatureFactory();
            maxSpeed = inMaxSpeed;  
        }
     }

    public static CreatureFactory getCreatureFactory() {
       return _singleton;
    }

    private CreatureFactory() {
    }
    
   
   interface ICreatureCreator<T extends ICreature> {
      public T create(IEnvironment env, Point2D position, double speed,
            double direction, Color color);
   }
   
   private static double maxSpeed = 10; // default value
   private final Random rand = new Random();

   public <T extends ICreature> Collection<T> createCreatures(IEnvironment env, int count, ICreatureCreator<T> creator) {
      Collection<T> creatures = new ArrayList<T>();
      
      Dimension s = env.getSize();
      
      for (int i=0; i<count; i++) {   
         // X coordinate
         double x = (rand.nextDouble() * s.getWidth()) - s.getWidth() / 2;

         // Y coordinate
         double y = (rand.nextDouble() * s.getHeight()) - s.getHeight() / 2;

         // direction
         double direction = (rand.nextDouble() * 2 * Math.PI);

         // speed
         int speed = (int) (rand.nextDouble() * maxSpeed);

         T creature = creator.create(env, new Point2D.Double(x,y), speed, direction, Color.RED);
         creatures.add(creature);
      }
      
      return creatures;
   }
   
   public Collection<SmartCreature> createSmartCreatures(IEnvironment env, int count) {
      return createCreatures(env, count, new ICreatureCreator<SmartCreature>() {
         public SmartCreature create(IEnvironment env, Point2D position, double speed,
               double direction, Color color) {            
            return // TODO: call the BouncingCreature constructor
         }
      });
   }

   
   public Collection<BouncingCreature> createBouncingCreatures(IEnvironment env, int count, IColorStrategy colorStrategy) {
      return createCreatures(env, count, new ICreatureCreator<BouncingCreature>() {
         @Override
           public BouncingCreature create(IEnvironment env, Point2D position,
               double speed, double direction, Color color) {
            return // TODO: call the BouncingCreature constructor
         }
      });
   }

}

and change the Launcher.init() code to add the following:

      double myMaxSpeed = 5;
      CreatureFactory.init(myMaxSpeed);
      CreatureFactory factory = CreatureFactory.getCreatureFactory();
      Collection<BouncingCreature> creatures = factory.createBouncingCreatures(simulator, 10);
      simulator.addAllCreatures(creatures);
//      simulator.addCreature(new BouncingCreature(simulator, new Point2D.Double(0, 0), 3, 0, Color.BLUE));
      simulator.start();

Exercise 4: Color strategies (Strategy pattern)

Regardless what color you have picked up, after a while it will get a bit boring, so it would be nice if the factory can also be more colorful. For this it should take yet another parameter a reference to an instance of a IColorPicker that will have one method getNextColor(). Then implement different strategies like one that only gets back one color, one that iterates over the color cube like in the old createCreature method, etc.

If you think about the interface, you might realize that it is kind of iterator, thus you could also implement it using simply an Iterator interface. What would be the advantage/disadvantage?

-- PhilippeCollet - 08 Nov 2013

Revision: r1.3 - 08 Nov 2013 - 10:30 - PhilippeCollet
Minfo > SeTD4y1314
Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WIKIDeptinfo? Send feedback