netoxi

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

目录

· Strategy

    · When to use the Strategy Design Pattern?

    · Sample Code

· Observer

    · When to use the Observer Design Pattern?

    · Sample Code

· Command

    · What is the Command Design Pattern?

    · Benefits of the Command Design Pattern.

    · Sample Code

· Template Method

    · What is the Template Method Design Pattern?

    · Sample Code

· Iterator

    · What is the Iterator Design Pattern?

    · Sample Code

· State

    · What is the State Design Pattern?

    · State Design Pattern Example.

    · Sample Code

· Chain of Responsibility

    · What is the Chain of Responsibility Design Pattern?

    · Sample Code

· Interpreter

    · What is the Interpreter Design Pattern?

    · Sample Code

· Mediator

    · What is the Mediator Design Pattern?

    · Sample Code

· Memento

    · What is the Memento Design Pattern?

    · Sample Code

· Visitor

    · What is the Visitor Design Pattern?

    · Sample Code


 

Strategy

When to use the Strategy Design Pattern?

• When you want to define a class that will have one behavior that is similar to other behaviors in a list.

• I want the class object to be able to choose from

• Not Flying.

• Fly with Wings.

• Fly Super Fast.

• When you need to use one of several behaviors dynamically.

• Often reduces long lists of conditionals.

• Avoids duplicate code.

• Keeps class changes from forcing other class changes.

• Can hide complicated / secret code from the user.

• Negative: Increased number of objects / classes.

Sample Code

• Animal.java

 1 public class Animal {
 2     
 3     private String name;
 4     private double height;
 5     private int weight;
 6     private String favFood;
 7     private double speed;
 8     private String sound;
 9     
10     // Instead of using an interface in a traditional way
11     // we use an instance variable that is a subclass
12     // of the Flys interface.
13     
14     // Animal doesn't care what flyingType does, it just
15     // knows the behavior is available to its subclasses
16     
17     // This is known as Composition : Instead of inheriting
18     // an ability through inheritance the class is composed
19     // with Objects with the right ability
20     
21     // Composition allows you to change the capabilities of 
22     // objects at run time!
23     
24     public Flys flyingType;
25     
26     public void setName(String newName){ name = newName; }
27     public String getName(){ return name; }
28     
29     public void setHeight(double newHeight){ height = newHeight; }
30     public double getHeight(){ return height; }
31     
32     public void setWeight(int newWeight){ 
33         if (newWeight > 0){
34             weight = newWeight; 
35         } else {
36             System.out.println("Weight must be bigger than 0");
37         }
38     }
39     public double getWeight(){ return weight; }
40     
41     public void setFavFood(String newFavFood){ favFood = newFavFood; }
42     public String getFavFood(){ return favFood; }
43     
44     public void setSpeed(double newSpeed){ speed = newSpeed; }
45     public double getSpeed(){ return speed; }
46     
47     public void setSound(String newSound){ sound = newSound; }
48     public String getSound(){ return sound; }
49     
50     /* BAD
51     * You don't want to add methods to the super class.
52     * You need to separate what is different between subclasses
53     * and the super class
54     public void fly(){
55         
56         System.out.println("I'm flying");
57         
58     }
59     */
60     
61     // Animal pushes off the responsibility for flying to flyingType
62     
63     public String tryToFly(){
64         
65         return flyingType.fly();
66         
67     }
68     
69     // If you want to be able to change the flyingType dynamically
70     // add the following method
71     
72     public void setFlyingAbility(Flys newFlyType){
73         
74         flyingType = newFlyType;
75         
76     }
77     
78 }

• Dog.java

 1 public class Dog extends Animal{
 2     
 3     public void digHole(){
 4         
 5         System.out.println("Dug a hole");
 6         
 7     }
 8     
 9     public Dog(){
10         
11         super();
12         
13         setSound("Bark");
14         
15         // We set the Flys interface polymorphically
16         // This sets the behavior as a non-flying Animal
17         
18         flyingType = new CantFly();
19         
20     }
21     
22     /* BAD
23     * You could override the fly method, but we are breaking
24     * the rule that we need to abstract what is different to 
25     * the subclasses
26     * 
27     public void fly(){
28         
29         System.out.println("I can't fly");
30         
31     }
32     */
33     
34 }

• Bird.java

 1 public class Bird extends Animal{
 2     
 3     // The constructor initializes all objects
 4     
 5     public Bird(){
 6         
 7         super();
 8         
 9         setSound("Tweet");
10         
11         // We set the Flys interface polymorphically
12         // This sets the behavior as a non-flying Animal
13         
14         flyingType = new ItFlys();
15         
16     }
17     
18 }

• Flys.java

 1 // The interface is implemented by many other
 2 // subclasses that allow for many types of flying
 3 // without effecting Animal, or Flys.
 4 
 5 // Classes that implement new Flys interface
 6 // subclasses can allow other classes to use
 7 // that code eliminating code duplication
 8 
 9 // I'm decoupling : encapsulating the concept that varies
10 
11 public interface Flys {
12     
13    String fly();
14    
15 }
16 
17 // Class used if the Animal can fly
18 
19 class ItFlys implements Flys{
20 
21     public String fly() {
22         
23         return "Flying High";
24         
25     }
26     
27 }
28 
29 //Class used if the Animal can't fly
30 
31 class CantFly implements Flys{
32 
33     public String fly() {
34         
35         return "I can't fly";
36         
37     }
38     
39 }

• AnimalPlay.java

 1 public class AnimalPlay{
 2     
 3     public static void main(String[] args){
 4         
 5         Animal sparky = new Dog();
 6         Animal tweety = new Bird();
 7         
 8         System.out.println("Dog: " + sparky.tryToFly());
 9         
10         System.out.println("Bird: " + tweety.tryToFly());
11         
12         // This allows dynamic changes for flyingType
13         
14         sparky.setFlyingAbility(new ItFlys());
15         
16         System.out.println("Dog: " + sparky.tryToFly());
17         
18     }
19     
20 }

Observer

When to use the Observer Design Pattern?

• When you need many other objects to receive an update when another object changes.

• Stock market with thousands of stocks needs to send updates to objects representing individual stocks.

• The Subject (publisher) sends many stocks to the Observers.

• The Observers (subscribers) takes the ones they want and use them.

• Loose coupling is a benefit.

• The Subject (publisher) doesn't need to know anything about the Observers (subscribers).

• Negatives: The Subject (publisher) may send updates that don't matter to the Observer (subscriber).

Sample Code

• Subject.java

 1 // This interface handles adding, deleting and updating
 2 // all observers 
 3 
 4 public interface Subject {
 5     
 6     public void register(Observer o);
 7     public void unregister(Observer o);
 8     public void notifyObserver();
 9     
10 }

• Observer.java

1 // The Observers update method is called when the Subject changes
2 
3 public interface Observer {
4     
5     public void update(double ibmPrice, double aaplPrice, double googPrice);
6     
7 }

• StockGrabber.java

 1 import java.util.ArrayList;
 2 
 3 // Uses the Subject interface to update all Observers
 4 
 5 public class StockGrabber implements Subject{
 6     
 7     private ArrayList<Observer> observers;
 8     private double ibmPrice;
 9     private double aaplPrice;
10     private double googPrice;
11     
12     public StockGrabber(){
13         
14         // Creates an ArrayList to hold all observers
15         
16         observers = new ArrayList<Observer>();
17     }
18     
19     public void register(Observer newObserver) {
20         
21         // Adds a new observer to the ArrayList
22         
23         observers.add(newObserver);
24         
25     }
26 
27     public void unregister(Observer deleteObserver) {
28         
29         // Get the index of the observer to delete
30         
31         int observerIndex = observers.indexOf(deleteObserver);
32         
33         // Print out message (Have to increment index to match)
34         
35         System.out.println("Observer " + (observerIndex+1) + " deleted");
36         
37         // Removes observer from the ArrayList
38         
39         observers.remove(observerIndex);
40         
41     }
42 
43     public void notifyObserver() {
44         
45         // Cycle through all observers and notifies them of
46         // price changes
47         
48         for(Observer observer : observers){
49             
50             observer.update(ibmPrice, aaplPrice, googPrice);
51             
52         }
53     }
54     
55     // Change prices for all stocks and notifies observers of changes
56     
57     public void setIBMPrice(double newIBMPrice){
58         
59         this.ibmPrice = newIBMPrice;
60         
61         notifyObserver();
62         
63     }
64     
65     public void setAAPLPrice(double newAAPLPrice){
66         
67         this.aaplPrice = newAAPLPrice;
68         
69         notifyObserver();
70         
71     }
72 
73     public void setGOOGPrice(double newGOOGPrice){
74     
75         this.googPrice = newGOOGPrice;
76     
77         notifyObserver();
78     
79     }
80     
81 }

• StockObserver.java

 1 // Represents each Observer that is monitoring changes in the subject
 2 
 3 public class StockObserver implements Observer {
 4     
 5     private double ibmPrice;
 6     private double aaplPrice;
 7     private double googPrice;
 8     
 9     // Static used as a counter
10     
11     private static int observerIDTracker = 0;
12     
13     // Used to track the observers
14     
15     private int observerID;
16     
17     // Will hold reference to the StockGrabber object
18     
19     private Subject stockGrabber;
20     
21     public StockObserver(Subject stockGrabber){
22         
23         // Store the reference to the stockGrabber object so
24         // I can make calls to its methods
25         
26         this.stockGrabber = stockGrabber;
27         
28         // Assign an observer ID and increment the static counter
29         
30         this.observerID = ++observerIDTracker;
31         
32         // Message notifies user of new observer
33         
34         System.out.println("New Observer " + this.observerID);
35         
36         // Add the observer to the Subjects ArrayList
37         
38         stockGrabber.register(this);
39         
40     }
41     
42     // Called to update all observers
43     
44     public void update(double ibmPrice, double aaplPrice, double googPrice) {
45         
46         this.ibmPrice = ibmPrice;
47         this.aaplPrice = aaplPrice;
48         this.googPrice = googPrice;
49         
50         printThePrices();
51         
52     }
53     
54     public void printThePrices(){
55         
56         System.out.println(observerID + "\nIBM: " + ibmPrice + "\nAAPL: " + 
57                 aaplPrice + "\nGOOG: " + googPrice + "\n");
58         
59     }
60     
61 }

