目录

· 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

 public class Animal {

     private String name;
private double height;
private int weight;
private String favFood;
private double speed;
private String sound; // Instead of using an interface in a traditional way
// we use an instance variable that is a subclass
// of the Flys interface. // Animal doesn't care what flyingType does, it just
// knows the behavior is available to its subclasses // This is known as Composition : Instead of inheriting
// an ability through inheritance the class is composed
// with Objects with the right ability // Composition allows you to change the capabilities of
// objects at run time! public Flys flyingType; public void setName(String newName){ name = newName; }
public String getName(){ return name; } public void setHeight(double newHeight){ height = newHeight; }
public double getHeight(){ return height; } public void setWeight(int newWeight){
if (newWeight > 0){
weight = newWeight;
} else {
System.out.println("Weight must be bigger than 0");
}
}
public double getWeight(){ return weight; } public void setFavFood(String newFavFood){ favFood = newFavFood; }
public String getFavFood(){ return favFood; } public void setSpeed(double newSpeed){ speed = newSpeed; }
public double getSpeed(){ return speed; } public void setSound(String newSound){ sound = newSound; }
public String getSound(){ return sound; } /* BAD
* You don't want to add methods to the super class.
* You need to separate what is different between subclasses
* and the super class
public void fly(){ System.out.println("I'm flying"); }
*/ // Animal pushes off the responsibility for flying to flyingType public String tryToFly(){ return flyingType.fly(); } // If you want to be able to change the flyingType dynamically
// add the following method public void setFlyingAbility(Flys newFlyType){ flyingType = newFlyType; } }

• Dog.java

 public class Dog extends Animal{

     public void digHole(){

         System.out.println("Dug a hole");

     }

     public Dog(){

         super();

         setSound("Bark");

         // We set the Flys interface polymorphically
// This sets the behavior as a non-flying Animal flyingType = new CantFly(); } /* BAD
* You could override the fly method, but we are breaking
* the rule that we need to abstract what is different to
* the subclasses
*
public void fly(){ System.out.println("I can't fly"); }
*/ }

• Bird.java

 public class Bird extends Animal{

     // The constructor initializes all objects

     public Bird(){

         super();

         setSound("Tweet");

         // We set the Flys interface polymorphically
// This sets the behavior as a non-flying Animal flyingType = new ItFlys(); } }

• Flys.java

 // The interface is implemented by many other
// subclasses that allow for many types of flying
// without effecting Animal, or Flys. // Classes that implement new Flys interface
// subclasses can allow other classes to use
// that code eliminating code duplication // I'm decoupling : encapsulating the concept that varies public interface Flys { String fly(); } // Class used if the Animal can fly class ItFlys implements Flys{ public String fly() { return "Flying High"; } } //Class used if the Animal can't fly class CantFly implements Flys{ public String fly() { return "I can't fly"; } }

• AnimalPlay.java

 public class AnimalPlay{

     public static void main(String[] args){

         Animal sparky = new Dog();
Animal tweety = new Bird(); System.out.println("Dog: " + sparky.tryToFly()); System.out.println("Bird: " + tweety.tryToFly()); // This allows dynamic changes for flyingType sparky.setFlyingAbility(new ItFlys()); System.out.println("Dog: " + sparky.tryToFly()); } }

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

 // This interface handles adding, deleting and updating
// all observers public interface Subject { public void register(Observer o);
public void unregister(Observer o);
public void notifyObserver(); }

• Observer.java

 // The Observers update method is called when the Subject changes

 public interface Observer {

     public void update(double ibmPrice, double aaplPrice, double googPrice);

 }

• StockGrabber.java

 import java.util.ArrayList;

 // Uses the Subject interface to update all Observers

 public class StockGrabber implements Subject{

     private ArrayList<Observer> observers;
private double ibmPrice;
private double aaplPrice;
private double googPrice; public StockGrabber(){ // Creates an ArrayList to hold all observers observers = new ArrayList<Observer>();
} public void register(Observer newObserver) { // Adds a new observer to the ArrayList observers.add(newObserver); } public void unregister(Observer deleteObserver) { // Get the index of the observer to delete int observerIndex = observers.indexOf(deleteObserver); // Print out message (Have to increment index to match) System.out.println("Observer " + (observerIndex+1) + " deleted"); // Removes observer from the ArrayList observers.remove(observerIndex); } public void notifyObserver() { // Cycle through all observers and notifies them of
// price changes for(Observer observer : observers){ observer.update(ibmPrice, aaplPrice, googPrice); }
} // Change prices for all stocks and notifies observers of changes public void setIBMPrice(double newIBMPrice){ this.ibmPrice = newIBMPrice; notifyObserver(); } public void setAAPLPrice(double newAAPLPrice){ this.aaplPrice = newAAPLPrice; notifyObserver(); } public void setGOOGPrice(double newGOOGPrice){ this.googPrice = newGOOGPrice; notifyObserver(); } }

• StockObserver.java

 // Represents each Observer that is monitoring changes in the subject

 public class StockObserver implements Observer {

     private double ibmPrice;
private double aaplPrice;
private double googPrice; // Static used as a counter private static int observerIDTracker = 0; // Used to track the observers private int observerID; // Will hold reference to the StockGrabber object private Subject stockGrabber; public StockObserver(Subject stockGrabber){ // Store the reference to the stockGrabber object so
// I can make calls to its methods this.stockGrabber = stockGrabber; // Assign an observer ID and increment the static counter this.observerID = ++observerIDTracker; // Message notifies user of new observer System.out.println("New Observer " + this.observerID); // Add the observer to the Subjects ArrayList stockGrabber.register(this); } // Called to update all observers public void update(double ibmPrice, double aaplPrice, double googPrice) { this.ibmPrice = ibmPrice;
this.aaplPrice = aaplPrice;
this.googPrice = googPrice; printThePrices(); } public void printThePrices(){ System.out.println(observerID + "\nIBM: " + ibmPrice + "\nAAPL: " +
aaplPrice + "\nGOOG: " + googPrice + "\n"); } }

• GrabStocks.java

 public class GrabStocks{

     public static void main(String[] args){

         // Create the Subject object
// It will handle updating all observers
// as well as deleting and adding them StockGrabber stockGrabber = new StockGrabber(); // Create an Observer that will be sent updates from Subject StockObserver observer1 = new StockObserver(stockGrabber); stockGrabber.setIBMPrice(197.00);
stockGrabber.setAAPLPrice(677.60);
stockGrabber.setGOOGPrice(676.40); StockObserver observer2 = new StockObserver(stockGrabber); stockGrabber.setIBMPrice(197.00);
stockGrabber.setAAPLPrice(677.60);
stockGrabber.setGOOGPrice(676.40); // Delete one of the observers // stockGrabber.unregister(observer2); stockGrabber.setIBMPrice(197.00);
stockGrabber.setAAPLPrice(677.60);
stockGrabber.setGOOGPrice(676.40); // Create 3 threads using the Runnable interface
// GetTheStock implements Runnable, so it doesn't waste
// its one extendable class option Runnable getIBM = new GetTheStock(stockGrabber, 2, "IBM", 197.00);
Runnable getAAPL = new GetTheStock(stockGrabber, 2, "AAPL", 677.60);
Runnable getGOOG = new GetTheStock(stockGrabber, 2, "GOOG", 676.40); // Call for the code in run to execute new Thread(getIBM).start();
new Thread(getAAPL).start();
new Thread(getGOOG).start(); } }

• GetTheStock.java

 import java.text.DecimalFormat;

 public class GetTheStock implements Runnable{

     // Could be used to set how many seconds to wait
// in Thread.sleep() below // private int startTime;
private String stock;
private double price; // Will hold reference to the StockGrabber object private Subject stockGrabber; public GetTheStock(Subject stockGrabber, int newStartTime, String newStock, double newPrice){ // Store the reference to the stockGrabber object so
// I can make calls to its methods this.stockGrabber = stockGrabber; // startTime = newStartTime; Not used to have variable sleep time
stock = newStock;
price = newPrice; } public void run(){ for(int i = 1; i <= 20; i++){ try{ // Sleep for 2 seconds
Thread.sleep(2000); // Use Thread.sleep(startTime * 1000); to
// make sleep time variable
}
catch(InterruptedException e)
{} // Generates a random number between -.03 and .03 double randNum = (Math.random() * (.06)) - .03; // Formats decimals to 2 places DecimalFormat df = new DecimalFormat("#.##"); // Change the price and then convert it back into a double price = Double.valueOf(df.format((price + randNum))); if(stock == "IBM") ((StockGrabber) stockGrabber).setIBMPrice(price);
if(stock == "AAPL") ((StockGrabber) stockGrabber).setAAPLPrice(price);
if(stock == "GOOG") ((StockGrabber) stockGrabber).setGOOGPrice(price); System.out.println(stock + ": " + df.format((price + randNum)) +
" " + df.format(randNum)); System.out.println(); }
} }

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

 public interface ElectronicDevice {

     public void on();

     public void off();

     public void volumeUp();

     public void volumenDown();

 }

• Television.java(RECEIVER)

 public class Television implements ElectronicDevice {

     private int volume = 0;

     public void on() {

         System.out.println("TV is on");

     }

     public void off() {

         System.out.println("TV is off");

     }

     public void volumeUp() {

         volume++;

         System.out.println("TV Volume is at: " + volume);

     }

     public void volumenDown() {

         volume--;

         System.out.println("TV Volume is at: " + volume);

     }

 }

• Command.java

 // Each command you want to issue will implement
// the Command interface public interface Command { public void execute(); // You may want to offer the option to undo a command public void undo(); }

• TurnTVOn.java(COMMAND)

 public class TurnTVOn implements Command {

     ElectronicDevice theDevice;

     public TurnTVOn(ElectronicDevice newDevice){

         theDevice = newDevice;

     }

     public void execute() {

         theDevice.on();

     }

     public void undo() {

         theDevice.off();

     }

 }

• TurnTVOff.java(COMMAND)

 public class TurnTVOff implements Command {

     ElectronicDevice theDevice;

     public TurnTVOff(ElectronicDevice newDevice){

         theDevice = newDevice;

     }

     public void execute() {

         theDevice.off();

     }

     // Used if you want to allow for undo
// Do the opposite of execute() public void undo() { theDevice.on(); } }

• TurnTVUp.java(COMMAND)

 public class TurnTVUp implements Command {

     ElectronicDevice theDevice;

     public TurnTVUp(ElectronicDevice newDevice){

         theDevice = newDevice;

     }

     public void execute() {

         theDevice.volumeUp();

     }

     public void undo() {

         theDevice.volumenDown();

     }

 }

• DeviceButton.java(INVOKER)

 // This is known as the invoker
// It has a method press() that when executed
// causes the execute method to be called // The execute method for the Command interface then calls
// the method assigned in the class that implements the
// Command interface public class DeviceButton{ Command theCommand; public DeviceButton(Command newCommand){ theCommand = newCommand; } public void press(){ theCommand.execute(); } // Now the remote can undo past commands public void pressUndo(){ theCommand.undo(); } }

• TVRemote.java

 public class TVRemote {

     public static ElectronicDevice getDevice(){

         return new Television();

     }

 }

• PlayWithRemote.java

 import java.util.ArrayList;
import java.util.List; public class PlayWithRemote{ public static void main(String[] args){ // Gets the ElectronicDevice to use ElectronicDevice newDevice = TVRemote.getDevice(); // TurnTVOn contains the command to turn on the tv
// When execute() is called on this command object
// it will execute the method on() in Television TurnTVOn onCommand = new TurnTVOn(newDevice); // Calling the execute() causes on() to execute in Television DeviceButton onPressed = new DeviceButton(onCommand); // When press() is called theCommand.execute(); executes onPressed.press(); //---------------------------------------------------------- // Now when execute() is called off() of Television executes TurnTVOff offCommand = new TurnTVOff(newDevice); // Calling the execute() causes off() to execute in Television onPressed = new DeviceButton(offCommand); // When press() is called theCommand.execute(); executes onPressed.press(); //---------------------------------------------------------- // Now when execute() is called volumeUp() of Television executes TurnTVUp volUpCommand = new TurnTVUp(newDevice); // Calling the execute() causes volumeUp() to execute in Television onPressed = new DeviceButton(volUpCommand); // When press() is called theCommand.execute(); executes onPressed.press();
onPressed.press();
onPressed.press(); //---------------------------------------------------------- // Creating a TV and Radio to turn off with 1 press Television theTV = new Television(); Radio theRadio = new Radio(); // Add the Electronic Devices to a List List<ElectronicDevice> allDevices = new ArrayList<ElectronicDevice>(); allDevices.add(theTV);
allDevices.add(theRadio); // Send the List of Electronic Devices to TurnItAllOff
// where a call to run execute() on this function will
// call off() for each device in the list TurnItAllOff turnOffDevices = new TurnItAllOff(allDevices); // This calls for execute() to run which calls for off() to
// run for every ElectronicDevice DeviceButton turnThemOff = new DeviceButton(turnOffDevices); turnThemOff.press(); //---------------------------------------------------------- /*
* It is common to be able to undo a command in a command pattern
* To do so, DeviceButton will have a method called undo
* Undo() will perform the opposite action that the normal
* Command performs. undo() needs to be added to every class
* with an execute()
*/ turnThemOff.pressUndo(); // To undo more than one command add them to a LinkedList
// using addFirst(). Then execute undo on each item until
// there are none left. (This is your Homework) } }

• Radio.java(RECEIVER)

 public class Radio implements ElectronicDevice {

     private int volume = 0;

     public void on() {

         System.out.println("Radio is on");

     }

     public void off() {

         System.out.println("Radio is off");

     }

     public void volumeUp() {

         volume++;

         System.out.println("Radio Volume is at: " + volume);

     }

     public void volumenDown() {

         volume--;

         System.out.println("Radio Volume is at: " + volume);

     }

 }

• TurnItAllOff.java(COMMAND)

 import java.util.List;

 public class TurnItAllOff implements Command {
List<ElectronicDevice> theDevices; public TurnItAllOff(List<ElectronicDevice> newDevices) {
theDevices = newDevices;
} public void execute() { for (ElectronicDevice device : theDevices) {
device.off();
} } public void undo() { for (ElectronicDevice device : theDevices) {
device.on();
} }
}

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

 public class ItalianHoagie extends Hoagie{

     String[] meatUsed = { "Salami", "Pepperoni", "Capicola Ham" };
String[] cheeseUsed = { "Provolone" };
String[] veggiesUsed = { "Lettuce", "Tomatoes", "Onions", "Sweet Peppers" };
String[] condimentsUsed = { "Oil", "Vinegar" }; public void addMeat(){ System.out.print("Adding the Meat: "); for (String meat : meatUsed){ System.out.print(meat + " "); } } public void addCheese(){ System.out.print("Adding the Cheese: "); for (String cheese : cheeseUsed){ System.out.print(cheese + " "); } } public void addVegetables(){ System.out.print("Adding the Vegetables: "); for (String vegetable : veggiesUsed){ System.out.print(vegetable + " "); } } public void addCondiments(){ System.out.print("Adding the Condiments: "); for (String condiment : condimentsUsed){ System.out.print(condiment + " "); } } } /*
public void makeSandwich(){ cutBun();
addMeat();
addCheese();
addVegetables();
addCondiments();
wrapTheHoagie(); } public void cutBun(){ System.out.println("The Hoagie is Cut"); } public void addMeat(){ System.out.println("Add Salami, Pepperoni and Capicola ham"); } public void addCheese(){ System.out.println("Add Provolone"); } public void addVegetables(){ System.out.println("Add Lettuce, Tomatoes, Onions and Sweet Peppers"); } public void addCondiments(){ System.out.println("Add Oil and Vinegar"); } public void wrapTheHoagie(){ System.out.println("Wrap the Hoagie"); } }
*/

• Hoagie.java

 // A Template Method Pattern contains a method that provides
// the steps of the algorithm. It allows subclasses to override
// some of the methods public abstract class Hoagie { boolean afterFirstCondiment = false; // This is the Template Method
// Declare this method final to keep subclasses from
// changing the algorithm final void makeSandwich(){ cutBun(); if(customerWantsMeat()){ addMeat(); // Here to handle new lines for spacing
afterFirstCondiment = true; } if(customerWantsCheese()){ if(afterFirstCondiment) { System.out.print("\n"); } addCheese(); afterFirstCondiment = true; } if(customerWantsVegetables()){ if(afterFirstCondiment) { System.out.print("\n"); } addVegetables(); afterFirstCondiment = true; } if(customerWantsCondiments()){ if(afterFirstCondiment) { System.out.print("\n"); } addCondiments(); afterFirstCondiment = true; } wrapTheHoagie(); } // These methods must be overridden by the extending subclasses abstract void addMeat();
abstract void addCheese();
abstract void addVegetables();
abstract void addCondiments(); public void cutBun(){ System.out.println("The Hoagie is Cut"); } // These are called hooks
// If the user wants to override these they can // Use abstract methods when you want to force the user
// to override and use a hook when you want it to be optional boolean customerWantsMeat() { return true; }
boolean customerWantsCheese() { return true; }
boolean customerWantsVegetables() { return true; }
boolean customerWantsCondiments() { return true; } public void wrapTheHoagie(){ System.out.println("\nWrap the Hoagie"); } public void afterFirstCondiment(){ System.out.println("\n"); } }

• VeggieHoagie.java

 public class VeggieHoagie extends Hoagie{

     String[] veggiesUsed = { "Lettuce", "Tomatoes", "Onions", "Sweet Peppers" };
String[] condimentsUsed = { "Oil", "Vinegar" }; boolean customerWantsMeat() { return false; }
boolean customerWantsCheese() { return false; } public void addVegetables(){ System.out.print("Adding the Vegetables: "); for (String vegetable : veggiesUsed){ System.out.print(vegetable + " "); } } public void addCondiments(){ System.out.print("Adding the Condiments: "); for (String condiment : condimentsUsed){ System.out.print(condiment + " "); } } void addMeat() {} void addCheese() {} }

• SandwichSculptor.java

 public class SandwichSculptor {

     public static void main(String[] args){

         ItalianHoagie cust12Hoagie = new ItalianHoagie();

         cust12Hoagie.makeSandwich();

         System.out.println();

         VeggieHoagie cust13Hoagie = new VeggieHoagie();

         cust13Hoagie.makeSandwich();

     }

 }

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

 // Will hold all of the info needed for each song

 // I told all users to:
// 1. create a function named addSong() for adding song, band and release
// 2. create a function named getBestSongs() that will return the collection
// of songs public class SongInfo{ String songName;
String bandName;
int yearReleased; public SongInfo(String newSongName, String newBandName, int newYearReleased){ songName = newSongName;
bandName = newBandName;
yearReleased = newYearReleased; } public String getSongName(){ return songName; }
public String getBandName(){ return bandName; }
public int getYearReleased(){ return yearReleased; } }

• SongsOfThe70s.java

 import java.util.ArrayList;
import java.util.Iterator; public class SongsOfThe70s implements SongIterator{ // ArrayList holds SongInfo objects ArrayList<SongInfo> bestSongs; public SongsOfThe70s() { bestSongs = new ArrayList<SongInfo>(); addSong("Imagine", "John Lennon", 1971);
addSong("American Pie", "Don McLean", 1971);
addSong("I Will Survive", "Gloria Gaynor", 1979); } // Add a SongInfo object to the end of the ArrayList public void addSong(String songName, String bandName, int yearReleased){ SongInfo songInfo = new SongInfo(songName, bandName, yearReleased); bestSongs.add(songInfo); } // Get rid of this
// Return the ArrayList filled with SongInfo Objects public ArrayList<SongInfo> getBestSongs(){ return bestSongs; } // NEW By adding this method I'll be able to treat all
// collections the same public Iterator createIterator() {
// TODO Auto-generated method stub
return bestSongs.iterator();
} }

• SongsOfThe80s.java

 import java.util.Arrays;
import java.util.Iterator; public class SongsOfThe80s implements SongIterator{ // Create an array of SongInfo Objects SongInfo[] bestSongs; // Used to increment to the next position in the array int arrayValue = 0; public SongsOfThe80s() { bestSongs = new SongInfo[3]; addSong("Roam", "B 52s", 1989);
addSong("Cruel Summer", "Bananarama", 1984);
addSong("Head Over Heels", "Tears For Fears", 1985); } // Add a SongInfo Object to the array and increment to the next position public void addSong(String songName, String bandName, int yearReleased){ SongInfo song = new SongInfo(songName, bandName, yearReleased); bestSongs[arrayValue] = song; arrayValue++; } // This is replaced by the Iterator public SongInfo[] getBestSongs(){ return bestSongs; } // NEW By adding this method I'll be able to treat all
// collections the same @Override
public Iterator createIterator() {
// TODO Auto-generated method stub
return Arrays.asList(bestSongs).iterator();
} }

