Design patterns can be a helpful guide to organizing a program. A pattern is simply a description of a way of organizing the objects and classes in the design of a program that can be adapted to other programs. As discussed in class, a difficulty with the Fish class is that if we want to use inheritance to creat subclasses of Fish that have different ways of moving, different ways of breeding and, perhaps, different ways of dying, and we want different combinations of these, then the inheritance hierarchy can become quite large and convoluted.
The strategy design pattern suggests that when a class describes objects that could implement a particular responsibility in different ways, with different strategies (algorithms), then rather than create modifications through inheritance, we can regard the strategy as an object. For example the Fish class has three responsibilities: moving, breeding, and determining whether it should die. Rather than create subclasses of Fish that define different ways of moving, breeding, and/or dying, we can define the Fish class itself to have an instance variable for each strategy, having these instance variables set by the contructors.
This is a natural place to use an interface or an abstract class.
We define the type of each strategy using an interface (or abstract class),
then the implementing classes implement that interface. If we work with the
three movements defined in the MBS and consider two ways of breeding, the
original "all or none" breeding (where based on a probability the
fish breeds in every empy neighbor or does not breed) and a diferent "independent"
breeding (where each empty neighbor is checked indepenedently and with a given
probability the fish breeds into that location or not), the we can diagram
the situation as follows (we leave the issue of dying out).

To do this lab you should start with the MBS code files in the folder labeled Strategy Pattern. This includes the Fish class that currently has methods for breeding and dying, and the subclasses DarterFish and SlowFish.
You will need to do the following.
1. Create interfaces FishMovement and FishBreeder. The movement interface should specify a method move that takes a Fish as parameter. The breed interface should specify a method breed that takes a Fish as parameter. (You may choose to change these to abstract classes later.)
2. Complete the modified Fish class supplied with the lab. It has an instance variable for each of the interfaces given above and all the constructors set those fields from parameters. You will need to determine which methods from the Fish class should be included for breeding and moving and which should be placed in the FishBreeder or FishMovement You can copy code from the original Fish class as needed.
3. The class ThreeWay will implement the original fish movement strategy. It should have a move method that is essentially the same as the original move method, except that it uses its Fish parameter to reference the environment, location, and other methods of the Fish that are used in moving. It should also copy the nextLocation method with the same changes (giving the method a Fish parameter). The emptyNeighbors method that is used by the nextLocation method presents an interesting design decision. If we place it in the ThreeWay class, then we will also need to make a copy in the breeding methods. What alternatives are there? Where should the emptyNeighbors method be placed? The methods changeLocation and changeDirection also present a design decision. They will be used by every class that implements FishMovement. Should they remain in the Fish class, should they be placed in the abstract FishMovement (making it an abstract class instead of an interface), or should they be copied into every class that implements FishMovement?
4. The class AllOrNone will implement the original breeding method. It will include an instance variable to store the probability of breeding and will implement the method breed (taking a Fish parameter). Again, we need access to the emptyNeighbors method, so the question is where should this method be placed or copied? For breeding another design decision is where we should place the generateChild method, so that it breeds true -- that is the children fish have the same characteristics as their parents.
5. The Fish class has no breed or move method since these are now in the FishMovement and FishBreeder classes. You must determine which auxiliary methods should beplaced in the classes implementing FishMovement and FishBreeder (and the probability of breeding, which will now be placed in the breeding classes) and which should remain in the Fish class. The following is a partial definition of the new Fish class.
public class
Fish implements Locatable
{
...
private FishMovement mover;
private FishBreeder breeder;
public Fish(Environment env, Location loc, FishMovement mv, FishBreeder
brd)
...
public void act()
{
if(!isInEnv())
return;
if(!breeder.breed(this))
move.move(this);
...
}
6. Rewrite the class SimpleMBSDemo2 to test the new version of the Fish class. Each fish that is declared will need to have a FishMovement object and a FishBreed object passed as a parameter to the constructor, the latter with a probability passed to its constructor. If you use a constructor that allows you to set color, you can use that to distinguish the different types of fish for testing.
7. Now add three or four additional classes implementing FishMovement, one that gives SlowFish action, one for DarterFish action, and one or two others of your own choosing (CircleFish action, PathFollower, Hunter, or your own)
8. Finally, add at least one additional method of breeding as a class implementing FishBreeder, either independent breeding or single fish breeding, or your own.
9. Again test you classes by modifying the SimpleMBSDemo2 driver.
Put your completed code into your own Strategy folder. Email the instructor when you have completed your code. In your email, mention any design decisions that you made in completing your implementation.