• GrabStocks.java

 1 public class GrabStocks{
 2     
 3     public static void main(String[] args){
 4         
 5         // Create the Subject object
 6         // It will handle updating all observers 
 7         // as well as deleting and adding them
 8         
 9         StockGrabber stockGrabber = new StockGrabber();
10         
11         // Create an Observer that will be sent updates from Subject
12         
13         StockObserver observer1 = new StockObserver(stockGrabber);
14         
15         stockGrabber.setIBMPrice(197.00);
16         stockGrabber.setAAPLPrice(677.60);
17         stockGrabber.setGOOGPrice(676.40);
18         
19         StockObserver observer2 = new StockObserver(stockGrabber);
20         
21         stockGrabber.setIBMPrice(197.00);
22         stockGrabber.setAAPLPrice(677.60);
23         stockGrabber.setGOOGPrice(676.40);
24         
25         // Delete one of the observers
26         
27         // stockGrabber.unregister(observer2);
28         
29         stockGrabber.setIBMPrice(197.00);
30         stockGrabber.setAAPLPrice(677.60);
31         stockGrabber.setGOOGPrice(676.40);
32         
33         // Create 3 threads using the Runnable interface
34         // GetTheStock implements Runnable, so it doesn't waste 
35         // its one extendable class option
36         
37         Runnable getIBM = new GetTheStock(stockGrabber, 2, "IBM", 197.00);
38         Runnable getAAPL = new GetTheStock(stockGrabber, 2, "AAPL", 677.60);
39         Runnable getGOOG = new GetTheStock(stockGrabber, 2, "GOOG", 676.40);
40         
41         // Call for the code in run to execute 
42         
43         new Thread(getIBM).start();
44         new Thread(getAAPL).start();
45         new Thread(getGOOG).start();
46         
47         
48     }
49     
50 }

• GetTheStock.java

 1 import java.text.DecimalFormat;
 2 
 3 public class GetTheStock implements Runnable{
 4     
 5     // Could be used to set how many seconds to wait
 6     // in Thread.sleep() below
 7     
 8     // private int startTime; 
 9     private String stock;
10     private double price;
11     
12     // Will hold reference to the StockGrabber object
13     
14     private Subject stockGrabber;
15     
16     public GetTheStock(Subject stockGrabber, int newStartTime, String newStock, double newPrice){
17         
18         // Store the reference to the stockGrabber object so
19         // I can make calls to its methods
20                 
21         this.stockGrabber = stockGrabber;
22         
23         // startTime = newStartTime;  Not used to have variable sleep time
24         stock = newStock;
25         price = newPrice;
26         
27     }
28     
29     public void run(){
30         
31         for(int i = 1; i <= 20; i++){
32         
33             try{
34                 
35                 // Sleep for 2 seconds
36                 Thread.sleep(2000);
37                 
38                 // Use Thread.sleep(startTime * 1000); to 
39                 // make sleep time variable
40             }
41             catch(InterruptedException e)
42             {}
43             
44             // Generates a random number between -.03 and .03
45             
46             double randNum = (Math.random() * (.06)) - .03;
47             
48             // Formats decimals to 2 places
49             
50             DecimalFormat df = new DecimalFormat("#.##");
51             
52             // Change the price and then convert it back into a double
53             
54             price = Double.valueOf(df.format((price + randNum)));
55             
56             if(stock == "IBM") ((StockGrabber) stockGrabber).setIBMPrice(price);
57             if(stock == "AAPL") ((StockGrabber) stockGrabber).setAAPLPrice(price);
58             if(stock == "GOOG") ((StockGrabber) stockGrabber).setGOOGPrice(price);
59             
60             System.out.println(stock + ": " + df.format((price + randNum)) + 
61                     " " + df.format(randNum));
62             
63             System.out.println();
64         
65         }
66     }
67     
68 }

Command

What is the Command Design Pattern?

• The command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.

• This information includes the method name, the object that owns the method and values for the method parameters.

• Allows you to store lists of code that is executed at a later time or many times.

• Client says I want a specific Command to run when execute() is called on one of these encapsulated (hidden) objects.

• An object called the Invoker transfers this Command to another object called a Receiver to execute the right code.

• TurnTVOn - DeviceButton - TurnTVOn - Television.TurnTVOn()

Benefits of the Command Design Pattern.

• Allows you to set aside a list of commands for later use.

• A class is a great place to store procedures you want to be executed.

• You can store multiple commands in a class to use over and over.

• You can implement undo procedures for past commands.

• Negative: You create many small classes that store lists of commands.

Sample Code

• ElectronicDevice.java

 1 public interface ElectronicDevice {
 2     
 3     public void on();
 4     
 5     public void off();
 6     
 7     public void volumeUp();
 8     
 9     public void volumenDown();
10     
11 }

• Television.java(RECEIVER)

 1 public class Television implements ElectronicDevice {
 2 
 3     private int volume = 0;
 4     
 5     public void on() {
 6         
 7         System.out.println("TV is on");
 8         
 9     }
10 
11     public void off() {
12         
13         System.out.println("TV is off");
14         
15     }
16 
17     public void volumeUp() {
18         
19         volume++;
20         
21         System.out.println("TV Volume is at: " + volume);
22         
23     }
24 
25     public void volumenDown() {
26         
27         volume--;
28         
29         System.out.println("TV Volume is at: " + volume);
30         
31     }
32     
33 }

• Command.java

 1 // Each command you want to issue will implement 
 2 // the Command interface
 3 
 4 public interface Command {
 5     
 6     public void execute();
 7     
 8     // You may want to offer the option to undo a command
 9     
10     public void undo();
11     
12 }

• TurnTVOn.java(COMMAND)

 1 public class TurnTVOn implements Command {
 2 
 3     ElectronicDevice theDevice;
 4     
 5     public TurnTVOn(ElectronicDevice newDevice){
 6         
 7         theDevice = newDevice;
 8         
 9     }
10     
11     public void execute() {
12         
13         theDevice.on();
14         
15     }
16 
17     public void undo() {
18         
19         theDevice.off();
20         
21     }
22     
23 }

• TurnTVOff.java(COMMAND)

 1 public class TurnTVOff implements Command {
 2 
 3     ElectronicDevice theDevice;
 4     
 5     public TurnTVOff(ElectronicDevice newDevice){
 6         
 7         theDevice = newDevice;
 8         
 9     }
10     
11     public void execute() {
12         
13         theDevice.off();
14         
15     }
16 
17     // Used if you want to allow for undo
18     // Do the opposite of execute()
19     
20     public void undo() {
21         
22         theDevice.on();
23         
24     }
25     
26 }

• TurnTVUp.java(COMMAND)

 1 public class TurnTVUp implements Command {
 2 
 3     ElectronicDevice theDevice;
 4     
 5     public TurnTVUp(ElectronicDevice newDevice){
 6         
 7         theDevice = newDevice;
 8         
 9     }
10     
11     public void execute() {
12         
13         theDevice.volumeUp();
14         
15     }
16 
17     public void undo() {
18         
19         theDevice.volumenDown();
20         
21     }
22     
23 }

• DeviceButton.java(INVOKER)

 1 // This is known as the invoker
 2 // It has a method press() that when executed
 3 // causes the execute method to be called
 4 
 5 // The execute method for the Command interface then calls 
 6 // the method assigned in the class that implements the
 7 // Command interface
 8 
 9 public class DeviceButton{
10     
11     Command theCommand;
12     
13     public DeviceButton(Command newCommand){
14         
15         theCommand = newCommand;
16         
17     }
18     
19     public void press(){
20         
21         theCommand.execute();
22         
23     }
24     
25     // Now the remote can undo past commands
26     
27     public void pressUndo(){
28         
29         theCommand.undo();
30         
31     }
32     
33 }

• TVRemote.java

1 public class TVRemote {
2     
3     public static ElectronicDevice getDevice(){
4         
5         return new Television();
6         
7     }
8     
9 }

• PlayWithRemote.java

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 public class PlayWithRemote{
  5     
  6     public static void main(String[] args){
  7         
  8         // Gets the ElectronicDevice to use
  9         
 10         ElectronicDevice newDevice = TVRemote.getDevice();
 11         
 12         // TurnTVOn contains the command to turn on the tv
 13         // When execute() is called on this command object
 14         // it will execute the method on() in Television
 15         
 16         TurnTVOn onCommand = new TurnTVOn(newDevice);
 17         
 18         // Calling the execute() causes on() to execute in Television
 19         
 20         DeviceButton onPressed = new DeviceButton(onCommand);
 21         
 22         // When press() is called theCommand.execute(); executes
 23         
 24         onPressed.press();
 25         
 26         //----------------------------------------------------------
 27         
 28         // Now when execute() is called off() of Television executes
 29         
 30         TurnTVOff offCommand = new TurnTVOff(newDevice);
 31         
 32         // Calling the execute() causes off() to execute in Television
 33         
 34         onPressed = new DeviceButton(offCommand);
 35         
 36         // When press() is called theCommand.execute(); executes
 37         
 38         onPressed.press();
 39         
 40         //----------------------------------------------------------
 41         
 42         // Now when execute() is called volumeUp() of Television executes
 43         
 44         TurnTVUp volUpCommand = new TurnTVUp(newDevice);
 45                 
 46         // Calling the execute() causes volumeUp() to execute in Television
 47                 
 48         onPressed = new DeviceButton(volUpCommand);
 49                 
 50         // When press() is called theCommand.execute(); executes
 51                 
 52         onPressed.press();
 53         onPressed.press();
 54         onPressed.press();
 55         
 56         //----------------------------------------------------------
 57         
 58         // Creating a TV and Radio to turn off with 1 press
 59         
 60         Television theTV = new Television();
 61         
 62         Radio theRadio = new Radio();
 63         
 64         // Add the Electronic Devices to a List
 65         
 66         List<ElectronicDevice> allDevices = new ArrayList<ElectronicDevice>();
 67         
 68         allDevices.add(theTV);
 69         allDevices.add(theRadio);
 70         
 71         // Send the List of Electronic Devices to TurnItAllOff
 72         // where a call to run execute() on this function will
 73         // call off() for each device in the list 
 74         
 75         TurnItAllOff turnOffDevices = new TurnItAllOff(allDevices);
 76         
 77         // This calls for execute() to run which calls for off() to
 78         // run for every ElectronicDevice
 79         
 80         DeviceButton turnThemOff = new DeviceButton(turnOffDevices);
 81         
 82         turnThemOff.press();
 83         
 84         //----------------------------------------------------------
 85         
 86         /*
 87          * It is common to be able to undo a command in a command pattern
 88          * To do so, DeviceButton will have a method called undo
 89          * Undo() will perform the opposite action that the normal
 90          * Command performs. undo() needs to be added to every class
 91          * with an execute()
 92          */
 93         
 94         turnThemOff.pressUndo();
 95         
 96         // To undo more than one command add them to a LinkedList
 97         // using addFirst(). Then execute undo on each item until 
 98         // there are none left. (This is your Homework)
 99         
100     }
101     
102 }