• SongsOfThe90s.java

 import java.util.Hashtable;
import java.util.Iterator; public class SongsOfThe90s implements SongIterator{ // Create a Hashtable with an int as a key and SongInfo
// Objects Hashtable<Integer, SongInfo> bestSongs = new Hashtable<Integer, SongInfo>(); // Will increment the Hashtable key int hashKey = 0; public SongsOfThe90s() { addSong("Losing My Religion", "REM", 1991);
addSong("Creep", "Radiohead", 1993);
addSong("Walk on the Ocean", "Toad The Wet Sprocket", 1991); } // Add a new SongInfo Object to the Hashtable and then increment
// the Hashtable key public void addSong(String songName, String bandName, int yearReleased){ SongInfo songInfo = new SongInfo(songName, bandName, yearReleased); bestSongs.put(hashKey, songInfo); hashKey++; } // This is replaced by the Iterator
// Return a Hashtable full of SongInfo Objects public Hashtable<Integer, SongInfo> getBestSongs(){ return bestSongs; } // NEW By adding this method I'll be able to treat all
// collections the same public Iterator createIterator() {
// TODO Auto-generated method stub
return bestSongs.values().iterator();
} }

• DiscJockey.java

 import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator; public class DiscJockey { SongsOfThe70s songs70s;
SongsOfThe80s songs80s;
SongsOfThe90s songs90s; // NEW Passing in song iterators SongIterator iter70sSongs;
SongIterator iter80sSongs;
SongIterator iter90sSongs; /* OLD WAY
public DiscJockey(SongsOfThe70s newSongs70s, SongsOfThe80s newSongs80s, SongsOfThe90s newSongs90s) { songs70s = newSongs70s;
songs80s = newSongs80s;
songs90s = newSongs90s; }
*/ // NEW WAY Initialize the iterators public DiscJockey(SongIterator newSongs70s, SongIterator newSongs80s, SongIterator newSongs90s) { iter70sSongs = newSongs70s;
iter80sSongs = newSongs80s;
iter90sSongs = newSongs90s; } public void showTheSongs(){ // Because the SongInfo Objects are stored in different
// collections everything must be handled on an individual
// basis. This is BAD! ArrayList aL70sSongs = songs70s.getBestSongs(); System.out.println("Songs of the 70s\n"); for(int i=0; i < aL70sSongs.size(); i++){ SongInfo bestSongs = (SongInfo) aL70sSongs.get(i); System.out.println(bestSongs.getSongName());
System.out.println(bestSongs.getBandName());
System.out.println(bestSongs.getYearReleased() + "\n"); } SongInfo[] array80sSongs = songs80s.getBestSongs(); System.out.println("Songs of the 80s\n"); for(int j=0; j < array80sSongs.length; j++){ SongInfo bestSongs = array80sSongs[j]; System.out.println(bestSongs.getSongName());
System.out.println(bestSongs.getBandName());
System.out.println(bestSongs.getYearReleased() + "\n"); } Hashtable<Integer, SongInfo> ht90sSongs = songs90s.getBestSongs(); System.out.println("Songs of the 90s\n"); for (Enumeration<Integer> e = ht90sSongs.keys(); e.hasMoreElements();)
{
SongInfo bestSongs = ht90sSongs.get(e.nextElement()); System.out.println(bestSongs.getSongName());
System.out.println(bestSongs.getBandName());
System.out.println(bestSongs.getYearReleased() + "\n"); } } // Now that I can treat everything as an Iterator it cleans up
// the code while allowing me to treat all collections as 1 public void showTheSongs2(){ System.out.println("NEW WAY WITH ITERATOR\n"); Iterator Songs70s = iter70sSongs.createIterator();
Iterator Songs80s = iter80sSongs.createIterator();
Iterator Songs90s = iter90sSongs.createIterator(); System.out.println("Songs of the 70s\n");
printTheSongs(Songs70s); System.out.println("Songs of the 80s\n");
printTheSongs(Songs80s); System.out.println("Songs of the 90s\n");
printTheSongs(Songs90s); } public void printTheSongs(Iterator iterator){ while(iterator.hasNext()){ SongInfo songInfo = (SongInfo) iterator.next(); System.out.println(songInfo.getSongName());
System.out.println(songInfo.getBandName());
System.out.println(songInfo.getYearReleased() + "\n"); } } }

