zoukankan      html  css  js  c++  java
  • 设计模式教程(Design Patterns Tutorial)笔记之二 结构型模式(Structural Patterns)

    目录

    · Decorator

        · What is the Decorator Design Pattern?

        · Sample Code 

    · Adapter

        · What is the Adapter Design Pattern?

        · Sample Code

    · Facade

        · What is the Facade Design Pattern?

        · Sample Code

    · Bridge

        · What is the Bridge Design Pattern?

        · When to use the Bridge Design Pattern?

        · Sample Code

    · Flyweight

        · What is the Flyweight Design Pattern?

        · Sample Code

    · Proxy

        · What is the Proxy Design Pattern?

        · Sample Code


    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
    ");
     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
    ");
    43                     
    44                 } else {
    45                     
    46                     System.out.println("Transaction Failed
    ");
    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
    ");
    61                     
    62                 } else {
    63                     
    64                     System.out.println("Transaction Failed
    ");
    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("
    Test TV with Pause");
    22         
    23         theTV2.buttonFivePressed();
    24         theTV2.buttonSixPressed();
    25         theTV2.buttonNinePressed();
    26         theTV2.deviceFeedback();
    27         
    28         // HOMEWORK
    29         
    30         System.out.println("
    Test 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("
    Current ATM State " + atmProxy.getATMState());
    30         
    31         System.out.println("
    Cash 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
    本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。

  • 相关阅读:
    博客园Js设置
    springboot练习笔记
    相关的其他文件
    设计模式之----代理模式
    JSP的四种范围
    io流读写及相关内容
    缓存
    gson解析json
    Android简单获得通讯录
    android服务之一 Service
  • 原文地址:https://www.cnblogs.com/netoxi/p/10089215.html
Copyright © 2011-2022 走看看