• Radio.java(RECEIVER)

 1 public class Radio implements ElectronicDevice {
 2 
 3     private int volume = 0;
 4     
 5     public void on() {
 6         
 7         System.out.println("Radio is on");
 8         
 9     }
10 
11     public void off() {
12         
13         System.out.println("Radio is off");
14         
15     }
16 
17     public void volumeUp() {
18         
19         volume++;
20         
21         System.out.println("Radio Volume is at: " + volume);
22         
23     }
24 
25     public void volumenDown() {
26         
27         volume--;
28         
29         System.out.println("Radio Volume is at: " + volume);
30         
31     }
32     
33 }

• TurnItAllOff.java(COMMAND)

 1 import java.util.List;
 2 
 3 public class TurnItAllOff implements Command {
 4   List<ElectronicDevice> theDevices;
 5  
 6   public TurnItAllOff(List<ElectronicDevice> newDevices) {
 7       theDevices = newDevices;
 8   }
 9  
10   public void execute() {
11  
12     for (ElectronicDevice device : theDevices) {
13       device.off();
14     }
15  
16   }
17 
18   public void undo() {
19     
20     for (ElectronicDevice device : theDevices) {
21           device.on();
22         }
23     
24   }
25 }

Template Method

What is the Template Method Design Pattern?

• Used to create a group of subclasses that have to execute a similar group of methods.

• You create an abstract class that contains a method called the Template Method.

• The Template Method contains a series of method calls that every subclass object will call.

• The subclass objects can override some of the method calls.

Sample Code

• ItalianHoagie.java

  1 public class ItalianHoagie extends Hoagie{
  2     
  3     String[] meatUsed = { "Salami", "Pepperoni", "Capicola Ham" };
  4     String[] cheeseUsed = { "Provolone" };
  5     String[] veggiesUsed = { "Lettuce", "Tomatoes", "Onions", "Sweet Peppers" };
  6     String[] condimentsUsed = { "Oil", "Vinegar" };
  7     
  8     public void addMeat(){
  9         
 10         System.out.print("Adding the Meat: ");
 11         
 12         for (String meat : meatUsed){
 13             
 14             System.out.print(meat + " ");
 15             
 16         }
 17         
 18     }
 19     
 20     public void addCheese(){
 21         
 22         System.out.print("Adding the Cheese: ");
 23         
 24         for (String cheese : cheeseUsed){
 25             
 26             System.out.print(cheese + " ");
 27             
 28         }
 29         
 30     }
 31     
 32     public void addVegetables(){
 33         
 34         System.out.print("Adding the Vegetables: ");
 35         
 36         for (String vegetable : veggiesUsed){
 37             
 38             System.out.print(vegetable + " ");
 39             
 40         }
 41         
 42     }
 43     
 44     public void addCondiments(){
 45         
 46         System.out.print("Adding the Condiments: ");
 47         
 48         for (String condiment : condimentsUsed){
 49             
 50             System.out.print(condiment + " ");
 51             
 52         }
 53         
 54     }
 55     
 56 }
 57     
 58     /*
 59     public void makeSandwich(){
 60         
 61         cutBun();
 62         addMeat();
 63         addCheese();
 64         addVegetables();
 65         addCondiments();
 66         wrapTheHoagie();
 67         
 68     }
 69     
 70     public void cutBun(){
 71         
 72         System.out.println("The Hoagie is Cut");
 73         
 74     }
 75     
 76     public void addMeat(){
 77         
 78         System.out.println("Add Salami, Pepperoni and Capicola ham");
 79         
 80     }
 81     
 82     public void addCheese(){
 83         
 84         System.out.println("Add Provolone");
 85         
 86     }
 87     
 88     public void addVegetables(){
 89         
 90         System.out.println("Add Lettuce, Tomatoes, Onions and Sweet Peppers");
 91         
 92     }
 93     
 94     public void addCondiments(){
 95         
 96         System.out.println("Add Oil and Vinegar");
 97         
 98     }
 99     
100     public void wrapTheHoagie(){
101         
102         System.out.println("Wrap the Hoagie");
103         
104     }
105     
106 }
107     */

• Hoagie.java

 1 // A Template Method Pattern contains a method that provides
 2 // the steps of the algorithm. It allows subclasses to override 
 3 // some of the methods
 4 
 5 public abstract class Hoagie {
 6     
 7     boolean afterFirstCondiment = false;
 8     
 9     // This is the Template Method
10     // Declare this method final to keep subclasses from
11     // changing the algorithm
12     
13     final void makeSandwich(){
14         
15         cutBun();
16         
17         if(customerWantsMeat()){
18             
19             addMeat();
20             
21             // Here to handle new lines for spacing
22             afterFirstCondiment = true;
23             
24         }
25         
26         if(customerWantsCheese()){
27             
28             if(afterFirstCondiment) { System.out.print("\n"); }
29             
30             addCheese();
31             
32             afterFirstCondiment = true;
33             
34         }
35         
36         if(customerWantsVegetables()){
37             
38             if(afterFirstCondiment) { System.out.print("\n"); }
39             
40             addVegetables();
41             
42             afterFirstCondiment = true;
43             
44         }
45         
46         if(customerWantsCondiments()){
47             
48             if(afterFirstCondiment) { System.out.print("\n"); }
49             
50             addCondiments();
51             
52             afterFirstCondiment = true;
53             
54         }
55         
56         wrapTheHoagie();
57         
58     }
59     
60     // These methods must be overridden by the extending subclasses
61     
62     abstract void addMeat();
63     abstract void addCheese();
64     abstract void addVegetables();
65     abstract void addCondiments();
66     
67     public void cutBun(){
68         
69         System.out.println("The Hoagie is Cut");
70         
71     }
72     
73     // These are called hooks
74     // If the user wants to override these they can
75     
76     // Use abstract methods when you want to force the user
77     // to override and use a hook when you want it to be optional
78     
79     boolean customerWantsMeat() { return true; }
80     boolean customerWantsCheese() { return true; }
81     boolean customerWantsVegetables() { return true; }
82     boolean customerWantsCondiments() { return true; }
83     
84     public void wrapTheHoagie(){
85         
86         System.out.println("\nWrap the Hoagie");
87         
88     }
89     
90     public void afterFirstCondiment(){
91         
92         System.out.println("\n");
93         
94     }
95     
96 }

• VeggieHoagie.java

 1 public class VeggieHoagie extends Hoagie{
 2 
 3     String[] veggiesUsed = { "Lettuce", "Tomatoes", "Onions", "Sweet Peppers" };
 4     String[] condimentsUsed = { "Oil", "Vinegar" };
 5     
 6     boolean customerWantsMeat() { return false; }
 7     boolean customerWantsCheese() { return false; }
 8     
 9     public void addVegetables(){
10         
11         System.out.print("Adding the Vegetables: ");
12         
13         for (String vegetable : veggiesUsed){
14             
15             System.out.print(vegetable + " ");
16             
17         }
18         
19     }
20     
21     public void addCondiments(){
22         
23         System.out.print("Adding the Condiments: ");
24         
25         for (String condiment : condimentsUsed){
26             
27             System.out.print(condiment + " ");
28             
29         }
30         
31     }
32 
33     void addMeat() {}
34     
35     void addCheese() {}
36     
37     
38 }

• SandwichSculptor.java

 1 public class SandwichSculptor {
 2     
 3     public static void main(String[] args){
 4         
 5         ItalianHoagie cust12Hoagie = new ItalianHoagie();
 6         
 7         cust12Hoagie.makeSandwich();
 8         
 9         System.out.println();
10         
11         VeggieHoagie cust13Hoagie = new VeggieHoagie();
12         
13         cust13Hoagie.makeSandwich();
14         
15     }
16     
17 }

Iterator

What is the Iterator Design Pattern?

• The Iterator pattern provides you with a uniform way to access different collections of objects.

• If you get an Array, ArrayList and Hashtable of objects, you pop out an iterator for each and treat them the same.

• This provides a uniform way to cycle through different collections.

• You can also write polymorphic code because you can refer to each collection of objects because they'll implement the same interface.

Sample Code