• RadioStation.java

 public class RadioStation {

     public static void main(String[] args){

         SongsOfThe70s songs70s = new SongsOfThe70s();
SongsOfThe80s songs80s = new SongsOfThe80s();
SongsOfThe90s songs90s = new SongsOfThe90s(); DiscJockey madMike = new DiscJockey(songs70s, songs80s, songs90s); // madMike.showTheSongs(); madMike.showTheSongs2(); } }

• SongIterator.java

 import java.util.Iterator;

 public interface SongIterator {

     public Iterator createIterator();

 }

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

 public interface ATMState {

     // Different states expected
// HasCard, NoCard, HasPin, NoCash void insertCard(); void ejectCard(); void insertPin(int pinEntered); void requestCash(int cashToWithdraw); }

• ATMMachine.java

 public class ATMMachine {

     ATMState hasCard;
ATMState noCard;
ATMState hasCorrectPin;
ATMState atmOutOfMoney; ATMState atmState; int cashInMachine = 2000;
boolean correctPinEntered = false; public ATMMachine(){ hasCard = new HasCard(this);
noCard = new NoCard(this);
hasCorrectPin = new HasPin(this);
atmOutOfMoney = new NoCash(this); atmState = noCard; if(cashInMachine < 0){ atmState = atmOutOfMoney; } } void setATMState(ATMState newATMState){ atmState = newATMState; } public void setCashInMachine(int newCashInMachine){ cashInMachine = newCashInMachine; } public void insertCard() { atmState.insertCard(); } public void ejectCard() { atmState.ejectCard(); } public void requestCash(int cashToWithdraw) { atmState.requestCash(cashToWithdraw); } public void insertPin(int pinEntered){ atmState.insertPin(pinEntered); } public ATMState getYesCardState() { return hasCard; }
public ATMState getNoCardState() { return noCard; }
public ATMState getHasPin() { return hasCorrectPin; }
public ATMState getNoCashState() { return atmOutOfMoney; } }

• HasCard.java

 public class HasCard implements ATMState {

     ATMMachine atmMachine;

     public HasCard(ATMMachine newATMMachine){

         atmMachine = newATMMachine;

     }

     public void insertCard() {

         System.out.println("You can only insert one card at a time");

     }

     public void ejectCard() {

         System.out.println("Your card is ejected");
atmMachine.setATMState(atmMachine.getNoCardState()); } public void requestCash(int cashToWithdraw) { System.out.println("You have not entered your PIN"); } public void insertPin(int pinEntered) { if(pinEntered == 1234){ System.out.println("You entered the correct PIN");
atmMachine.correctPinEntered = true;
atmMachine.setATMState(atmMachine.getHasPin()); } else { System.out.println("You entered the wrong PIN");
atmMachine.correctPinEntered = false;
System.out.println("Your card is ejected");
atmMachine.setATMState(atmMachine.getNoCardState()); }
}
}

• NoCard.java

 public class NoCard implements ATMState {

     ATMMachine atmMachine;

     public NoCard(ATMMachine newATMMachine){

         atmMachine = newATMMachine;

     }

     public void insertCard() {

         System.out.println("Please enter your pin");
atmMachine.setATMState(atmMachine.getYesCardState()); } public void ejectCard() { System.out.println("You didn't enter a card"); } public void requestCash(int cashToWithdraw) { System.out.println("You have not entered your card"); } public void insertPin(int pinEntered) { System.out.println("You have not entered your card"); }
}

• HasPin.java

 public class HasPin implements ATMState {

     ATMMachine atmMachine;

     public HasPin(ATMMachine newATMMachine){

         atmMachine = newATMMachine;

     }

     public void insertCard() {

         System.out.println("You already entered a card");

     }

     public void ejectCard() {

         System.out.println("Your card is ejected");
atmMachine.setATMState(atmMachine.getNoCardState()); } public void requestCash(int cashToWithdraw) { if(cashToWithdraw > atmMachine.cashInMachine){ System.out.println("You don't have that much cash available");
System.out.println("Your card is ejected");
atmMachine.setATMState(atmMachine.getNoCardState()); } else { System.out.println(cashToWithdraw + " is provided by the machine");
atmMachine.setCashInMachine(atmMachine.cashInMachine - cashToWithdraw); System.out.println("Your card is ejected");
atmMachine.setATMState(atmMachine.getNoCardState()); if(atmMachine.cashInMachine <= 0){ atmMachine.setATMState(atmMachine.getNoCashState()); }
}
} public void insertPin(int pinEntered) { System.out.println("You already entered a PIN"); }
}

• NoCash.java

 public class NoCash implements ATMState {

     ATMMachine atmMachine;

     public NoCash(ATMMachine newATMMachine){

         atmMachine = newATMMachine;

     }

     public void insertCard() {

         System.out.println("We don't have any money");
System.out.println("Your card is ejected"); } public void ejectCard() { System.out.println("We don't have any money");
System.out.println("There is no card to eject"); } public void requestCash(int cashToWithdraw) { System.out.println("We don't have any money"); } public void insertPin(int pinEntered) { System.out.println("We don't have any money"); }
}

• TestATMMachine.java

 public class TestATMMachine {

     public static void main(String[] args){

         ATMMachine atmMachine = new ATMMachine();

         atmMachine.insertCard();

         atmMachine.ejectCard();

         atmMachine.insertCard();

         atmMachine.insertPin(1234);

         atmMachine.requestCash(2000);

         atmMachine.insertCard();

         atmMachine.insertPin(1234);

     }
}

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

 // The chain of responsibility pattern has a
// group of objects that are expected to between
// them be able to solve a problem.
// If the first Object can't solve it, it passes
// the data to the next Object in the chain public interface Chain { // Defines the next Object to receive the data
// if this Object can't process it public void setNextChain(Chain nextChain); // Either solves the problem or passes the data
// to the next Object in the chain public void calculate(Numbers request); }

• Numbers.java

 // This object will contain 2 numbers and a
// calculation to perform in the form of a String public class Numbers { private int number1;
private int number2; private String calculationWanted; public Numbers(int newNumber1, int newNumber2, String calcWanted){ number1 = newNumber1;
number2 = newNumber2;
calculationWanted = calcWanted; } public int getNumber1(){ return number1; }
public int getNumber2(){ return number2; }
public String getCalcWanted(){ return calculationWanted; } }

• AddNumbers.java

 public class AddNumbers implements Chain{

     private  Chain nextInChain;

     // Defines the next Object to receive the
// data if this one can't use it public void setNextChain(Chain nextChain) { nextInChain = nextChain; } // Tries to calculate the data, or passes it
// to the Object defined in method setNextChain() public void calculate(Numbers request) { if(request.getCalcWanted() == "add"){ System.out.print(request.getNumber1() + " + " + request.getNumber2() + " = "+
(request.getNumber1()+request.getNumber2())); } else { nextInChain.calculate(request); } }
}

