目录
· What is the Decorator Design Pattern?
· Adapter
· What is the Adapter Design Pattern?
· Facade
· What is the Facade Design Pattern?
· Bridge
· What is the Bridge Design Pattern?
· When to use the Bridge Design Pattern?
· What is the Flyweight Design Pattern?
· Proxy
· What is the Proxy Design Pattern?
Decorator
What is the Decorator Design Pattern?
• The Decorator allows you to modify an object dynamically.
• You would use it when you want the capabilities of inheritance with subclasses, but you need to add functionality at run time.
• It is more flexible than inheritance.
• Simplifies code because you add functionality using many simple classes.
• Rather than rewrite old code you can extend with new code.
Sample Code
• Pizza.java
1 // Blueprint for classes that will have decorators 2 3 public interface Pizza { 4 5 public String getDescription(); 6 7 public double getCost(); 8 9 } 10 11 12 /* 13 public abstract class Pizza{ 14 15 16 public abstract void setDescription(String newDescription); 17 public abstract String getDescription(); 18 19 public abstract void setCost(double newCost); 20 public abstract double getCost(); 21 22 // I could use getter and setter methods for every 23 // potential Pizza topping 24 25 } 26 */
• ThreeCheesePizza.java
1 // By going this route I'll have to create a new subclass 2 // for an infinite number of pizza. 3 // I'd also have to change prices in many classes 4 // when just 1 Pizza topping cost changes 5 6 // Inheritance is static while composition is dynamic 7 // Through composition I'll be able to add new functionality 8 // by writing new code rather than by changing current code 9 10 public class ThreeCheesePizza extends Pizza{ 11 12 private String description = "Mozzarella, Fontina, Parmesan Cheese Pizza"; 13 private double cost = 10.50; 14 15 public void setDescription(String newDescription) { 16 17 description = newDescription; 18 19 } 20 21 public String getDescription() { 22 23 return description; 24 25 } 26 27 public void setCost(double newCost) { 28 29 cost = newCost; 30 31 } 32 33 public double getCost() { 34 35 return cost; 36 37 } 38 }
• PlainPizza.java
1 // Implements the Pizza interface with only the required 2 // methods from the interface 3 4 // Every Pizza made will start as a PlainPizza 5 6 public class PlainPizza implements Pizza { 7 8 public String getDescription() { 9 10 return "Thin dough"; 11 12 } 13 14 public double getCost() { 15 16 System.out.println("Cost of Dough: " + 4.00); 17 18 return 4.00; 19 20 } 21 22 }
• ToppingDecorator.java
1 // Has a "Has a" relationship with Pizza. This is an 2 // Aggregation Relationship 3 4 abstract class ToppingDecorator implements Pizza { 5 6 protected Pizza tempPizza; 7 8 // Assigns the type instance to this attribute 9 // of a Pizza 10 11 // All decorators can dynamically customize the Pizza 12 // instance PlainPizza because of this 13 14 public ToppingDecorator(Pizza newPizza){ 15 16 tempPizza = newPizza; 17 18 } 19 20 public String getDescription() { 21 22 return tempPizza.getDescription(); 23 24 } 25 26 public double getCost() { 27 28 return tempPizza.getCost(); 29 30 } 31 32 }
• Mozzarella.java
1 public class Mozzarella extends ToppingDecorator { 2 3 public Mozzarella(Pizza newPizza) { 4 5 super(newPizza); 6 7 System.out.println("Adding Dough"); 8 9 System.out.println("Adding Moz"); 10 } 11 12 // Returns the result of calling getDescription() for 13 // PlainPizza and adds " mozzarella" to it 14 15 public String getDescription(){ 16 17 return tempPizza.getDescription() + ", mozzarella"; 18 19 } 20 21 public double getCost(){ 22 23 System.out.println("Cost of Moz: " + .50); 24 25 return tempPizza.getCost() + .50; 26 27 } 28 29 }
• TomatoSauce.java
1 public class TomatoSauce extends ToppingDecorator { 2 3 public TomatoSauce(Pizza newPizza) { 4 super(newPizza); 5 6 System.out.println("Adding Sauce"); 7 } 8 9 // Returns the result of calling getDescription() for 10 // PlainPizza, Mozzarella and then TomatoSauce 11 12 public String getDescription(){ 13 14 return tempPizza.getDescription() + ", tomato sauce"; 15 16 } 17 18 public double getCost(){ 19 20 System.out.println("Cost of Sauce: " + .35); 21 22 return tempPizza.getCost() + .35; 23 24 } 25 26 }
• PizzaMaker.java
1 public class PizzaMaker { 2 3 public static void main(String[] args){ 4 5 // The PlainPizza object is sent to the Mozzarella constructor 6 // and then to the TomatoSauce constructor 7 8 Pizza basicPizza = new TomatoSauce(new Mozzarella(new PlainPizza())); 9 10 System.out.println("Ingredients: " + basicPizza.getDescription()); 11 12 System.out.println("Price: " + basicPizza.getCost()); 13 14 } 15 16 }
Adapter
What is the Adapter Design Pattern?
• Allows 2 incompatible interfaces to work together.
• Used when the client expects a (target) interface.
• The Adapter class allows the use of the available interface and the Target interface.
• Any class can work together as long as the Adapter solves the issue that all classes must implement every method defined by the shared interface.
Sample Code
• EnemyAttacker.java
1 // This is the Target Interface : This is what the client 2 // expects to work with. It is the adapters job to make new 3 // classes compatible with this one. 4 5 public interface EnemyAttacker { 6 7 public void fireWeapon(); 8 9 public void driveForward(); 10 11 public void assignDriver(String driverName); 12 13 }
• EnemyTank.java
1 // EnemyTank implements EnemyAttacker perfectly 2 // Our job is to make classes with different methods 3 // from EnemyAttacker to work with the EnemyAttacker interface 4 5 import java.util.Random; 6 7 public class EnemyTank implements EnemyAttacker{ 8 9 Random generator = new Random(); 10 11 public void fireWeapon() { 12 13 int attackDamage = generator.nextInt(10) + 1; 14 15 System.out.println("Enemy Tank Does " + attackDamage + " Damage"); 16 17 } 18 19 public void driveForward() { 20 21 int movement = generator.nextInt(5) + 1; 22 23 System.out.println("Enemy Tank moves " + movement + " spaces"); 24 25 } 26 27 public void assignDriver(String driverName) { 28 29 System.out.println(driverName + " is driving the tank"); 30 31 } 32 33 }
• EnemyRobot.java
1 // This is the Adaptee. The Adapter sends method calls 2 // to objects that use the EnemyAttacker interface 3 // to the right methods defined in EnemyRobot 4 5 import java.util.Random; 6 7 public class EnemyRobot{ 8 9 Random generator = new Random(); 10 11 public void smashWithHands() { 12 13 int attackDamage = generator.nextInt(10) + 1; 14 15 System.out.println("Enemy Robot Causes " + attackDamage + " Damage With Its Hands"); 16 17 } 18 19 public void walkForward() { 20 21 int movement = generator.nextInt(5) + 1; 22 23 System.out.println("Enemy Robot Walks Forward " + movement + " spaces"); 24 25 } 26 27 public void reactToHuman(String driverName) { 28 29 System.out.println("Enemy Robot Tramps on " + driverName); 30 31 } 32 33 34 35 }
• EnemyRobotAdapter.java
1 // The Adapter must provide an alternative action for 2 // the the methods that need to be used because 3 // EnemyAttacker was implemented. 4 5 // This adapter does this by containing an object 6 // of the same type as the Adaptee (EnemyRobot) 7 // All calls to EnemyAttacker methods are sent 8 // instead to methods used by EnemyRobot 9 10 public class EnemyRobotAdapter implements EnemyAttacker{ 11 12 EnemyRobot theRobot; 13 14 public EnemyRobotAdapter(EnemyRobot newRobot){ 15 16 theRobot = newRobot; 17 18 } 19 20 public void fireWeapon() { 21 22 theRobot.smashWithHands(); 23 24 } 25 26 public void driveForward() { 27 28 theRobot.walkForward(); 29 30 } 31 32 public void assignDriver(String driverName) { 33 34 theRobot.reactToHuman(driverName); 35 36 } 37 38 39 40 }
• TestEnemyAttackers.java
1 public class TestEnemyAttackers{ 2 3 public static void main(String[] args){ 4 5 EnemyTank rx7Tank = new EnemyTank(); 6 7 EnemyRobot fredTheRobot = new EnemyRobot(); 8 9 EnemyAttacker robotAdapter = new EnemyRobotAdapter(fredTheRobot); 10 11 System.out.println("The Robot"); 12 13 fredTheRobot.reactToHuman("Paul"); 14 fredTheRobot.walkForward(); 15 fredTheRobot.smashWithHands(); 16 System.out.println(); 17 18 System.out.println("The Enemy Tank"); 19 20 rx7Tank.assignDriver("Frank"); 21 rx7Tank.driveForward(); 22 rx7Tank.fireWeapon(); 23 System.out.println(); 24 25 System.out.println("The Robot with Adapter"); 26 27 robotAdapter.assignDriver("Mark"); 28 robotAdapter.driveForward(); 29 robotAdapter.fireWeapon(); 30 31 } 32 33 }
Facade
What is the Facade Design Pattern?
• When you create a simplified interface that performs many other actions behind the scenes.
• Can I withdrawal $50 from the bank?
• Check if the checking account is valid.
• Check if the security code is valid.
• Check if funds are available.
• Make changes accordingly.
Sample Code
• WelcomeToBank.java
1 public class WelcomeToBank{ 2 3 public WelcomeToBank() { 4 5 System.out.println("Welcome to ABC Bank"); 6 System.out.println("We are happy to give you your money if we can find it\n"); 7 8 9 } 10 11 }
• AccountNumberCheck.java
1 public class AccountNumberCheck{ 2 3 private int accountNumber = 12345678; 4 5 public int getAccountNumber() { return accountNumber; } 6 7 public boolean accountActive(int acctNumToCheck){ 8 9 if(acctNumToCheck == getAccountNumber()) { 10 11 return true; 12 13 } else { 14 15 return false; 16 17 } 18 19 } 20 21 }
• SecurityCodeCheck.java
1 public class SecurityCodeCheck { 2 3 private int securityCode = 1234; 4 5 public int getSecurityCode() { return securityCode; } 6 7 public boolean isCodeCorrect(int secCodeToCheck){ 8 9 if(secCodeToCheck == getSecurityCode()) { 10 11 return true; 12 13 } else { 14 15 return false; 16 17 } 18 19 } 20 21 }
• FundsCheck.java
1 public class FundsCheck { 2 3 private double cashInAccount = 1000.00; 4 5 public double getCashInAccount() { return cashInAccount; } 6 7 public void decreaseCashInAccount(double cashWithdrawn) { cashInAccount -= cashWithdrawn; } 8 9 public void increaseCashInAccount(double cashDeposited) { cashInAccount += cashDeposited; } 10 11 public boolean haveEnoughMoney(double cashToWithdrawal) { 12 13 if(cashToWithdrawal > getCashInAccount()) { 14 15 System.out.println("Error: You don't have enough money"); 16 System.out.println("Current Balance: " + getCashInAccount()); 17 18 return false; 19 20 } else { 21 22 decreaseCashInAccount(cashToWithdrawal); 23 24 System.out.println("Withdrawal Complete: Current Balance is " + getCashInAccount()); 25 26 return true; 27 28 } 29 30 } 31 32 public void makeDeposit(double cashToDeposit) { 33 34 increaseCashInAccount(cashToDeposit); 35 36 System.out.println("Deposit Complete: Current Balance is " + getCashInAccount()); 37 38 } 39 40 }
• BankAccountFacade.java
1 // The Facade Design Pattern decouples or separates the client 2 // from all of the sub components 3 4 // The Facades aim is to simplify interfaces so you don't have 5 // to worry about what is going on under the hood 6 7 public class BankAccountFacade { 8 9 private int accountNumber; 10 private int securityCode; 11 12 AccountNumberCheck acctChecker; 13 SecurityCodeCheck codeChecker; 14 FundsCheck fundChecker; 15 16 WelcomeToBank bankWelcome; 17 18 public BankAccountFacade(int newAcctNum, int newSecCode){ 19 20 accountNumber = newAcctNum; 21 securityCode = newSecCode; 22 23 bankWelcome = new WelcomeToBank(); 24 25 acctChecker = new AccountNumberCheck(); 26 codeChecker = new SecurityCodeCheck(); 27 fundChecker = new FundsCheck(); 28 29 } 30 31 public int getAccountNumber() { return accountNumber; } 32 33 public int getSecurityCode() { return securityCode; } 34 35 36 public void withdrawCash(double cashToGet){ 37 38 if(acctChecker.accountActive(getAccountNumber()) && 39 codeChecker.isCodeCorrect(getSecurityCode()) && 40 fundChecker.haveEnoughMoney(cashToGet)) { 41 42 System.out.println("Transaction Complete\n"); 43 44 } else { 45 46 System.out.println("Transaction Failed\n"); 47 48 } 49 50 } 51 52 53 public void depositCash(double cashToDeposit){ 54 55 if(acctChecker.accountActive(getAccountNumber()) && 56 codeChecker.isCodeCorrect(getSecurityCode())) { 57 58 fundChecker.makeDeposit(cashToDeposit); 59 60 System.out.println("Transaction Complete\n"); 61 62 } else { 63 64 System.out.println("Transaction Failed\n"); 65 66 } 67 68 } 69 70 }
• TestBankAccount.java
1 public class TestBankAccount { 2 3 public static void main(String[] args){ 4 5 BankAccountFacade accessingBank = new BankAccountFacade(12345678, 1234); 6 7 accessingBank.withdrawCash(50.00); 8 9 accessingBank.withdrawCash(990.00); 10 11 } 12 13 }
Bridge
What is the Bridge Design Pattern?
• Decouple an abstraction from its implementation so that the two can vary independently.
• The Bridge Design Pattern is very poorly explained.
• Everyone seems to explain it differently.
• Progressively adding functionality while separating out major differences using abstract classes.
When to use the Bridge Design Pattern?
• When you want to be able to change both the abstractions (abstract classes) and concrete classes independently.
• When you want the first abstract class to define rules (Abstract TV).
• The concrete class adds additional rules (Concrete TV).
• An abstract class has a reference to the device and it defines abstract methods that will be defined (Abstract Remote).
• The Concrete Remote defines the abstract methods required.
Sample Code
• EntertainmentDevice.java
1 // Implementor 2 // With the Bridge Design Pattern you create 2 layers of abstraction 3 // In this example I'll have an abstract class representing 4 // different types of devices. I also have an abstract class 5 // that will represent different types of remote controls 6 7 // This allows me to use an infinite variety of devices and remotes 8 9 abstract class EntertainmentDevice { 10 11 public int deviceState; 12 13 public int maxSetting; 14 15 public int volumeLevel = 0; 16 17 public abstract void buttonFivePressed(); 18 19 public abstract void buttonSixPressed(); 20 21 public void deviceFeedback() { 22 23 if(deviceState > maxSetting || deviceState < 0) { deviceState = 0; } 24 25 System.out.println("On Channel " + deviceState); 26 27 } 28 29 public void buttonSevenPressed() { 30 31 volumeLevel++; 32 33 System.out.println("Volume at: " + volumeLevel); 34 35 } 36 37 public void buttonEightPressed() { 38 39 volumeLevel--; 40 41 System.out.println("Volume at: " + volumeLevel); 42 43 } 44 45 }
• TVDevice.java
1 // Concrete Implementor 2 3 // Here is an implementation of the EntertainmentDevice 4 // abstract class. I'm specifying what makes it different 5 // from other devices 6 7 public class TVDevice extends EntertainmentDevice { 8 9 public TVDevice(int newDeviceState, int newMaxSetting){ 10 11 deviceState = newDeviceState; 12 13 maxSetting = newMaxSetting; 14 15 } 16 17 public void buttonFivePressed() { 18 19 System.out.println("Channel Down"); 20 21 deviceState--; 22 23 } 24 25 public void buttonSixPressed() { 26 27 System.out.println("Channel Up"); 28 29 deviceState++; 30 31 } 32 33 }
• RemoteButton.java
1 // Abstraction 2 3 // This is an abstract class that will represent numerous 4 // ways to work with each device 5 6 public abstract class RemoteButton{ 7 8 // A reference to a generic device using aggregation 9 10 private EntertainmentDevice theDevice; 11 12 public RemoteButton(EntertainmentDevice newDevice){ 13 14 theDevice = newDevice; 15 16 } 17 18 public void buttonFivePressed() { 19 20 theDevice.buttonFivePressed(); 21 22 } 23 24 public void buttonSixPressed() { 25 26 theDevice.buttonSixPressed(); 27 28 } 29 30 public void deviceFeedback(){ 31 32 theDevice.deviceFeedback(); 33 34 } 35 36 public abstract void buttonNinePressed(); 37 38 }
• TVRemoteMute.java
1 // Refined Abstraction 2 3 // If I decide I want to further extend the remote I can 4 5 public class TVRemoteMute extends RemoteButton{ 6 7 public TVRemoteMute(EntertainmentDevice newDevice) { 8 super(newDevice); 9 } 10 11 public void buttonNinePressed() { 12 13 System.out.println("TV was Muted"); 14 15 } 16 17 }
• TVRemotePause.java
1 // Refined Abstraction 2 3 // If I decide I want to further extend the remote I can 4 5 public class TVRemotePause extends RemoteButton{ 6 7 public TVRemotePause(EntertainmentDevice newDevice) { 8 super(newDevice); 9 } 10 11 public void buttonNinePressed() { 12 13 System.out.println("TV was Paused"); 14 15 } 16 17 }
• TestTheRemote.java
1 public class TestTheRemote{ 2 3 public static void main(String[] args){ 4 5 RemoteButton theTV = new TVRemoteMute(new TVDevice(1, 200)); 6 7 RemoteButton theTV2 = new TVRemotePause(new TVDevice(1, 200)); 8 9 // HOMEWORK -------------- 10 11 RemoteButton theDVD = new DVDRemote(new DVDDevice(1,14)); 12 13 // ----------------------- 14 15 System.out.println("Test TV with Mute"); 16 17 theTV.buttonFivePressed(); 18 theTV.buttonSixPressed(); 19 theTV.buttonNinePressed(); 20 21 System.out.println("\nTest TV with Pause"); 22 23 theTV2.buttonFivePressed(); 24 theTV2.buttonSixPressed(); 25 theTV2.buttonNinePressed(); 26 theTV2.deviceFeedback(); 27 28 // HOMEWORK 29 30 System.out.println("\nTest DVD"); 31 32 theDVD.buttonFivePressed(); 33 theDVD.buttonSixPressed(); 34 theDVD.buttonNinePressed(); 35 theDVD.buttonNinePressed(); 36 37 } 38 39 }
Flyweight
What is the Flyweight Design Pattern?
• Used when you need to create a large number of similar objects.
• To reduce memory usage you share objects that are similar in some way rather than creating new ones.
• Intrinsic State: Color.
• Extrinsic State: Size.
Sample Code
• FlyWeightTest.java
1 // The Flyweight design pattern is used when you need to 2 // create a large number of similar objects 3 4 // To reduce memory this pattern shares Objects that are 5 // the same rather than creating new ones 6 7 import javax.swing.*; 8 9 import java.awt.BorderLayout; 10 import java.awt.Color; 11 import java.awt.Graphics; 12 13 import java.awt.event.ActionEvent; 14 import java.awt.event.ActionListener; 15 import java.util.Random; 16 17 public class FlyWeightTest extends JFrame{ 18 19 private static final long serialVersionUID = 1L; 20 21 JButton startDrawing; 22 23 int windowWidth = 1750; 24 int windowHeight = 1000; 25 26 // A new rectangle is created only if a new color is needed 27 28 Color[] shapeColor = {Color.orange, Color.red, Color.yellow, 29 Color.blue, Color.pink, Color.cyan, Color.magenta, 30 Color.black, Color.gray}; 31 32 public static void main(String[] args){ 33 34 new FlyWeightTest(); 35 36 } 37 38 public FlyWeightTest(){ 39 40 // Create the frame, position it and handle closing it 41 42 this.setSize(windowWidth,windowHeight); 43 this.setLocationRelativeTo(null); 44 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 45 this.setTitle("Flyweight Test"); 46 47 JPanel contentPane = new JPanel(); 48 49 contentPane.setLayout(new BorderLayout()); 50 51 final JPanel drawingPanel = new JPanel(); 52 53 startDrawing = new JButton("Button 1"); 54 55 contentPane.add(drawingPanel, BorderLayout.CENTER); 56 57 contentPane.add(startDrawing, BorderLayout.SOUTH); 58 59 startDrawing.addActionListener(new ActionListener() { 60 61 public void actionPerformed(ActionEvent event) { 62 Graphics g = drawingPanel.getGraphics(); 63 64 65 long startTime = System.currentTimeMillis(); 66 67 68 for(int i=0; i < 100000; ++i) { 69 70 // 71 // Uses rectangles stored in the HashMap to 72 // speed up the program 73 74 MyRect rect = RectFactory.getRect(getRandColor()); 75 rect.draw(g, getRandX(), getRandY(), 76 getRandX(), getRandY()); 77 78 // 79 /* 80 MyRect rect = new MyRect(getRandColor(), getRandX(), getRandY(), getRandX(), getRandY()); 81 rect.draw(g); 82 */ 83 84 85 // 86 /* 87 g.setColor(getRandColor()); 88 g.fillRect(getRandX(), getRandY(), getRandX(), getRandY()); 89 */ 90 91 92 } 93 94 long endTime = System.currentTimeMillis(); 95 96 System.out.println("That took " + (endTime - startTime) + " milliseconds"); 97 98 } 99 }); 100 101 this.add(contentPane); 102 103 this.setVisible(true); 104 105 } 106 107 // Picks random x & y coordinates 108 109 private int getRandX(){ return (int)(Math.random()*windowWidth); } 110 111 private int getRandY(){ return (int)(Math.random()*windowHeight); } 112 113 // Picks a random Color from the 9 available 114 115 private Color getRandColor(){ 116 Random randomGenerator = new Random(); 117 118 int randInt = randomGenerator.nextInt(9); 119 120 return shapeColor[randInt]; 121 122 } 123 124 }
• MyRect.java
1 import java.awt.*; 2 public class MyRect { 3 private Color color = Color.black; 4 private int x, y, x2, y2; 5 6 public MyRect(Color color) { 7 8 this.color = color; 9 10 } 11 12 public void draw(Graphics g, int upperX, int upperY, int lowerX, int lowerY) { 13 g.setColor(color); 14 g.fillRect(upperX, upperY, lowerX, lowerY); 15 } 16 17 /* Original forces creation of a rectangle every time 18 19 public MyRect(Color color, int upperX, int upperY, int lowerX, int lowerY) { 20 this.color = color; 21 this.x = upperX; 22 this.y = upperY; 23 this.x2 = lowerX; 24 this.y2 = lowerY; 25 } 26 27 public void draw(Graphics g) { 28 g.setColor(color); 29 g.fillRect(x, y, x2, y2); 30 } 31 */ 32 }
• RectFactory.java
1 // This factory only creates a new rectangle if it 2 // uses a color not previously used 3 4 // Intrinsic State: Color 5 // Extrinsic State: X & Y Values 6 7 import java.util.HashMap; 8 import java.awt.Color; 9 public class RectFactory { 10 11 // The HashMap uses the color as the key for every 12 // rectangle it will make up to 8 total 13 14 private static final HashMap<Color, MyRect> rectsByColor = new HashMap<Color, MyRect>(); 15 16 public static MyRect getRect(Color color) { 17 MyRect rect = (MyRect)rectsByColor.get(color); 18 19 // Checks if a rectangle with a specific 20 // color has been made. If not it makes a 21 // new one, otherwise it returns one made already 22 23 if(rect == null) { 24 rect = new MyRect(color); 25 26 // Add new rectangle to HashMap 27 28 rectsByColor.put(color, rect); 29 30 } 31 return rect; 32 } 33 }
Proxy
What is the Proxy Design Pattern?
• Provide a class which will limit access to another class.
• You may do this for security reasons, because an Object is intensive to create, or is accessed from a remote location.
Sample Code
• ATMMachine.java
1 public class ATMMachine implements GetATMData{ 2 3 4 public ATMState getYesCardState() { return hasCard; } 5 public ATMState getNoCardState() { return noCard; } 6 public ATMState getHasPin() { return hasCorrectPin; } 7 public ATMState getNoCashState() { return atmOutOfMoney; } 8 9 // NEW STUFF 10 11 public ATMState getATMState() { return atmState; } 12 public int getCashInMachine() { return cashInMachine; } 13 }
• GetATMData.java
1 // This interface will contain just those methods 2 // that you want the proxy to provide access to 3 4 public interface GetATMData { 5 public ATMState getATMState(); 6 public int getCashInMachine(); 7 }
• ATMProxy.java
1 // In this situation the proxy both creates and destroys 2 // an ATMMachine Object 3 4 public class ATMProxy implements GetATMData { 5 6 // Allows the user to access getATMState in the 7 // Object ATMMachine 8 9 public ATMState getATMState() { 10 11 ATMMachine realATMMachine = new ATMMachine(); 12 13 return realATMMachine.getATMState(); 14 } 15 16 // Allows the user to access getCashInMachine 17 // in the Object ATMMachine 18 19 public int getCashInMachine() { 20 21 ATMMachine realATMMachine = new ATMMachine(); 22 23 return realATMMachine.getCashInMachine(); 24 25 } 26 27 }
• 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 // NEW STUFF : Proxy Design Pattern Code 22 // The interface limits access to just the methods you want 23 // made accessible 24 25 GetATMData realATMMachine = new ATMMachine(); 26 27 GetATMData atmProxy = new ATMProxy(); 28 29 System.out.println("\nCurrent ATM State " + atmProxy.getATMState()); 30 31 System.out.println("\nCash in ATM Machine $" + atmProxy.getCashInMachine()); 32 33 // The user can't perform this action because ATMProxy doesn't 34 // have access to that potentially harmful method 35 // atmProxy.setCashInMachine(10000); 36 37 } 38 39 }
• ATMState.java
1 public interface ATMState { 2 3 void insertCard(); 4 void ejectCard(); 5 void insertPin(int pinEntered); 6 void requestCash(int cashToWithdraw); 7 8 }
作者:netoxi
出处:http://www.cnblogs.com/netoxi
本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。