• SongInfo.java

 1 // Will hold all of the info needed for each song
 2 
 3 // I told all users to:
 4 // 1. create a function named addSong() for adding song, band and release
 5 // 2. create a function named getBestSongs() that will return the collection
 6 //    of songs
 7 
 8 public class SongInfo{
 9     
10     String songName; 
11     String bandName; 
12     int yearReleased;
13     
14     public SongInfo(String newSongName, String newBandName, int newYearReleased){
15         
16         songName = newSongName;
17         bandName = newBandName;
18         yearReleased = newYearReleased;
19         
20     }
21     
22     public String getSongName(){ return songName; }
23     public String getBandName(){ return bandName; }
24     public int getYearReleased(){ return yearReleased; }
25     
26 }

• SongsOfThe70s.java

 1 import java.util.ArrayList;
 2 import java.util.Iterator;
 3 
 4 public class SongsOfThe70s implements SongIterator{
 5     
 6     // ArrayList holds SongInfo objects
 7     
 8     ArrayList<SongInfo> bestSongs;
 9     
10     public SongsOfThe70s() {
11         
12         bestSongs = new ArrayList<SongInfo>();
13         
14         addSong("Imagine", "John Lennon", 1971);
15         addSong("American Pie", "Don McLean", 1971);
16         addSong("I Will Survive", "Gloria Gaynor", 1979);
17         
18     }
19     
20     // Add a SongInfo object to the end of the ArrayList
21     
22     public void addSong(String songName, String bandName, int yearReleased){
23         
24         SongInfo songInfo = new SongInfo(songName, bandName, yearReleased);
25         
26         bestSongs.add(songInfo);
27         
28     }
29     
30     
31     // Get rid of this
32     // Return the ArrayList filled with SongInfo Objects
33     
34     public ArrayList<SongInfo> getBestSongs(){
35         
36         return bestSongs;
37         
38     }
39 
40     // NEW By adding this method I'll be able to treat all
41     // collections the same
42     
43     public Iterator createIterator() {
44         // TODO Auto-generated method stub
45         return bestSongs.iterator();
46     }
47     
48 }

• SongsOfThe80s.java

 1 import java.util.Arrays;
 2 import java.util.Iterator;
 3 
 4 public class SongsOfThe80s implements SongIterator{
 5     
 6     // Create an array of SongInfo Objects
 7     
 8     SongInfo[] bestSongs;
 9     
10     // Used to increment to the next position in the array
11     
12     int arrayValue = 0;
13     
14     public SongsOfThe80s() {
15         
16         bestSongs = new SongInfo[3];
17         
18         addSong("Roam", "B 52s", 1989);
19         addSong("Cruel Summer", "Bananarama", 1984);
20         addSong("Head Over Heels", "Tears For Fears", 1985);
21         
22     }
23     
24     // Add a SongInfo Object to the array and increment to the next position
25     
26     public void addSong(String songName, String bandName, int yearReleased){
27         
28         SongInfo song = new SongInfo(songName, bandName, yearReleased);
29             
30         bestSongs[arrayValue] = song;
31         
32         arrayValue++;
33         
34     }
35     
36     // This is replaced by the Iterator
37     
38     public SongInfo[] getBestSongs(){
39         
40         return bestSongs;
41         
42     }
43 
44     // NEW By adding this method I'll be able to treat all
45     // collections the same
46         
47     @Override
48     public Iterator createIterator() {
49         // TODO Auto-generated method stub
50         return Arrays.asList(bestSongs).iterator();    
51     }
52     
53 }

• SongsOfThe90s.java

 1 import java.util.Hashtable;
 2 import java.util.Iterator;
 3 
 4 public class SongsOfThe90s implements SongIterator{
 5     
 6     // Create a Hashtable with an int as a key and SongInfo
 7     // Objects 
 8     
 9     Hashtable<Integer, SongInfo> bestSongs = new Hashtable<Integer, SongInfo>();
10     
11     // Will increment the Hashtable key
12     
13     int hashKey = 0;
14     
15     public SongsOfThe90s() {
16         
17         addSong("Losing My Religion", "REM", 1991);
18         addSong("Creep", "Radiohead", 1993);
19         addSong("Walk on the Ocean", "Toad The Wet Sprocket", 1991);
20         
21     }
22     
23     // Add a new SongInfo Object to the Hashtable and then increment
24     // the Hashtable key
25     
26     public void addSong(String songName, String bandName, int yearReleased){
27         
28         SongInfo songInfo = new SongInfo(songName, bandName, yearReleased);
29         
30         bestSongs.put(hashKey, songInfo);
31         
32         hashKey++;
33             
34     }
35     
36     // This is replaced by the Iterator
37     // Return a Hashtable full of SongInfo Objects
38     
39     public Hashtable<Integer, SongInfo> getBestSongs(){
40         
41         return bestSongs;
42         
43     }
44 
45     // NEW By adding this method I'll be able to treat all
46     // collections the same
47     
48     public Iterator createIterator() {
49         // TODO Auto-generated method stub
50         return bestSongs.values().iterator();
51     }
52     
53 }

• DiscJockey.java

  1 import java.util.ArrayList;
  2 import java.util.Enumeration;
  3 import java.util.Hashtable;
  4 import java.util.Iterator;
  5 
  6 public class DiscJockey {
  7     
  8     SongsOfThe70s songs70s;
  9     SongsOfThe80s songs80s;
 10     SongsOfThe90s songs90s;
 11     
 12     // NEW Passing in song iterators
 13     
 14     SongIterator iter70sSongs;
 15     SongIterator iter80sSongs;
 16     SongIterator iter90sSongs;
 17     
 18     /* OLD WAY
 19     public DiscJockey(SongsOfThe70s newSongs70s, SongsOfThe80s newSongs80s, SongsOfThe90s newSongs90s) {
 20         
 21         songs70s = newSongs70s;
 22         songs80s = newSongs80s;
 23         songs90s = newSongs90s;
 24         
 25     }
 26     */
 27     
 28     // NEW WAY Initialize the iterators    
 29     
 30     public DiscJockey(SongIterator newSongs70s, SongIterator newSongs80s, SongIterator newSongs90s) {
 31         
 32         iter70sSongs = newSongs70s;
 33         iter80sSongs = newSongs80s;
 34         iter90sSongs = newSongs90s;
 35         
 36     }
 37     
 38     public void showTheSongs(){
 39         
 40         // Because the SongInfo Objects are stored in different
 41         // collections everything must be handled on an individual
 42         // basis. This is BAD!
 43         
 44         ArrayList aL70sSongs = songs70s.getBestSongs();
 45         
 46         System.out.println("Songs of the 70s\n");
 47         
 48         for(int i=0; i < aL70sSongs.size(); i++){
 49             
 50             SongInfo bestSongs = (SongInfo) aL70sSongs.get(i);
 51             
 52             System.out.println(bestSongs.getSongName());
 53             System.out.println(bestSongs.getBandName());
 54             System.out.println(bestSongs.getYearReleased() + "\n");
 55             
 56         }
 57         
 58         SongInfo[] array80sSongs = songs80s.getBestSongs();
 59         
 60         System.out.println("Songs of the 80s\n");
 61         
 62         for(int j=0; j < array80sSongs.length; j++){
 63             
 64             SongInfo bestSongs = array80sSongs[j];
 65             
 66             System.out.println(bestSongs.getSongName());
 67             System.out.println(bestSongs.getBandName());
 68             System.out.println(bestSongs.getYearReleased() + "\n");
 69             
 70         }
 71         
 72         Hashtable<Integer, SongInfo> ht90sSongs = songs90s.getBestSongs();
 73         
 74         System.out.println("Songs of the 90s\n");
 75         
 76         for (Enumeration<Integer> e = ht90sSongs.keys(); e.hasMoreElements();)
 77         {
 78             SongInfo bestSongs = ht90sSongs.get(e.nextElement());
 79             
 80             System.out.println(bestSongs.getSongName());
 81             System.out.println(bestSongs.getBandName());
 82             System.out.println(bestSongs.getYearReleased() + "\n");
 83             
 84         }
 85         
 86     }
 87     
 88     // Now that I can treat everything as an Iterator it cleans up
 89     // the code while allowing me to treat all collections as 1
 90     
 91     public void showTheSongs2(){
 92         
 93         System.out.println("NEW WAY WITH ITERATOR\n");
 94         
 95         Iterator Songs70s = iter70sSongs.createIterator();
 96         Iterator Songs80s = iter80sSongs.createIterator();
 97         Iterator Songs90s = iter90sSongs.createIterator();
 98         
 99         System.out.println("Songs of the 70s\n");
100         printTheSongs(Songs70s);
101         
102         System.out.println("Songs of the 80s\n");
103         printTheSongs(Songs80s);
104         
105         System.out.println("Songs of the 90s\n");
106         printTheSongs(Songs90s);
107         
108     }
109     
110     public void printTheSongs(Iterator iterator){
111         
112         while(iterator.hasNext()){
113             
114             SongInfo songInfo = (SongInfo) iterator.next();
115             
116             System.out.println(songInfo.getSongName());
117             System.out.println(songInfo.getBandName());
118             System.out.println(songInfo.getYearReleased() + "\n");
119             
120         }
121         
122     }
123     
124 }

• RadioStation.java

 1 public class RadioStation {
 2     
 3     public static void main(String[] args){
 4         
 5         SongsOfThe70s songs70s = new SongsOfThe70s();
 6         SongsOfThe80s songs80s = new SongsOfThe80s();
 7         SongsOfThe90s songs90s = new SongsOfThe90s();
 8         
 9         DiscJockey madMike = new DiscJockey(songs70s, songs80s, songs90s);
10         
11         // madMike.showTheSongs();
12         
13         madMike.showTheSongs2();
14         
15     }
16     
17 }

• SongIterator.java

1 import java.util.Iterator;
2 
3 public interface SongIterator {
4     
5     public Iterator createIterator();
6     
7 }

State

What is the State Design Pattern?

• Allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

• Context (Account): Maintains an instance of a ConcreteState subclass that defines the current state.

• State: Defines an interface for encapsulating the behavior associated with a particular state of the Context.

• Concrete State: Each subclass implements a behavior associated with a state of Context.

State Design Pattern Example.

• Think about all possible states for the ATM:

• HasCard