• SubtractNumbers.java

 public class SubtractNumbers implements Chain{

     private  Chain nextInChain;

     @Override
public void setNextChain(Chain nextChain) { nextInChain = nextChain; } @Override
public void calculate(Numbers request) { if(request.getCalcWanted() == "sub"){ System.out.print(request.getNumber1() + " - " + request.getNumber2() + " = "+
(request.getNumber1()-request.getNumber2())); } else { nextInChain.calculate(request); } } }

• MultNumbers.java

 public class MultNumbers implements Chain{

     private  Chain nextInChain;

     @Override
public void setNextChain(Chain nextChain) { nextInChain = nextChain; } @Override
public void calculate(Numbers request) { if(request.getCalcWanted() == "mult"){ System.out.print(request.getNumber1() + " * " + request.getNumber2() + " = "+
(request.getNumber1()*request.getNumber2())); } else { nextInChain.calculate(request); } } }

• DivideNumbers.java

 public class DivideNumbers implements Chain{

     private  Chain nextInChain;

     @Override
public void setNextChain(Chain nextChain) { nextInChain = nextChain; } @Override
public void calculate(Numbers request) { if(request.getCalcWanted() == "div"){ System.out.print(request.getNumber1() + " / " + request.getNumber2() + " = "+
(request.getNumber1()/request.getNumber2())); } else { System.out.print("Only works for add, sub, mult, and div"); }
}
}

