• 设计模式教程(Design Patterns Tutorial)笔记之三 行为型模式(Behavioral Patterns)


    目录

    · 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 + "
    IBM: " + ibmPrice + "
    AAPL: " + 
    57                 aaplPrice + "
    GOOG: " + googPrice + "
    ");
    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("
    "); }
    29             
    30             addCheese();
    31             
    32             afterFirstCondiment = true;
    33             
    34         }
    35         
    36         if(customerWantsVegetables()){
    37             
    38             if(afterFirstCondiment) { System.out.print("
    "); }
    39             
    40             addVegetables();
    41             
    42             afterFirstCondiment = true;
    43             
    44         }
    45         
    46         if(customerWantsCondiments()){
    47             
    48             if(afterFirstCondiment) { System.out.print("
    "); }
    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("
    Wrap the Hoagie");
    87         
    88     }
    89     
    90     public void afterFirstCondiment(){
    91         
    92         System.out.println("
    ");
    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
    ");
     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() + "
    ");
     55             
     56         }
     57         
     58         SongInfo[] array80sSongs = songs80s.getBestSongs();
     59         
     60         System.out.println("Songs of the 80s
    ");
     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() + "
    ");
     69             
     70         }
     71         
     72         Hashtable<Integer, SongInfo> ht90sSongs = songs90s.getBestSongs();
     73         
     74         System.out.println("Songs of the 90s
    ");
     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() + "
    ");
     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
    ");
     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
    ");
    100         printTheSongs(Songs70s);
    101         
    102         System.out.println("Songs of the 80s
    ");
    103         printTheSongs(Songs80s);
    104         
    105         System.out.println("Songs of the 90s
    ");
    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() + "
    ");
    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
    ");
     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
    ");
     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("
    Stocks 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("
    Stock 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
    "+newArticle+ "
    ");
    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
    "+article + "
    ");
    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) + "
    ");
    12         System.out.println(vodka.accept(taxCalc) + "
    ");
    13         System.out.println(cigars.accept(taxCalc) + "
    ");
    14         
    15         System.out.println("TAX HOLIDAY PRICES
    ");
    16 
    17         System.out.println(milk.accept(taxHolidayCalc) + "
    ");
    18         System.out.println(vodka.accept(taxHolidayCalc) + "
    ");
    19         System.out.println(cigars.accept(taxHolidayCalc) + "
    ");
    20 
    21     }
    22 }

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

  • 相关阅读:
    使用json-lib进行Java和JSON之间的转换
    ajax+json+java
    了解Json
    Ehcache RIM
    利用FreeMarker静态化网页
    Timer和TimerTask
    windows下memcache安装
    mac下安装YII
    php static 和self区别
    YII behaviors使用
  • 原文地址:https://www.cnblogs.com/netoxi/p/10089221.html
Copyright © 2020-2023  润新知