• NoCard

• HasPin

• NoCash

Sample Code

• ATMState.java

 1 public interface ATMState {
 2     
 3     // Different states expected
 4     // HasCard, NoCard, HasPin, NoCash
 5     
 6     void insertCard();
 7     
 8     void ejectCard();
 9     
10     void insertPin(int pinEntered);
11     
12     void requestCash(int cashToWithdraw);
13     
14 }

• ATMMachine.java

 1 public class ATMMachine {
 2     
 3     ATMState hasCard;     
 4     ATMState noCard;
 5     ATMState hasCorrectPin;
 6     ATMState atmOutOfMoney;
 7     
 8     ATMState atmState;
 9     
10     int cashInMachine = 2000;
11     boolean correctPinEntered = false;
12     
13     public ATMMachine(){
14         
15         hasCard = new HasCard(this);
16         noCard = new NoCard(this);
17         hasCorrectPin = new HasPin(this);
18         atmOutOfMoney = new NoCash(this);
19         
20         atmState = noCard;
21         
22         if(cashInMachine < 0){
23             
24             atmState = atmOutOfMoney;
25             
26         }
27         
28     }
29     
30     void setATMState(ATMState newATMState){
31         
32         atmState = newATMState;
33         
34     }
35     
36     public void setCashInMachine(int newCashInMachine){
37         
38         cashInMachine = newCashInMachine;
39         
40     }
41     
42     public void insertCard() {
43         
44         atmState.insertCard();
45         
46     }
47 
48     public void ejectCard() {
49         
50         atmState.ejectCard();
51         
52     }
53 
54     public void requestCash(int cashToWithdraw) {
55         
56         atmState.requestCash(cashToWithdraw);
57         
58     }
59 
60     public void insertPin(int pinEntered){
61         
62         atmState.insertPin(pinEntered);
63         
64     }
65     
66     public ATMState getYesCardState() { return hasCard; }
67     public ATMState getNoCardState() { return noCard; }
68     public ATMState getHasPin() { return hasCorrectPin; }
69     public ATMState getNoCashState() { return atmOutOfMoney; }
70     
71 }

• HasCard.java

 1 public class HasCard implements ATMState {
 2     
 3     ATMMachine atmMachine;
 4     
 5     public HasCard(ATMMachine newATMMachine){
 6         
 7         atmMachine = newATMMachine;
 8         
 9     }
10 
11     public void insertCard() {
12         
13         System.out.println("You can only insert one card at a time");
14         
15     }
16 
17     public void ejectCard() {
18         
19         System.out.println("Your card is ejected");
20         atmMachine.setATMState(atmMachine.getNoCardState());
21         
22     }
23 
24     public void requestCash(int cashToWithdraw) {
25         
26         System.out.println("You have not entered your PIN");
27         
28         
29     }
30 
31     public void insertPin(int pinEntered) {
32         
33         if(pinEntered == 1234){
34             
35             System.out.println("You entered the correct PIN");
36             atmMachine.correctPinEntered = true;
37             atmMachine.setATMState(atmMachine.getHasPin());
38             
39         } else {
40             
41             System.out.println("You entered the wrong PIN");
42             atmMachine.correctPinEntered = false;
43             System.out.println("Your card is ejected");
44             atmMachine.setATMState(atmMachine.getNoCardState());
45             
46         }    
47     }    
48 }

• NoCard.java

 1 public class NoCard implements ATMState {
 2     
 3     ATMMachine atmMachine;
 4     
 5     public NoCard(ATMMachine newATMMachine){
 6         
 7         atmMachine = newATMMachine;
 8         
 9     }
10 
11     public void insertCard() {
12         
13         System.out.println("Please enter your pin");
14         atmMachine.setATMState(atmMachine.getYesCardState());
15         
16     }
17 
18     public void ejectCard() {
19         
20         System.out.println("You didn't enter a card");
21         
22     }
23 
24     public void requestCash(int cashToWithdraw) {
25         
26         System.out.println("You have not entered your card");
27         
28     }
29 
30     public void insertPin(int pinEntered) {
31         
32         System.out.println("You have not entered your card");
33         
34     }
35 }

• HasPin.java

 1 public class HasPin implements ATMState {
 2     
 3     ATMMachine atmMachine;
 4     
 5     public HasPin(ATMMachine newATMMachine){
 6         
 7         atmMachine = newATMMachine;
 8         
 9     }
10 
11     public void insertCard() {
12         
13         System.out.println("You already entered a card");
14         
15     }
16 
17     public void ejectCard() {
18         
19         System.out.println("Your card is ejected");
20         atmMachine.setATMState(atmMachine.getNoCardState());
21         
22     }
23 
24     public void requestCash(int cashToWithdraw) {
25         
26         if(cashToWithdraw > atmMachine.cashInMachine){
27             
28             System.out.println("You don't have that much cash available");
29             System.out.println("Your card is ejected");
30             atmMachine.setATMState(atmMachine.getNoCardState());
31             
32         } else {
33             
34             System.out.println(cashToWithdraw + " is provided by the machine");
35             atmMachine.setCashInMachine(atmMachine.cashInMachine - cashToWithdraw);
36             
37             System.out.println("Your card is ejected");
38             atmMachine.setATMState(atmMachine.getNoCardState());
39             
40             if(atmMachine.cashInMachine <= 0){ 
41                 
42                 atmMachine.setATMState(atmMachine.getNoCashState());
43                 
44             }
45         } 
46     }
47 
48     public void insertPin(int pinEntered) {
49         
50         System.out.println("You already entered a PIN");
51         
52     }    
53 }

• NoCash.java

 1 public class NoCash implements ATMState {
 2     
 3     ATMMachine atmMachine;
 4     
 5     public NoCash(ATMMachine newATMMachine){
 6         
 7         atmMachine = newATMMachine;
 8         
 9     }
10 
11     public void insertCard() {
12         
13         System.out.println("We don't have any money");
14         System.out.println("Your card is ejected");
15         
16     }
17 
18     public void ejectCard() {
19         
20         System.out.println("We don't have any money");
21         System.out.println("There is no card to eject");
22         
23     }
24 
25     public void requestCash(int cashToWithdraw) {
26         
27         System.out.println("We don't have any money");
28         
29     }
30 
31     public void insertPin(int pinEntered) {
32         
33         System.out.println("We don't have any money");
34         
35     }    
36 }

• TestATMMachine.java

 1 public class TestATMMachine {
 2     
 3     public static void main(String[] args){
 4         
 5         ATMMachine atmMachine = new ATMMachine();
 6         
 7         atmMachine.insertCard();
 8         
 9         atmMachine.ejectCard();
10         
11         atmMachine.insertCard();
12         
13         atmMachine.insertPin(1234);
14         
15         atmMachine.requestCash(2000);
16         
17         atmMachine.insertCard();
18         
19         atmMachine.insertPin(1234);
20         
21     }    
22 }

Chain of Responsibility

What is the Chain of Responsibility Design Pattern?

• This pattern sends data to an object and if that object can't use it, it sends it to any number of other objects that may be able to use it.

• Create 4 objects that can either add, subtract, multiply, or divide.

• Send 2 numbers and a command and allow these 4 objects to decide which can handle the requested calculation.

Sample Code

• Chain.java

 1 // The chain of responsibility pattern has a 
 2 // group of objects that are expected to between
 3 // them be able to solve a problem. 
 4 // If the first Object can't solve it, it passes
 5 // the data to the next Object in the chain
 6 
 7 public interface Chain {
 8 
 9     // Defines the next Object to receive the data
10     // if this Object can't process it
11     
12     public void setNextChain(Chain nextChain);
13     
14     // Either solves the problem or passes the data
15     // to the next Object in the chain
16     
17     public void calculate(Numbers request);
18     
19 }

• Numbers.java

 1 // This object will contain 2 numbers and a
 2 // calculation to perform in the form of a String
 3 
 4 public class Numbers {
 5 
 6     private int number1;
 7     private int number2;
 8     
 9     private String calculationWanted;
10     
11     public Numbers(int newNumber1, int newNumber2, String calcWanted){
12         
13         number1 = newNumber1;
14         number2 = newNumber2;
15         calculationWanted = calcWanted;
16         
17     }
18     
19     public int getNumber1(){ return number1; }
20     public int getNumber2(){ return number2; }
21     public String getCalcWanted(){ return calculationWanted; }
22     
23 }

• AddNumbers.java

 1 public class AddNumbers implements Chain{
 2 
 3     private  Chain nextInChain;
 4     
 5     // Defines the next Object to receive the
 6     // data if this one can't use it
 7     
 8     public void setNextChain(Chain nextChain) {
 9         
10         nextInChain = nextChain;
11         
12     }
13 
14     // Tries to calculate the data, or passes it
15     // to the Object defined in method setNextChain()
16     
17     public void calculate(Numbers request) {
18         
19         if(request.getCalcWanted() == "add"){
20             
21             System.out.print(request.getNumber1() + " + " + request.getNumber2() + " = "+
22                     (request.getNumber1()+request.getNumber2()));
23             
24         } else {
25             
26             nextInChain.calculate(request);
27             
28         }
29         
30     }
31 }

• SubtractNumbers.java

 1 public class SubtractNumbers implements Chain{
 2 
 3     private  Chain nextInChain;
 4     
 5     @Override
 6     public void setNextChain(Chain nextChain) {
 7         
 8         nextInChain = nextChain;
 9         
10     }
11 
12     @Override
13     public void calculate(Numbers request) {
14         
15         if(request.getCalcWanted() == "sub"){
16             
17             System.out.print(request.getNumber1() + " - " + request.getNumber2() + " = "+
18                     (request.getNumber1()-request.getNumber2()));
19             
20         } else {
21             
22             nextInChain.calculate(request);
23             
24         }
25         
26     }
27 
28     
29     
30 }