• TestCalcChain.java

 public class TestCalcChain {

     public static void main(String[] args){

         // Here I define all of the objects in the chain

         Chain chainCalc1 = new AddNumbers();
Chain chainCalc2 = new SubtractNumbers();
Chain chainCalc3 = new MultNumbers();
Chain chainCalc4 = new DivideNumbers(); // Here I tell each object where to forward the
// data if it can't process the request chainCalc1.setNextChain(chainCalc2);
chainCalc2.setNextChain(chainCalc3);
chainCalc3.setNextChain(chainCalc4); // Define the data in the Numbers Object
// and send it to the first Object in the chain Numbers request = new Numbers(4,2,"add"); chainCalc1.calculate(request); } }

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

 public class ConversionContext {

     private String conversionQues = "";
private String conversionResponse = "";
private String fromConversion = "";
private String toConversion = "";
private double quantity; String[] partsOfQues; public ConversionContext(String input)
{
this.conversionQues = input; partsOfQues = getInput().split(" "); fromConversion = getCapitalized(partsOfQues[1]); toConversion = getLowercase(partsOfQues[3]); quantity = Double.valueOf(partsOfQues[0]); conversionResponse = partsOfQues[0] + " "+ partsOfQues[1] + " equals ";
} public String getInput() { return conversionQues; } public String getFromConversion() { return fromConversion; } public String getToConversion() { return toConversion; } public String getResponse() { return conversionResponse; } public double getQuantity() { return quantity; } // Make String lowercase public String getLowercase(String wordToLowercase){ return wordToLowercase.toLowerCase(); } // Capitalizes the first letter of a word public String getCapitalized(String wordToCapitalize){ // Make characters lower case wordToCapitalize = wordToCapitalize.toLowerCase(); // Make the first character uppercase wordToCapitalize = Character.toUpperCase(wordToCapitalize.charAt(0)) + wordToCapitalize.substring(1); // Put s on the end if not there int lengthOfWord = wordToCapitalize.length(); if((wordToCapitalize.charAt(lengthOfWord -1)) != 's'){ wordToCapitalize = new StringBuffer(wordToCapitalize).insert(lengthOfWord, "s").toString(); } return wordToCapitalize; } }

• Expression.java

 public abstract class Expression {

     public abstract String gallons(double quantity);
public abstract String quarts(double quantity);
public abstract String pints(double quantity);
public abstract String cups(double quantity);
public abstract String tablespoons(double quantity); }

• Gallons.java

 public class Gallons extends Expression{

     public String gallons(double quantity) {

         return Double.toString(quantity);
} public String quarts(double quantity) {
return Double.toString(quantity*4);
} public String pints(double quantity) {
return Double.toString(quantity*8);
} public String cups(double quantity) {
return Double.toString(quantity*16);
} public String tablespoons(double quantity) {
return Double.toString(quantity*256);
} }

• Quarts.java

 public class Quarts extends Expression{

     public String gallons(double quantity) {

         return Double.toString(quantity/4);
} public String quarts(double quantity) {
return Double.toString(quantity);
} public String pints(double quantity) {
return Double.toString(quantity*2);
} public String cups(double quantity) {
return Double.toString(quantity*4);
} public String tablespoons(double quantity) {
return Double.toString(quantity*64);
} }

• Pints.java

 public class Pints extends Expression{

     public String gallons(double quantity) {

         return Double.toString(quantity/8);
} public String quarts(double quantity) {
return Double.toString(quantity/2);
} public String pints(double quantity) {
return Double.toString(quantity);
} public String cups(double quantity) {
return Double.toString(quantity*2);
} public String tablespoons(double quantity) {
return Double.toString(quantity*32);
} }

• Cups.java

 public class Cups extends Expression{

     public String gallons(double quantity) {

         return Double.toString(quantity/16);
} public String quarts(double quantity) {
return Double.toString(quantity/4);
} public String pints(double quantity) {
return Double.toString(quantity/2);
} public String cups(double quantity) {
return Double.toString(quantity);
} public String tablespoons(double quantity) {
return Double.toString(quantity*16);
} }

• Tablespoons.java

 public class Tablespoons extends Expression{

     public String gallons(double quantity) {

         return Double.toString(quantity/256);
} public String quarts(double quantity) {
return Double.toString(quantity/64);
} public String pints(double quantity) {
return Double.toString(quantity/32);
} public String cups(double quantity) {
return Double.toString(quantity/16);
} public String tablespoons(double quantity) {
return Double.toString(quantity);
} }

• MeasurementConversion.java

 import java.lang.reflect.*;

 import javax.swing.*;

 public class MeasurementConversion {

     public static void main(String[] args){

         // Create pop up window that asks for a question

         JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String questionAsked = JOptionPane.showInputDialog(frame, "What is your question"); // Add the question to the context for analysis ConversionContext question = new ConversionContext(questionAsked); String fromConversion = question.getFromConversion(); String toConversion = question.getToConversion(); double quantity = question.getQuantity(); try { // Get class based on the from conversion string Class tempClass = Class.forName(fromConversion); // Get the constructor dynamically for the conversion string Constructor con = tempClass.getConstructor(); // Create a new instance of the object you want to convert from Object convertFrom = (Expression) con.newInstance(); // Define the method parameters expected by the method that
// will convert to your chosen unit of measure Class[] methodParams = new Class[]{Double.TYPE}; // Get the method dynamically that will be needed to convert
// into your chosen unit of measure Method conversionMethod = tempClass.getMethod(toConversion, methodParams); // Define the method parameters that will be passed to the above method Object[] params = new Object[]{new Double(quantity)}; // Get the quantity after the conversion String toQuantity = (String) conversionMethod.invoke(convertFrom, params); // Print the results String answerToQues = question.getResponse() +
toQuantity + " " + toConversion; JOptionPane.showMessageDialog(null,answerToQues); // Closes the frame after OK is clicked frame.dispose(); } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }

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

 public class StockOffer{

     private int stockShares = 0;
private String stockSymbol = "";
private int colleagueCode = 0; public StockOffer(int numOfShares, String stock, int collCode){ stockShares = numOfShares;
stockSymbol = stock;
colleagueCode = collCode; } public int getstockShares() { return stockShares; }
public String getStockSymbol() { return stockSymbol; }
public int getCollCode() { return colleagueCode; } }

• Colleague.java

 public abstract class Colleague{

     private Mediator mediator;
private int colleagueCode; public Colleague(Mediator newMediator){
mediator = newMediator; mediator.addColleague(this); } public void saleOffer(String stock, int shares){ mediator.saleOffer(stock, shares, this.colleagueCode); } public void buyOffer(String stock, int shares){ mediator.buyOffer(stock, shares, this.colleagueCode); } public void setCollCode(int collCode){ colleagueCode = collCode; } }

• GormanSlacks.java

 public class GormanSlacks extends Colleague{

     public GormanSlacks(Mediator newMediator) {
super(newMediator); System.out.println("Gorman Slacks signed up with the stockexchange\n"); } }

• JTPoorman.java

 public class JTPoorman extends Colleague{

     public JTPoorman(Mediator newMediator) {
super(newMediator); System.out.println("JT Poorman signed up with the stockexchange\n"); } }

• Mediator.java

 public interface Mediator {

     public void saleOffer(String stock, int shares, int collCode);

     public void buyOffer(String stock, int shares, int collCode);

     public void addColleague(Colleague colleague);

 }

• StockMediator.java

 import java.util.ArrayList;

 public class StockMediator implements Mediator{

     private ArrayList<Colleague> colleagues;
private ArrayList<StockOffer> stockBuyOffers;
private ArrayList<StockOffer> stockSaleOffers; private int colleagueCodes = 0; public StockMediator(){ colleagues = new ArrayList<Colleague>();
stockBuyOffers = new ArrayList<StockOffer>();
stockSaleOffers = new ArrayList<StockOffer>();
} public void addColleague(Colleague newColleague){ colleagues.add(newColleague); colleagueCodes++; newColleague.setCollCode(colleagueCodes); } public void saleOffer(String stock, int shares, int collCode) { boolean stockSold = false; for(StockOffer offer: stockBuyOffers){ if((offer.getStockSymbol() == stock) && (offer.getstockShares() == shares)){ System.out.println(shares + " shares of " + stock +
" sold to colleague code " + offer.getCollCode()); stockBuyOffers.remove(offer); stockSold = true; } if(stockSold){ break; } } if(!stockSold) { System.out.println(shares + " shares of " + stock +
" added to inventory"); StockOffer newOffering = new StockOffer(shares, stock, collCode); stockSaleOffers.add(newOffering); } } public void buyOffer(String stock, int shares, int collCode) { boolean stockBought = false; for(StockOffer offer: stockSaleOffers){ if((offer.getStockSymbol() == stock) && (offer.getstockShares() == shares)){ System.out.println(shares + " shares of " + stock +
" bought by colleague code " + offer.getCollCode()); stockSaleOffers.remove(offer); stockBought = true; } if(stockBought){ break; } } if(!stockBought) { System.out.println(shares + " shares of " + stock +
" added to inventory"); StockOffer newOffering = new StockOffer(shares, stock, collCode); stockBuyOffers.add(newOffering); } } public void getstockOfferings(){ System.out.println("\nStocks for Sale"); for(StockOffer offer: stockSaleOffers){ System.out.println(offer.getstockShares() + " of " + offer.getStockSymbol()); } System.out.println("\nStock Buy Offers"); for(StockOffer offer: stockBuyOffers){ System.out.println(offer.getstockShares() + " of " + offer.getStockSymbol()); } } }

• TestStockMediator.java

 public class TestStockMediator{

     public static void main(String[] args){

         StockMediator nyse = new StockMediator();

         GormanSlacks broker = new GormanSlacks(nyse);

         JTPoorman broker2 = new JTPoorman(nyse);

         broker.saleOffer("MSFT", 100);
broker.saleOffer("GOOG", 50); broker2.buyOffer("MSFT", 100);
broker2.saleOffer("NRG", 10); broker.buyOffer("NRG", 10); nyse.getstockOfferings(); } }

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

 // Memento Design Pattern
// Used stores an objects state at a point in time
// so it can be returned to that state later. It
// simply allows you to undo/redo changes on an Object public class Memento { // The article stored in memento Object private String article; // Save a new article String to the memento Object public Memento(String articleSave) { article = articleSave; } // Return the value stored in article public String getSavedArticle() { return article; } }

• Originator.java

 // Memento Design Pattern

 public class Originator{

     private String article;

     // Sets the value for the article

     public void set(String newArticle) {
System.out.println("From Originator: Current Version of Article\n"+newArticle+ "\n");
this.article = newArticle;
} // Creates a new Memento with a new article public Memento storeInMemento() {
System.out.println("From Originator: Saving to Memento");
return new Memento(article);
} // Gets the article currently stored in memento public String restoreFromMemento(Memento memento) { article = memento.getSavedArticle(); System.out.println("From Originator: Previous Article Saved in Memento\n"+article + "\n"); return article; } }

• Caretaker.java

 // Memento Design Pattern Tutorial

 import java.util.ArrayList;

 class Caretaker {

     // Where all mementos are saved

     ArrayList<Memento> savedArticles = new ArrayList<Memento>();

     // Adds memento to the ArrayList

     public void addMemento(Memento m) { savedArticles.add(m); }

     // Gets the memento requested from the ArrayList

     public Memento getMemento(int index) { return savedArticles.get(index); }
}

• TestMemento.java

 // Memento Design Pattern Tutorial

 import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import javax.swing.*; public class TestMemento extends JFrame{
public static void main(String[] args) { new TestMemento(); } private JButton saveBut, undoBut, redoBut; // JTextArea(rows, columns) private JTextArea theArticle = new JTextArea(40,60); // --------------------------------------------- // Create a caretaker that contains the ArrayList
// with all the articles in it. It can add and
// retrieve articles from the ArrayList Caretaker caretaker = new Caretaker(); // The originator sets the value for the article,
// creates a new memento with a new article, and
// gets the article stored in the current memento Originator originator = new Originator(); int saveFiles = 0, currentArticle = 0; // --------------------------------------------- public TestMemento(){ // Set basic information for the panel that will
// hold all the GUI elements this.setSize(750,780);
this.setTitle("Memento Design Pattern");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel1 = new JPanel(); // Add label to the panel panel1.add(new JLabel("Article")); // Add JTextArea to the panel panel1.add(theArticle); // Add the buttons & ButtonListeners to the panel ButtonListener saveListener = new ButtonListener();
ButtonListener undoListener = new ButtonListener();
ButtonListener redoListener = new ButtonListener(); saveBut = new JButton("Save");
saveBut.addActionListener(saveListener); undoBut = new JButton("Undo");
undoBut.addActionListener(undoListener); redoBut = new JButton("Redo");
redoBut.addActionListener(redoListener); panel1.add(saveBut);
panel1.add(undoBut);
panel1.add(redoBut); // Add panel to the frame that shows on screen this.add(panel1); this.setVisible(true); } class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { if(e.getSource() == saveBut){ // Get text in JTextArea String textInTextArea = theArticle.getText(); // Set the value for the current memento originator.set(textInTextArea); // Add new article to the ArrayList caretaker.addMemento( originator.storeInMemento() ); // saveFiles monitors how many articles are saved
// currentArticle monitors the current article displayed saveFiles++;
currentArticle++; System.out.println("Save Files " + saveFiles); // Make undo clickable undoBut.setEnabled(true); } else if(e.getSource() == undoBut){ if(currentArticle >= 1){ // Decrement to the current article displayed currentArticle--; // Get the older article saved and display it in JTextArea String textBoxString = originator.restoreFromMemento( caretaker.getMemento(currentArticle) ); theArticle.setText(textBoxString); // Make Redo clickable redoBut.setEnabled(true); } else { // Don't allow user to click Undo undoBut.setEnabled(false); } } else if(e.getSource() == redoBut){ if((saveFiles - 1) > currentArticle){ // Increment to the current article displayed currentArticle++; // Get the newer article saved and display it in JTextArea String textBoxString = originator.restoreFromMemento( caretaker.getMemento(currentArticle) ); theArticle.setText(textBoxString); // Make undo clickable undoBut.setEnabled(true); } else { // Don't allow user to click Redo redoBut.setEnabled(false); } } } } }

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

 // The visitor pattern is used when you have to perform
// the same action on many objects of different types interface Visitor { // Created to automatically use the right
// code based on the Object sent
// Method Overloading public double visit(Liquor liquorItem); public double visit(Tobacco tobaccoItem); public double visit(Necessity necessityItem); }

• TaxVisitor.java

 import java.text.DecimalFormat;

 // Concrete Visitor Class

 class TaxVisitor implements Visitor {

     // This formats the item prices to 2 decimal places

     DecimalFormat df = new DecimalFormat("#.##");

     // This is created so that each item is sent to the
// right version of visit() which is required by the
// Visitor interface and defined below public TaxVisitor() {
} // Calculates total price based on this being taxed
// as a liquor item public double visit(Liquor liquorItem) {
System.out.println("Liquor Item: Price with Tax");
return Double.parseDouble(df.format((liquorItem.getPrice() * .18) + liquorItem.getPrice()));
} // Calculates total price based on this being taxed
// as a tobacco item public double visit(Tobacco tobaccoItem) {
System.out.println("Tobacco Item: Price with Tax");
return Double.parseDouble(df.format((tobaccoItem.getPrice() * .32) + tobaccoItem.getPrice()));
} // Calculates total price based on this being taxed
// as a necessity item public double visit(Necessity necessityItem) {
System.out.println("Necessity Item: Price with Tax");
return Double.parseDouble(df.format(necessityItem.getPrice()));
} }

• Visitable.java

 interface Visitable {

     // Allows the Visitor to pass the object so
// the right operations occur on the right
// type of object. // accept() is passed the same visitor object
// but then the method visit() is called using
// the visitor object. The right version of visit()
// is called because of method overloading public double accept(Visitor visitor); }

• Liquor.java

 class Liquor implements Visitable {

     private double price;

     Liquor(double item) {
price = item;
} public double accept(Visitor visitor) {
return visitor.visit(this);
} public double getPrice() {
return price;
} }

• Necessity.java

 class Necessity implements Visitable {

     private double price;

     Necessity(double item) {
price = item;
} public double accept(Visitor visitor) {
return visitor.visit(this);
} public double getPrice() {
return price;
} }

• Tobacco.java

 class Tobacco implements Visitable {

     private double price;

     Tobacco(double item) {
price = item;
} public double accept(Visitor visitor) {
return visitor.visit(this);
} public double getPrice() {
return price;
} }

• TaxHolidayVisitor.java

 import java.text.DecimalFormat;

 // Concrete Visitor Class

 class TaxHolidayVisitor implements Visitor {

     // This formats the item prices to 2 decimal places

     DecimalFormat df = new DecimalFormat("#.##");

     // This is created so that each item is sent to the
// right version of visit() which is required by the
// Visitor interface and defined below public TaxHolidayVisitor() {
} // Calculates total price based on this being taxed
// as a liquor item public double visit(Liquor liquorItem) {
System.out.println("Liquor Item: Price with Tax");
return Double.parseDouble(df.format((liquorItem.getPrice() * .10) + liquorItem.getPrice()));
} // Calculates total price based on this being taxed
// as a tobacco item public double visit(Tobacco tobaccoItem) {
System.out.println("Tobacco Item: Price with Tax");
return Double.parseDouble(df.format((tobaccoItem.getPrice() * .30) + tobaccoItem.getPrice()));
} // Calculates total price based on this being taxed
// as a necessity item public double visit(Necessity necessityItem) {
System.out.println("Necessity Item: Price with Tax");
return Double.parseDouble(df.format(necessityItem.getPrice()));
} }