• MultNumbers.java

 1 public class MultNumbers implements Chain{
 2 
 3     private  Chain nextInChain;
 4     
 5     @Override
 6     public void setNextChain(Chain nextChain) {
 7         
 8         nextInChain = nextChain;
 9         
10     }
11 
12     @Override
13     public void calculate(Numbers request) {
14         
15         if(request.getCalcWanted() == "mult"){
16             
17             System.out.print(request.getNumber1() + " * " + request.getNumber2() + " = "+
18                     (request.getNumber1()*request.getNumber2()));
19             
20         } else {
21             
22             nextInChain.calculate(request);
23             
24         }
25         
26     }
27 
28     
29     
30 }

• DivideNumbers.java

 1 public class DivideNumbers implements Chain{
 2 
 3     private  Chain nextInChain;
 4     
 5     @Override
 6     public void setNextChain(Chain nextChain) {
 7         
 8         nextInChain = nextChain;
 9         
10     }
11 
12     @Override
13     public void calculate(Numbers request) {
14         
15         if(request.getCalcWanted() == "div"){
16             
17             System.out.print(request.getNumber1() + " / " + request.getNumber2() + " = "+
18                     (request.getNumber1()/request.getNumber2()));
19             
20         } else {
21             
22             System.out.print("Only works for add, sub, mult, and div");
23             
24         }
25     }
26 }

• TestCalcChain.java

 1 public class TestCalcChain {
 2     
 3     public static void main(String[] args){
 4         
 5         // Here I define all of the objects in the chain
 6         
 7         Chain chainCalc1 = new AddNumbers();
 8         Chain chainCalc2 = new SubtractNumbers();
 9         Chain chainCalc3 = new MultNumbers();
10         Chain chainCalc4 = new DivideNumbers();
11         
12         // Here I tell each object where to forward the
13         // data if it can't process the request
14         
15         chainCalc1.setNextChain(chainCalc2);
16         chainCalc2.setNextChain(chainCalc3);
17         chainCalc3.setNextChain(chainCalc4);
18         
19         // Define the data in the Numbers Object
20         // and send it to the first Object in the chain
21         
22         Numbers request = new Numbers(4,2,"add");
23         
24         chainCalc1.calculate(request);
25         
26     }
27 
28 }

Interpreter

What is the Interpreter Design Pattern?

• "The Interpreter pattern is normally ignored."

• "This pattern is almost never used."

• I find it to be extremely useful if combined with Java Reflection techniques.

• It is used to convert one representation of data into another.

• The Context contains the information that will be interpreted.

• The Expression is an abstract class that defines all the methods needed to perform the different conversations.

• The Terminal or Concrete Expressions provide specific conversations on different types of data.

Sample Code

• ConversionContext.java

 1 public class ConversionContext {
 2 
 3     private String conversionQues = "";
 4     private String conversionResponse = "";
 5     private String fromConversion = "";
 6     private String toConversion = "";
 7     private double quantity;
 8     
 9     String[] partsOfQues;
10 
11     public ConversionContext(String input)
12     {
13       this.conversionQues = input;
14       
15       partsOfQues = getInput().split(" ");
16       
17       fromConversion = getCapitalized(partsOfQues[1]);
18       
19       toConversion = getLowercase(partsOfQues[3]);
20       
21       quantity = Double.valueOf(partsOfQues[0]);
22       
23       conversionResponse = partsOfQues[0] + " "+ partsOfQues[1] + " equals ";
24     }
25 
26     public String getInput() { return conversionQues; }
27     
28     public String getFromConversion() { return fromConversion; }
29     
30     public String getToConversion() { return toConversion; }
31     
32     public String getResponse() { return conversionResponse; }
33     
34     public double getQuantity() { return quantity; }
35     
36     // Make String lowercase
37     
38     public String getLowercase(String wordToLowercase){
39         
40         return wordToLowercase.toLowerCase();
41         
42     }
43     
44     // Capitalizes the first letter of a word
45     
46     public String getCapitalized(String wordToCapitalize){
47         
48         // Make characters lower case
49         
50         wordToCapitalize = wordToCapitalize.toLowerCase();
51         
52         // Make the first character uppercase
53         
54         wordToCapitalize = Character.toUpperCase(wordToCapitalize.charAt(0)) + wordToCapitalize.substring(1);
55         
56         // Put s on the end if not there
57         
58         int lengthOfWord = wordToCapitalize.length();
59         
60         if((wordToCapitalize.charAt(lengthOfWord -1)) != 's'){
61             
62             wordToCapitalize = new StringBuffer(wordToCapitalize).insert(lengthOfWord, "s").toString();
63             
64         }
65         
66         return wordToCapitalize;
67         
68     }
69 
70 }

• Expression.java

1 public abstract class Expression {
2     
3     public abstract String gallons(double quantity);
4     public abstract String quarts(double quantity);
5     public abstract String pints(double quantity);
6     public abstract String cups(double quantity);
7     public abstract String tablespoons(double quantity);
8     
9 }

• Gallons.java

 1 public class Gallons extends Expression{
 2 
 3     public String gallons(double quantity) {
 4         
 5         return Double.toString(quantity);
 6     }
 7 
 8     public String quarts(double quantity) {
 9         return Double.toString(quantity*4);
10     }
11 
12     public String pints(double quantity) {
13         return Double.toString(quantity*8);
14     }
15 
16     public String cups(double quantity) {
17         return Double.toString(quantity*16);
18     }
19 
20     public String tablespoons(double quantity) {
21         return Double.toString(quantity*256);
22     }
23     
24 }

• Quarts.java

 1 public class Quarts extends Expression{
 2 
 3     public String gallons(double quantity) {
 4         
 5         return Double.toString(quantity/4);
 6     }
 7 
 8     public String quarts(double quantity) {
 9         return Double.toString(quantity);
10     }
11 
12     public String pints(double quantity) {
13         return Double.toString(quantity*2);
14     }
15 
16     public String cups(double quantity) {
17         return Double.toString(quantity*4);
18     }
19 
20     public String tablespoons(double quantity) {
21         return Double.toString(quantity*64);
22     }
23     
24 }

 • Pints.java

 1 public class Pints extends Expression{
 2 
 3     public String gallons(double quantity) {
 4         
 5         return Double.toString(quantity/8);
 6     }
 7 
 8     public String quarts(double quantity) {
 9         return Double.toString(quantity/2);
10     }
11 
12     public String pints(double quantity) {
13         return Double.toString(quantity);
14     }
15 
16     public String cups(double quantity) {
17         return Double.toString(quantity*2);
18     }
19 
20     public String tablespoons(double quantity) {
21         return Double.toString(quantity*32);
22     }
23     
24 }

• Cups.java

 1 public class Cups extends Expression{
 2 
 3     public String gallons(double quantity) {
 4         
 5         return Double.toString(quantity/16);
 6     }
 7 
 8     public String quarts(double quantity) {
 9         return Double.toString(quantity/4);
10     }
11 
12     public String pints(double quantity) {
13         return Double.toString(quantity/2);
14     }
15 
16     public String cups(double quantity) {
17         return Double.toString(quantity);
18     }
19 
20     public String tablespoons(double quantity) {
21         return Double.toString(quantity*16);
22     }
23     
24 }

• Tablespoons.java

 1 public class Tablespoons extends Expression{
 2 
 3     public String gallons(double quantity) {
 4         
 5         return Double.toString(quantity/256);
 6     }
 7 
 8     public String quarts(double quantity) {
 9         return Double.toString(quantity/64);
10     }
11 
12     public String pints(double quantity) {
13         return Double.toString(quantity/32);
14     }
15 
16     public String cups(double quantity) {
17         return Double.toString(quantity/16);
18     }
19 
20     public String tablespoons(double quantity) {
21         return Double.toString(quantity);
22     }
23     
24 }

• MeasurementConversion.java

 1 import java.lang.reflect.*;
 2 
 3 import javax.swing.*;
 4 
 5 public class MeasurementConversion {
 6     
 7     public static void main(String[] args){
 8         
 9         // Create pop up window that asks for a question
10         
11         JFrame frame = new JFrame();
12         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
13         
14         String questionAsked = JOptionPane.showInputDialog(frame, "What is your question");
15         
16         // Add the question to the context for analysis
17         
18         ConversionContext question = new ConversionContext(questionAsked);
19         
20         String fromConversion = question.getFromConversion();
21         
22         String toConversion = question.getToConversion();
23         
24         double quantity = question.getQuantity();
25         
26         try {
27             
28             // Get class based on the from conversion string
29             
30             Class tempClass = Class.forName(fromConversion);
31             
32             // Get the constructor dynamically for the conversion string
33             
34             Constructor con = tempClass.getConstructor();
35             
36             // Create a new instance of the object you want to convert from
37             
38             Object convertFrom = (Expression) con.newInstance();
39             
40             // Define the method parameters expected by the method that
41             // will convert to your chosen unit of measure
42             
43             Class[] methodParams = new Class[]{Double.TYPE};
44             
45             // Get the method dynamically that will be needed to convert
46             // into your chosen unit of measure
47 
48             Method conversionMethod = tempClass.getMethod(toConversion, methodParams);
49             
50             // Define the method parameters that will be passed to the above method
51             
52             Object[] params = new Object[]{new Double(quantity)};
53             
54             // Get the quantity after the conversion
55             
56             String toQuantity = (String) conversionMethod.invoke(convertFrom, params);
57             
58             // Print the results
59             
60             String answerToQues = question.getResponse() + 
61                     toQuantity + " " + toConversion;
62             
63             JOptionPane.showMessageDialog(null,answerToQues);
64             
65             // Closes the frame after OK is clicked
66             
67             frame.dispose();
68             
69         } catch (ClassNotFoundException e) {
70             // TODO Auto-generated catch block
71             e.printStackTrace();
72         } catch (NoSuchMethodException e) {
73             // TODO Auto-generated catch block
74             e.printStackTrace();
75         } catch (SecurityException e) {
76             // TODO Auto-generated catch block
77             e.printStackTrace();
78         } catch (InstantiationException e) {
79             // TODO Auto-generated catch block
80             e.printStackTrace();
81         } catch (IllegalAccessException e) {
82             // TODO Auto-generated catch block
83             e.printStackTrace();
84         } catch (IllegalArgumentException e) {
85             // TODO Auto-generated catch block
86             e.printStackTrace();
87         } catch (InvocationTargetException e) {
88             // TODO Auto-generated catch block
89             e.printStackTrace();
90         }
91         
92     }
93     
94 }