• VisitorTest.java

 public class VisitorTest {
public static void main(String[] args) { TaxVisitor taxCalc = new TaxVisitor();
TaxHolidayVisitor taxHolidayCalc = new TaxHolidayVisitor(); Necessity milk = new Necessity(3.47);
Liquor vodka = new Liquor(11.99);
Tobacco cigars = new Tobacco(19.99); System.out.println(milk.accept(taxCalc) + "\n");
System.out.println(vodka.accept(taxCalc) + "\n");
System.out.println(cigars.accept(taxCalc) + "\n"); System.out.println("TAX HOLIDAY PRICES\n"); System.out.println(milk.accept(taxHolidayCalc) + "\n");
System.out.println(vodka.accept(taxHolidayCalc) + "\n");
System.out.println(cigars.accept(taxHolidayCalc) + "\n"); }
}

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

设计模式教程(Design Patterns Tutorial)笔记之三 行为型模式(Behavioral Patterns)的更多相关文章

  1. Java 23种设计模式详尽分析与实例解析之三--行为型模式

    Java设计模式 行为型模式 职责链模式 模式动机:职责链可以是一条直线.一个环或者一个树形结构.链上的每一个对象都是请求处理者,职责链模式可以将请求的处理组织成一条链,并使请求链传递,由链上的处理者 ...

  2. Java 23种设计模式详尽分析与实例解析之一--创建型模式

    面向对象的设计原则 常用的面向对象设计原则包括7个,这些原则并不是独立存在的,它们相互依赖.互为补充. Java设计模式 创建型模式 简单工厂模式 模式动机: 考虑一个简单的软件应用场景,一个软件系统 ...

  3. (转)Java经典设计模式(3):十一种行为型模式(附实例和详解)

    原文出处: 小宝鸽 Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:J ...

  4. 设计模式教程(Design Patterns Tutorial)笔记之一 创建型模式(Creational Patterns)

    目录 · 概述 · Factory · What is the Factory Design Pattern? · Sample Code · Abstract Factory · What is t ...

  5. C#面向对象设计模式纵横谈——3.Abstract Factory 抽象工厂(创建型模式)

    动机(Motivation) 在软件系统中经常面临着“一系列相互依赖的对象”的创建工作,同时,由于需求变化,往往存在更多系列对象的创建工作.如何应对这种变化?如何绕过常规对象的创建,提供一种“封装机制 ...

  6. 【设计模式】observer(观察者)-- 对象行为型模式5.7

    1.意图 对象之间一对多的依赖关系,当目标对象发生改变时,所有依赖于它的对象都要得到通知并自动更新 2.别名 依赖,发布-订阅 3.动机 1)需要确保相互协作的对象的一致性(数据要保持一致),但一致性 ...

  7. 设计模式(Design Patterns)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  8. 设计模式(Design Patterns)Java版

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  9. Java设计模式(Design Patterns)——可复用面向对象软件的基础

    设计模式(Design Patterns) 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是为了可重用代码.让代码更容易被他 ...