Mediator

What is the Mediator Design Pattern?

• It is used to handle communication between related objects (Colleagues).

• All communication is handled by the Mediator and the Colleagues don't need to know anything about each other.

• GOF: Allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other. Allows for the actions of each object set to vary independently of one another.

Sample Code

• StockOffer.java

 1 public class StockOffer{
 2     
 3     private int stockShares = 0;
 4     private String stockSymbol = "";
 5     private int colleagueCode = 0;
 6     
 7     public StockOffer(int numOfShares, String stock, int collCode){
 8         
 9         stockShares = numOfShares;
10         stockSymbol = stock;
11         colleagueCode = collCode;
12         
13     }
14     
15     public int getstockShares() { return stockShares; }
16     public String getStockSymbol() { return stockSymbol; }
17     public int getCollCode() { return colleagueCode; }
18     
19 }

• Colleague.java

 1 public abstract class Colleague{
 2     
 3     private Mediator mediator;
 4     private int colleagueCode;
 5     
 6     
 7     public Colleague(Mediator newMediator){ 
 8         mediator = newMediator; 
 9         
10         mediator.addColleague(this);
11     
12     }
13     
14     public void saleOffer(String stock, int shares){
15         
16         mediator.saleOffer(stock, shares, this.colleagueCode);
17         
18     }
19     
20     public void buyOffer(String stock, int shares){
21         
22         mediator.buyOffer(stock, shares, this.colleagueCode);
23         
24     }
25     
26     public void setCollCode(int collCode){ colleagueCode = collCode; }
27     
28     
29 }

• GormanSlacks.java

 1 public class GormanSlacks extends Colleague{
 2 
 3     public GormanSlacks(Mediator newMediator) {
 4         super(newMediator);
 5         
 6         System.out.println("Gorman Slacks signed up with the stockexchange\n");
 7         
 8     }
 9     
10 }

• JTPoorman.java

 1 public class JTPoorman extends Colleague{
 2 
 3     public JTPoorman(Mediator newMediator) {
 4         super(newMediator);
 5         
 6         System.out.println("JT Poorman signed up with the stockexchange\n");
 7         
 8     }
 9     
10 }

• Mediator.java

1 public interface Mediator {
2     
3     public void saleOffer(String stock, int shares, int collCode);
4     
5     public void buyOffer(String stock, int shares, int collCode);
6 
7     public void addColleague(Colleague colleague);
8     
9 }

• StockMediator.java

  1 import java.util.ArrayList;
  2 
  3 public class StockMediator implements Mediator{
  4 
  5     private ArrayList<Colleague> colleagues;
  6     private ArrayList<StockOffer> stockBuyOffers;
  7     private ArrayList<StockOffer> stockSaleOffers;
  8     
  9     private int colleagueCodes = 0;
 10     
 11     public StockMediator(){
 12         
 13         colleagues = new ArrayList<Colleague>();
 14         stockBuyOffers = new ArrayList<StockOffer>();
 15         stockSaleOffers = new ArrayList<StockOffer>();
 16     }
 17     
 18     public void addColleague(Colleague newColleague){
 19         
 20         colleagues.add(newColleague);
 21         
 22         colleagueCodes++;
 23         
 24         newColleague.setCollCode(colleagueCodes);
 25         
 26     }
 27     
 28     public void saleOffer(String stock, int shares, int collCode) {
 29 
 30         boolean stockSold = false;
 31         
 32         for(StockOffer offer: stockBuyOffers){
 33             
 34             if((offer.getStockSymbol() == stock) && (offer.getstockShares() == shares)){
 35                 
 36                 System.out.println(shares + " shares of " + stock + 
 37                         " sold to colleague code " + offer.getCollCode());
 38                 
 39                 stockBuyOffers.remove(offer);
 40                 
 41                 stockSold = true;
 42                 
 43             } 
 44             
 45             if(stockSold){ break; }
 46             
 47         }
 48         
 49         if(!stockSold) {
 50             
 51             System.out.println(shares + " shares of " + stock + 
 52                     " added to inventory");
 53             
 54             StockOffer newOffering = new StockOffer(shares, stock, collCode);
 55             
 56             stockSaleOffers.add(newOffering);
 57             
 58         }
 59     
 60     }
 61 
 62     public void buyOffer(String stock, int shares, int collCode) {
 63         
 64         boolean stockBought = false;
 65         
 66         for(StockOffer offer: stockSaleOffers){
 67             
 68             if((offer.getStockSymbol() == stock) && (offer.getstockShares() == shares)){
 69                 
 70                 System.out.println(shares + " shares of " + stock + 
 71                         " bought by colleague code " + offer.getCollCode());
 72                 
 73                 stockSaleOffers.remove(offer);
 74                 
 75                 stockBought = true;
 76                 
 77             } 
 78             
 79             if(stockBought){ break; }
 80             
 81         }
 82         
 83         if(!stockBought) {
 84             
 85             System.out.println(shares + " shares of " + stock + 
 86                     " added to inventory");
 87             
 88             StockOffer newOffering = new StockOffer(shares, stock, collCode);
 89             
 90             stockBuyOffers.add(newOffering);
 91             
 92         }
 93         
 94     }
 95     
 96     public void getstockOfferings(){
 97         
 98         System.out.println("\nStocks for Sale");
 99         
100         for(StockOffer offer: stockSaleOffers){
101             
102             System.out.println(offer.getstockShares() + " of " + offer.getStockSymbol());
103             
104         }
105         
106         System.out.println("\nStock Buy Offers");
107         
108         for(StockOffer offer: stockBuyOffers){
109             
110             System.out.println(offer.getstockShares() + " of " + offer.getStockSymbol());
111             
112         }
113         
114     }
115     
116 }

• TestStockMediator.java

 1 public class TestStockMediator{
 2     
 3     public static void main(String[] args){
 4         
 5         StockMediator nyse = new StockMediator();
 6         
 7         GormanSlacks broker = new GormanSlacks(nyse);
 8         
 9         JTPoorman broker2 = new JTPoorman(nyse);
10         
11         broker.saleOffer("MSFT", 100);
12         broker.saleOffer("GOOG", 50);
13         
14         broker2.buyOffer("MSFT", 100);
15         broker2.saleOffer("NRG", 10);
16         
17         broker.buyOffer("NRG", 10);
18         
19         nyse.getstockOfferings();
20         
21     }
22     
23 }

Memento

What is the Memento Design Pattern?

• A way to store previous states of an object easily.

• Memento: The basic object that is stored in different states.

• Originator: Sets and Gets values from the currently targeted Memento. Creates new mementos and assign current values to them.

• Caretaker: Holds an ArrayList that contains all previous versions of the Memento. It can store and retrieve stored Mementos.

Sample Code

• Memento.java

 1 // Memento Design Pattern
 2 // Used stores an objects state at a point in time
 3 // so it can be returned to that state later. It
 4 // simply allows you to undo/redo changes on an Object
 5 
 6 public class Memento {
 7     
 8     // The article stored in memento Object
 9     
10     private String article;
11 
12     // Save a new article String to the memento Object
13     
14     public Memento(String articleSave) { article = articleSave; }
15     
16     // Return the value stored in article 
17     
18     public String getSavedArticle() { return article; }
19     
20 }

• Originator.java

 1 // Memento Design Pattern
 2 
 3 public class Originator{
 4     
 5     private String article;
 6 
 7     // Sets the value for the article
 8     
 9     public void set(String newArticle) { 
10         System.out.println("From Originator: Current Version of Article\n"+newArticle+ "\n");
11         this.article = newArticle; 
12     }
13 
14     // Creates a new Memento with a new article
15     
16     public Memento storeInMemento() { 
17         System.out.println("From Originator: Saving to Memento");
18         return new Memento(article); 
19     }
20        
21     // Gets the article currently stored in memento
22     
23     public String restoreFromMemento(Memento memento) {
24            
25         article = memento.getSavedArticle(); 
26            
27         System.out.println("From Originator: Previous Article Saved in Memento\n"+article + "\n");
28         
29         return article;
30        
31     }
32     
33 }

• Caretaker.java

 1 // Memento Design Pattern Tutorial
 2 
 3 import java.util.ArrayList;
 4 
 5 class Caretaker {
 6    
 7     // Where all mementos are saved
 8     
 9     ArrayList<Memento> savedArticles = new ArrayList<Memento>();
10 
11     // Adds memento to the ArrayList
12     
13     public void addMemento(Memento m) { savedArticles.add(m); }
14    
15     // Gets the memento requested from the ArrayList
16     
17     public Memento getMemento(int index) { return savedArticles.get(index); }
18 } 

• TestMemento.java

  1 // Memento Design Pattern Tutorial
  2 
  3 import java.awt.event.ActionEvent;
  4 import java.awt.event.ActionListener;
  5 
  6 import javax.swing.*;
  7 
  8 public class TestMemento extends JFrame{
  9    public static void main(String[] args) {
 10        
 11        new TestMemento();
 12        
 13    }
 14    
 15    private JButton saveBut, undoBut, redoBut;
 16    
 17    // JTextArea(rows, columns)
 18    
 19    private JTextArea theArticle = new JTextArea(40,60);
 20    
 21    // ---------------------------------------------
 22    
 23    // Create a caretaker that contains the ArrayList 
 24    // with all the articles in it. It can add and
 25    // retrieve articles from the ArrayList
 26    
 27    Caretaker caretaker = new Caretaker();
 28 
 29    // The originator sets the value for the article,
 30    // creates a new memento with a new article, and 
 31    // gets the article stored in the current memento
 32    
 33    Originator originator = new Originator();
 34    
 35    int saveFiles = 0, currentArticle = 0;
 36    
 37    // ---------------------------------------------
 38    
 39    public TestMemento(){
 40        
 41        // Set basic information for the panel that will
 42        // hold all the GUI elements
 43        
 44        this.setSize(750,780);
 45        this.setTitle("Memento Design Pattern");
 46        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 47        
 48        JPanel panel1 = new JPanel();
 49        
 50        // Add label to the panel
 51        
 52        panel1.add(new JLabel("Article"));
 53        
 54        // Add JTextArea to the panel
 55        
 56        panel1.add(theArticle);
 57        
 58        // Add the buttons & ButtonListeners to the panel
 59        
 60        ButtonListener saveListener = new ButtonListener();
 61        ButtonListener undoListener = new ButtonListener();
 62        ButtonListener redoListener = new ButtonListener();
 63        
 64        saveBut = new JButton("Save");
 65        saveBut.addActionListener(saveListener);
 66        
 67        undoBut = new JButton("Undo");
 68        undoBut.addActionListener(undoListener);
 69        
 70        redoBut = new JButton("Redo");
 71        redoBut.addActionListener(redoListener);
 72        
 73        panel1.add(saveBut);
 74        panel1.add(undoBut);
 75        panel1.add(redoBut);
 76        
 77        // Add panel to the frame that shows on screen
 78        
 79        this.add(panel1);
 80        
 81        this.setVisible(true);
 82        
 83    }
 84    
 85    class ButtonListener implements ActionListener {
 86 
 87         public void actionPerformed(ActionEvent e) {
 88             
 89             if(e.getSource() == saveBut){
 90                 
 91                 // Get text in JTextArea
 92                 
 93                 String textInTextArea = theArticle.getText();
 94                 
 95                 // Set the value for the current memento
 96                 
 97                 originator.set(textInTextArea);
 98                 
 99                 // Add new article to the ArrayList
100                 
101                 caretaker.addMemento( originator.storeInMemento() );
102                 
103                 // saveFiles monitors how many articles are saved
104                 // currentArticle monitors the current article displayed
105                 
106                 saveFiles++;
107                 currentArticle++;
108                 
109                 System.out.println("Save Files " + saveFiles);
110                 
111                 // Make undo clickable
112                 
113                 undoBut.setEnabled(true);
114                 
115             } else 
116                 
117                 if(e.getSource() == undoBut){
118                     
119                     if(currentArticle >= 1){
120                         
121                         // Decrement to the current article displayed
122                         
123                         currentArticle--;
124                         
125                         // Get the older article saved and display it in JTextArea
126                     
127                         String textBoxString = originator.restoreFromMemento( caretaker.getMemento(currentArticle) );
128                         
129                         theArticle.setText(textBoxString);
130                         
131                         // Make Redo clickable
132                         
133                         redoBut.setEnabled(true);
134                     
135                     } else {
136                         
137                         // Don't allow user to click Undo
138                         
139                         undoBut.setEnabled(false);
140                         
141                     }
142                     
143                 } else
144                     
145                     if(e.getSource() == redoBut){
146                     
147                     if((saveFiles - 1) > currentArticle){
148                         
149                         // Increment to the current article displayed
150                         
151                         currentArticle++;
152                         
153                         // Get the newer article saved and display it in JTextArea
154                     
155                         String textBoxString = originator.restoreFromMemento( caretaker.getMemento(currentArticle) );
156                         
157                         theArticle.setText(textBoxString);
158                         
159                         // Make undo clickable
160                         
161                         undoBut.setEnabled(true);
162                     
163                     } else {
164                         
165                         // Don't allow user to click Redo
166                         
167                         redoBut.setEnabled(false);
168                         
169                     }
170                     
171                 }
172             
173         }
174         
175     }
176    
177 }

Visitor

What is the Visitor Design Pattern?

• Allows you to add methods to classes of different types without much altering to those classes.

• You can make completely different methods depending on the class used.

• Allows you to define external classes that can extend other classes without majorly editing them.

Sample Code

• Visitor.java

 1 // The visitor pattern is used when you have to perform
 2 // the same action on many objects of different types
 3 
 4 interface Visitor {
 5     
 6     // Created to automatically use the right 
 7     // code based on the Object sent
 8     // Method Overloading
 9     
10     public double visit(Liquor liquorItem);
11     
12     public double visit(Tobacco tobaccoItem);
13     
14     public double visit(Necessity necessityItem);
15     
16 }

• TaxVisitor.java

 1 import java.text.DecimalFormat;
 2 
 3 // Concrete Visitor Class
 4 
 5 class TaxVisitor implements Visitor {
 6     
 7     // This formats the item prices to 2 decimal places
 8     
 9     DecimalFormat df = new DecimalFormat("#.##");
10 
11     // This is created so that each item is sent to the
12     // right version of visit() which is required by the
13     // Visitor interface and defined below
14     
15     public TaxVisitor() {
16     }
17     
18     // Calculates total price based on this being taxed
19     // as a liquor item
20     
21     public double visit(Liquor liquorItem) {
22         System.out.println("Liquor Item: Price with Tax");
23         return Double.parseDouble(df.format((liquorItem.getPrice() * .18) + liquorItem.getPrice()));
24     }
25     
26     // Calculates total price based on this being taxed
27     // as a tobacco item
28         
29     public double visit(Tobacco tobaccoItem) {
30         System.out.println("Tobacco Item: Price with Tax");
31         return Double.parseDouble(df.format((tobaccoItem.getPrice() * .32) + tobaccoItem.getPrice()));
32     }
33     
34     // Calculates total price based on this being taxed
35     // as a necessity item
36         
37     public double visit(Necessity necessityItem) {
38         System.out.println("Necessity Item: Price with Tax");
39         return Double.parseDouble(df.format(necessityItem.getPrice()));
40     }
41 
42 }

• Visitable.java

 1 interface Visitable {
 2 
 3     // Allows the Visitor to pass the object so
 4     // the right operations occur on the right 
 5     // type of object.
 6     
 7     // accept() is passed the same visitor object
 8     // but then the method visit() is called using 
 9     // the visitor object. The right version of visit()
10     // is called because of method overloading
11     
12     public double accept(Visitor visitor);
13     
14 }

• Liquor.java

 1 class Liquor implements Visitable {
 2     
 3     private double price;
 4 
 5     Liquor(double item) {
 6         price = item;
 7     }
 8 
 9     public double accept(Visitor visitor) {
10         return visitor.visit(this);
11     }
12 
13     public double getPrice() {
14         return price;
15     }
16     
17 }

• Necessity.java

 1 class Necessity implements Visitable {
 2     
 3     private double price;
 4 
 5     Necessity(double item) {
 6         price = item;
 7     }
 8 
 9     public double accept(Visitor visitor) {
10         return visitor.visit(this);
11     }
12 
13     public double getPrice() {
14         return price;
15     }
16     
17 }

• Tobacco.java

 1 class Tobacco implements Visitable {
 2     
 3     private double price;
 4 
 5     Tobacco(double item) {
 6         price = item;
 7     }
 8 
 9     public double accept(Visitor visitor) {
10         return visitor.visit(this);
11     }
12 
13     public double getPrice() {
14         return price;
15     }
16     
17 }

• TaxHolidayVisitor.java

 1 import java.text.DecimalFormat;
 2 
 3 // Concrete Visitor Class
 4 
 5 class TaxHolidayVisitor implements Visitor {
 6     
 7     // This formats the item prices to 2 decimal places
 8     
 9     DecimalFormat df = new DecimalFormat("#.##");
10 
11     // This is created so that each item is sent to the
12     // right version of visit() which is required by the
13     // Visitor interface and defined below
14     
15     public TaxHolidayVisitor() {
16     }
17     
18     // Calculates total price based on this being taxed
19     // as a liquor item
20     
21     public double visit(Liquor liquorItem) {
22         System.out.println("Liquor Item: Price with Tax");
23         return Double.parseDouble(df.format((liquorItem.getPrice() * .10) + liquorItem.getPrice()));
24     }
25     
26     // Calculates total price based on this being taxed
27     // as a tobacco item
28         
29     public double visit(Tobacco tobaccoItem) {
30         System.out.println("Tobacco Item: Price with Tax");
31         return Double.parseDouble(df.format((tobaccoItem.getPrice() * .30) + tobaccoItem.getPrice()));
32     }
33     
34     // Calculates total price based on this being taxed
35     // as a necessity item
36         
37     public double visit(Necessity necessityItem) {
38         System.out.println("Necessity Item: Price with Tax");
39         return Double.parseDouble(df.format(necessityItem.getPrice()));
40     }
41 
42 }

• VisitorTest.java

 1 public class VisitorTest {
 2     public static void main(String[] args) {
 3         
 4         TaxVisitor taxCalc = new TaxVisitor();
 5         TaxHolidayVisitor taxHolidayCalc = new TaxHolidayVisitor();
 6         
 7         Necessity milk = new Necessity(3.47);
 8         Liquor vodka = new Liquor(11.99);
 9         Tobacco cigars = new Tobacco(19.99);
10         
11         System.out.println(milk.accept(taxCalc) + "\n");
12         System.out.println(vodka.accept(taxCalc) + "\n");
13         System.out.println(cigars.accept(taxCalc) + "\n");
14         
15         System.out.println("TAX HOLIDAY PRICES\n");
16 
17         System.out.println(milk.accept(taxHolidayCalc) + "\n");
18         System.out.println(vodka.accept(taxHolidayCalc) + "\n");
19         System.out.println(cigars.accept(taxHolidayCalc) + "\n");
20 
21     }
22 }

 

作者:netoxi
出处:http://www.cnblogs.com/netoxi
本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。

 

posted on 2018-12-19 10:08  netoxi  阅读(405)  评论(0编辑  收藏  举报