随机推荐

  1. POI2015 解题报告

    由于博主没有BZOJ权限号, 是在洛咕做的题~ 完成了13题(虽然有一半难题都是看题解的QAQ)剩下的题咕咕咕~~ Luogu3585 [POI2015]PIE Solution 模拟, 按顺序搜索, ...

  2. Mad Libs游戏1

    简单的输入输出 输入代码 name1=input('请输入姓名:') name2=input('请输入一个句子:') name3=input('请输入一个地点:') name4=input('请输入一 ...

  3. Hibernate 基础入门

    概述: JDBC:将java和数据库连接的驱动程序加载到项目中,在代码里面,注册驱动,创建链接,创建satement对象,发送并执行sql之类,关闭连接. hibernate :数据持久化一个框架,对 ...

  4. DedeCMS文章页去img图片width和height属性

    方法一:正则匹配去除 打开include/ arc.archives.class.php,查找代码: //设置全局环境变量 $this->Fields['typename'] = $this-& ...

  5. 延迟执行(Invoke 函数)和消息发送(SendMessage 函数)

    Invoke 函数需要继承 MonoBehaviour 类后才能使用. Invoke(string str,float a):a 秒后执行名为 str 函数(只会调用一次). Invoke(strin ...

  6. C++顺序容器之list初探

    C++顺序容器之list初探 双向链表,支持双向顺序访问.在list中任何位置进行插入和删除速度都很快. list不支持随机访问,为了访问一个元素,必须遍历整个容器. #include<iost ...

  7. [UWP] 用 AudioGraph 来增强 UWP 的音频处理能力

    Audio Graph AudioGraph 是 Windows.Media.Audio 命名空间下提供的音频处理接口之一. 可以通过 AudioGraph 的静态方法 CreateAsync 来实例 ...

  8. cad2012卸载/安装失败/如何彻底卸载清除干净cad2012注册表和文件的方法

    cad2012提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装cad2012失败提示cad2012安装未完成,某些产品无法安装,也有时候想重新安装cad2012 ...

  9. i春秋SRC部落携手同程SRC发布首届漏洞提交任务

    [部落守卫者集结令]拿巨额奖金?上白帽子排行榜?近距离膜拜大佬?学技术?掌握窍门?又或者你是个责任感爆棚想要互联网行业安全的有志青年?加入i春秋部落守卫者(The Guarders),统统满足你! [ ...

  10. Nginx---(Server虚拟主机)

    server{ listen PORT; server_name NAME; root /PATH: } 基于端口 listen指令监听在不同的端口; 基于IP 基于FQDN (域名,主机名) ser ...