目录
· 概述
· Factory
· What is the Factory Design Pattern?
· What is the Abstract Factory Design Pattern?
· What can you do with an Abstract Factory Design Pattern?
· What is the Singleton Design Pattern?
· Builder
· What is the Builder Design Pattern?
· What is the Prototype Design Pattern?
概述
最近在YouTube上看了一套不错的设计模式视频,同时翻看GOF的《设计模式 可复用面向对象软件的基础》,刷新了我对设计模式的认识。加之之前的一篇博文《设计模式笔记——GoF设计模式汇总》中未提及比较少用的解释器和访问者模式,以及大陆无法打开YouTube等原因,所以将这套视频所学到的主要内容记录成笔记,供未来需要时查阅和复习。
Factory
What is the Factory Design Pattern?
• When a method returns one of several possible classes that share a common super class.
• Create a new enemy in a game.
• Random number generator picks a number assigned to a specific enemy.
• The factory returns the enemy associated with that number.
• The class is chosen at run time.
Sample Code
• EnemyShip.java
1 public abstract class EnemyShip { 2 3 private String name; 4 private double speed; 5 private double directionX; 6 private double directionY; 7 private double amtDamage; 8 9 public String getName() { return name; } 10 public void setName(String newName) { name = newName; } 11 12 public double getDamage() { return amtDamage; } 13 public void setDamage(double newDamage) { amtDamage = newDamage; } 14 15 public void followHeroShip(){ 16 17 System.out.println(getName() + " is following the hero"); 18 19 } 20 21 public void displayEnemyShip(){ 22 23 System.out.println(getName() + " is on the screen"); 24 25 } 26 27 public void enemyShipShoots() { 28 29 System.out.println(getName() + " attacks and does " + getDamage() + " damage to hero"); 30 31 } 32 33 }
• UFOEnemyShip.java
1 public class UFOEnemyShip extends EnemyShip { 2 3 public UFOEnemyShip(){ 4 5 setName("UFO Enemy Ship"); 6 7 setDamage(20.0); 8 9 } 10 11 }
• RocketEnemyShip.java
1 public class RocketEnemyShip extends EnemyShip { 2 3 public RocketEnemyShip(){ 4 5 setName("Rocket Enemy Ship"); 6 7 setDamage(10.0); 8 9 } 10 11 }
• EnemyShipTesting.java
1 import java.util.Scanner; 2 3 public class EnemyShipTesting { 4 5 public static void main(String[] args){ 6 7 // Create the factory object 8 EnemyShipFactory shipFactory = new EnemyShipFactory(); 9 10 // Enemy ship object 11 12 EnemyShip theEnemy = null; 13 14 Scanner userInput = new Scanner(System.in); 15 16 System.out.print("What type of ship? (U / R / B)"); 17 18 if (userInput.hasNextLine()){ 19 20 String typeOfShip = userInput.nextLine(); 21 22 theEnemy = shipFactory.makeEnemyShip(typeOfShip); 23 24 if(theEnemy != null){ 25 26 doStuffEnemy(theEnemy); 27 28 } else System.out.print("Please enter U, R, or B next time"); 29 30 } 31 32 /* 33 EnemyShip theEnemy = null; 34 35 // Old way of creating objects 36 // When we use new we are not being dynamic 37 38 EnemyShip ufoShip = new UFOEnemyShip(); 39 40 doStuffEnemy(ufoShip); 41 42 System.out.print(" "); 43 44 // ----------------------------------------- 45 46 // This allows me to make the program more dynamic 47 // It doesn't close the code from being modified 48 // and that is bad! 49 50 // Defines an input stream to watch: keyboard 51 Scanner userInput = new Scanner(System.in); 52 53 String enemyShipOption = ""; 54 55 System.out.print("What type of ship? (U or R)"); 56 57 if (userInput.hasNextLine()){ 58 59 enemyShipOption = userInput.nextLine(); 60 61 } 62 63 if (enemyShipOption == "U"){ 64 65 theEnemy = new UFOEnemyShip(); 66 67 68 } else 69 70 if (enemyShipOption == "R"){ 71 72 theEnemy = new RocketEnemyShip(); 73 74 } else { 75 76 theEnemy = new BigUFOEnemyShip(); 77 78 } 79 80 doStuffEnemy(theEnemy); 81 82 // -------------------------------------------- 83 */ 84 85 } 86 87 // Executes methods of the super class 88 89 public static void doStuffEnemy(EnemyShip anEnemyShip){ 90 91 anEnemyShip.displayEnemyShip(); 92 93 anEnemyShip.followHeroShip(); 94 95 anEnemyShip.enemyShipShoots(); 96 97 } 98 99 }
• BigUFOEnemyShip.java
1 public class BigUFOEnemyShip extends UFOEnemyShip { 2 3 public BigUFOEnemyShip(){ 4 5 setName("Big UFO Enemy Ship"); 6 7 setDamage(40.0); 8 9 } 10 11 }
• EnemyShipFactory.java
1 // This is a factory thats only job is creating ships 2 // By encapsulating ship creation, we only have one 3 // place to make modifications 4 5 public class EnemyShipFactory{ 6 7 // This could be used as a static method if we 8 // are willing to give up subclassing it 9 10 public EnemyShip makeEnemyShip(String newShipType){ 11 12 EnemyShip newShip = null; 13 14 if (newShipType.equals("U")){ 15 16 return new UFOEnemyShip(); 17 18 } else 19 20 if (newShipType.equals("R")){ 21 22 return new RocketEnemyShip(); 23 24 } else 25 26 if (newShipType.equals("B")){ 27 28 return new BigUFOEnemyShip(); 29 30 } else return null; 31 32 } 33 34 }
Abstract Factory
What is the Abstract Factory Design Pattern?
• It is like a factory, but everything is encapsulated.
• The method that orders the object.
• The factories that build the object.
• The final objects.
• The final objects contain objects that use the Strategy Design Pattern.
• Composition: Object class fields are objects.
What can you do with an Abstract Factory Design Pattern?
• Allows you to create families of related objects without specifying a concrete class.
• Use when you have many objects that can be added, or changed dynamically during runtime.
• You can model anything you can imagine and have those objects interact through common interfaces.
• The Bad: Things can get complicated.
Sample Code
• EnemyShipTesting.java
1 public class EnemyShipTesting { 2 3 public static void main(String[] args) { 4 5 // EnemyShipBuilding handles orders for new EnemyShips 6 // You send it a code using the orderTheShip method & 7 // it sends the order to the right factory for creation 8 9 EnemyShipBuilding MakeUFOs = new UFOEnemyShipBuilding(); 10 11 EnemyShip theGrunt = MakeUFOs.orderTheShip("UFO"); 12 System.out.println(theGrunt + " "); 13 14 EnemyShip theBoss = MakeUFOs.orderTheShip("UFO BOSS"); 15 System.out.println(theBoss + " "); 16 17 } 18 19 }
• EnemyShipBuilding.java
1 public abstract class EnemyShipBuilding { 2 3 // This acts as an ordering mechanism for creating 4 // EnemyShips that have a weapon, engine & name 5 // & nothing else 6 7 // The specific parts used for engine & weapon depend 8 // upon the String that is passed to this method 9 10 protected abstract EnemyShip makeEnemyShip(String typeOfShip); 11 12 // When called a new EnemyShip is made. The specific parts 13 // are based on the String entered. After the ship is made 14 // we execute multiple methods in the EnemyShip Object 15 16 public EnemyShip orderTheShip(String typeOfShip) { 17 EnemyShip theEnemyShip = makeEnemyShip(typeOfShip); 18 19 theEnemyShip.makeShip(); 20 theEnemyShip.displayEnemyShip(); 21 theEnemyShip.followHeroShip(); 22 theEnemyShip.enemyShipShoots(); 23 24 return theEnemyShip; 25 26 } 27 }
• UFOEnemyShipBuilding.java
1 // This is the only class that needs to change, if you 2 // want to determine which enemy ships you want to 3 // provide as an option to build 4 5 public class UFOEnemyShipBuilding extends EnemyShipBuilding { 6 7 protected EnemyShip makeEnemyShip(String typeOfShip) { 8 EnemyShip theEnemyShip = null; 9 10 // If UFO was sent grab use the factory that knows 11 // what types of weapons and engines a regular UFO 12 // needs. The EnemyShip object is returned & given a name 13 14 if(typeOfShip.equals("UFO")){ 15 EnemyShipFactory shipPartsFactory = new UFOEnemyShipFactory(); 16 theEnemyShip = new UFOEnemyShip(shipPartsFactory); 17 theEnemyShip.setName("UFO Grunt Ship"); 18 19 } else 20 21 // If UFO BOSS was sent grab use the factory that knows 22 // what types of weapons and engines a Boss UFO 23 // needs. The EnemyShip object is returned & given a name 24 25 if(typeOfShip.equals("UFO BOSS")){ 26 EnemyShipFactory shipPartsFactory = new UFOBossEnemyShipFactory(); 27 theEnemyShip = new UFOBossEnemyShip(shipPartsFactory); 28 theEnemyShip.setName("UFO Boss Ship"); 29 30 } 31 32 return theEnemyShip; 33 } 34 }
• EnemyShipFactory.java
1 // With an Abstract Factory Pattern you won't 2 // just build ships, but also all of the components 3 // for the ships 4 5 // Here is where you define the parts that are required 6 // if an object wants to be an enemy ship 7 8 public interface EnemyShipFactory{ 9 10 public ESWeapon addESGun(); 11 public ESEngine addESEngine(); 12 13 }
• UFOEnemyShipFactory.java
1 // This factory uses the EnemyShipFactory interface 2 // to create very specific UFO Enemy Ship 3 4 // This is where we define all of the parts the ship 5 // will use by defining the methods implemented 6 // being ESWeapon and ESEngine 7 8 // The returned object specifies a specific weapon & engine 9 10 public class UFOEnemyShipFactory implements EnemyShipFactory{ 11 12 // Defines the weapon object to associate with the ship 13 14 public ESWeapon addESGun() { 15 return new ESUFOGun(); // Specific to regular UFO 16 } 17 18 // Defines the engine object to associate with the ship 19 20 public ESEngine addESEngine() { 21 return new ESUFOEngine(); // Specific to regular UFO 22 } 23 }
• UFOBossEnemyShipFactory.java
1 // This factory uses the EnemyShipFactory interface 2 // to create very specific UFO Enemy Ship 3 4 // This is where we define all of the parts the ship 5 // will use by defining the methods implemented 6 // being ESWeapon and ESEngine 7 8 // The returned object specifies a specific weapon & engine 9 10 public class UFOBossEnemyShipFactory implements EnemyShipFactory{ 11 12 // Defines the weapon object to associate with the ship 13 14 public ESWeapon addESGun() { 15 return new ESUFOBossGun(); // Specific to Boss UFO 16 } 17 18 // Defines the engine object to associate with the ship 19 20 public ESEngine addESEngine() { 21 return new ESUFOBossEngine(); // Specific to Boss UFO 22 } 23 24 }
• EnemyShip.java
1 public abstract class EnemyShip { 2 3 private String name; 4 5 // Newly defined objects that represent weapon & engine 6 // These can be changed easily by assigning new parts 7 // in UFOEnemyShipFactory or UFOBossEnemyShipFactory 8 9 ESWeapon weapon; 10 ESEngine engine; 11 12 public String getName() { return name; } 13 public void setName(String newName) { name = newName; } 14 15 abstract void makeShip(); 16 17 // Because I defined the toString method in engine 18 // when it is printed the String defined in toString goes 19 // on the screen 20 21 public void followHeroShip(){ 22 23 System.out.println(getName() + " is following the hero at " + engine ); 24 25 } 26 27 public void displayEnemyShip(){ 28 29 System.out.println(getName() + " is on the screen"); 30 31 } 32 33 public void enemyShipShoots(){ 34 35 System.out.println(getName() + " attacks and does " + weapon); 36 37 } 38 39 // If any EnemyShip object is printed to screen this shows up 40 41 public String toString(){ 42 43 String infoOnShip = "The " + name + " has a top speed of " + engine + 44 " and an attack power of " + weapon; 45 46 return infoOnShip; 47 48 } 49 50 }
• UFOEnemyShip.java
1 public class UFOEnemyShip extends EnemyShip{ 2 3 // We define the type of ship we want to create 4 // by stating we want to use the factory that 5 // makes enemy ships 6 7 EnemyShipFactory shipFactory; 8 9 // The enemy ship required parts list is sent to 10 // this method. They state that the enemy ship 11 // must have a weapon and engine assigned. That 12 // object also states the specific parts needed 13 // to make a regular UFO versus a Boss UFO 14 15 public UFOEnemyShip(EnemyShipFactory shipFactory){ 16 17 this.shipFactory = shipFactory; 18 19 } 20 21 // EnemyShipBuilding calls this method to build a 22 // specific UFOEnemyShip 23 24 void makeShip() { 25 26 System.out.println("Making enemy ship " + getName()); 27 28 // The specific weapon & engine needed were passed in 29 // shipFactory. We are assigning those specific part 30 // objects to the UFOEnemyShip here 31 32 weapon = shipFactory.addESGun(); 33 engine = shipFactory.addESEngine(); 34 35 } 36 37 }
• UFOBossEnemyShip.java
1 public class UFOBossEnemyShip extends EnemyShip{ 2 3 // We define the type of ship we want to create 4 // by stating we want to use the factory that 5 // makes enemy ships 6 7 EnemyShipFactory shipFactory; 8 9 // The enemy ship required parts list is sent to 10 // this method. They state that the enemy ship 11 // must have a weapon and engine assigned. That 12 // object also states the specific parts needed 13 // to make a Boss UFO versus a Regular UFO 14 15 public UFOBossEnemyShip(EnemyShipFactory shipFactory){ 16 17 this.shipFactory = shipFactory; 18 19 } 20 21 // EnemyShipBuilding calls this method to build a 22 // specific UFOBossEnemyShip 23 24 void makeShip() { 25 26 // TODO Auto-generated method stub 27 28 System.out.println("Making enemy ship " + getName()); 29 30 // The specific weapon & engine needed were passed in 31 // shipFactory. We are assigning those specific part 32 // objects to the UFOBossEnemyShip here 33 34 weapon = shipFactory.addESGun(); 35 engine = shipFactory.addESEngine(); 36 37 } 38 39 }
• ESEngine.java
1 // Any part that implements the interface ESEngine 2 // can replace that part in any ship 3 4 public interface ESEngine{ 5 6 // User is forced to implement this method 7 // It outputs the string returned when the 8 // object is printed 9 10 public String toString(); 11 12 }
• ESWeapon.java
1 // Any part that implements the interface ESWeapon 2 // can replace that part in any ship 3 4 public interface ESWeapon{ 5 6 // User is forced to implement this method 7 // It outputs the string returned when the 8 // object is printed 9 10 public String toString(); 11 12 }
• ESUFOGun.java
1 // Here we define a basic component of a space ship 2 // Any part that implements the interface ESWeapon 3 // can replace that part in any ship 4 5 public class ESUFOGun implements ESWeapon{ 6 7 // EnemyShip contains a reference to the object 8 // ESWeapon. It is stored in the field weapon 9 10 // The Strategy design pattern is being used here 11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen 14 15 public String toString(){ 16 return "20 damage"; 17 } 18 19 }
• ESUFOEngine.java
1 // Here we define a basic component of a space ship 2 // Any part that implements the interface ESEngine 3 // can replace that part in any ship 4 5 public class ESUFOEngine implements ESEngine{ 6 7 // EnemyShip contains a reference to the object 8 // ESWeapon. It is stored in the field weapon 9 10 // The Strategy design pattern is being used here 11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen 14 15 public String toString(){ 16 return "1000 mph"; 17 } 18 19 }
• ESUFOBossGun.java
1 // Here we define a basic component of a space ship 2 // Any part that implements the interface ESWeapon 3 // can replace that part in any ship 4 5 public class ESUFOBossGun implements ESWeapon{ 6 7 // EnemyShip contains a reference to the object 8 // ESWeapon. It is stored in the field weapon 9 10 // The Strategy design pattern is being used here 11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen 14 15 public String toString(){ 16 return "40 damage"; 17 } 18 19 }
• ESUFOBossEngine.java
1 // Here we define a basic component of a space ship 2 // Any part that implements the interface ESEngine 3 // can replace that part in any ship 4 5 public class ESUFOBossEngine implements ESEngine{ 6 7 // EnemyShip contains a reference to the object 8 // ESWeapon. It is stored in the field weapon 9 10 // The Strategy design pattern is being used here 11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen 14 15 public String toString(){ 16 return "2000 mph"; 17 } 18 19 }
Singleton
What is the Singleton Design Pattern?
• It is used when you want to eliminate the option of instantiating more than one object.
• I'll Samplenstrate it using a class that holds all the potential Scrabble letters and spits out new ones upon request.
• Each player will share the same potential letter list.
• Each player has their own set of letters.
Sample Code
• Singleton.java
1 import java.util.Arrays; 2 import java.util.Collections; 3 import java.util.LinkedList; 4 5 public class Singleton { 6 7 private static Singleton firstInstance = null; 8 9 String[] scrabbleLetters = {"a", "a", "a", "a", "a", "a", "a", "a", "a", 10 "b", "b", "c", "c", "d", "d", "d", "d", "e", "e", "e", "e", "e", 11 "e", "e", "e", "e", "e", "e", "e", "f", "f", "g", "g", "g", "h", 12 "h", "i", "i", "i", "i", "i", "i", "i", "i", "i", "j", "k", "l", 13 "l", "l", "l", "m", "m", "n", "n", "n", "n", "n", "n", "o", "o", 14 "o", "o", "o", "o", "o", "o", "p", "p", "q", "r", "r", "r", "r", 15 "r", "r", "s", "s", "s", "s", "t", "t", "t", "t", "t", "t", "u", 16 "u", "u", "u", "v", "v", "w", "w", "x", "y", "y", "z",}; 17 18 private LinkedList<String> letterList = new LinkedList<String> (Arrays.asList(scrabbleLetters)); 19 20 // Used to slow down 1st thread 21 static boolean firstThread = true; 22 23 // Created to keep users from instantiation 24 // Only Singleton will be able to instantiate this class 25 26 private Singleton() { } 27 28 // We could make getInstance a synchronized method to force 29 // every thread to wait its turn. That way only one thread 30 // can access a method at a time. This can really slow everything 31 // down though 32 // public static synchronized Singleton getInstance() 33 34 public static Singleton getInstance() { 35 if(firstInstance == null) { 36 37 // This is here to test what happens if threads try 38 // to create instances of this class 39 40 if(firstThread){ 41 42 firstThread = false; 43 44 try { 45 Thread.currentThread(); 46 Thread.sleep(1000); 47 } catch (InterruptedException e) { 48 49 e.printStackTrace(); 50 } 51 } 52 53 // Here we just use synchronized when the first object 54 // is created 55 56 synchronized(Singleton.class){ 57 58 if(firstInstance == null) { 59 // If the instance isn't needed it isn't created 60 // This is known as lazy instantiation 61 62 firstInstance = new Singleton(); 63 64 // Shuffle the letters in the list 65 Collections.shuffle(firstInstance.letterList); 66 67 } 68 69 } 70 71 } 72 73 // Under either circumstance this returns the instance 74 75 return firstInstance; 76 } 77 78 public LinkedList<String> getLetterList(){ 79 80 return firstInstance.letterList; 81 82 } 83 84 public LinkedList<String> getTiles(int howManyTiles){ 85 86 // Tiles to be returned to the user 87 88 LinkedList<String> tilesToSend = new LinkedList<String>(); 89 90 // Cycle through the LinkedList while adding the starting 91 // Strings to the to be returned LinkedList while deleting 92 // them from letterList 93 94 for(int i = 0; i <= howManyTiles; i++){ 95 96 tilesToSend.add(firstInstance.letterList.remove(0)); 97 98 } 99 100 // Return the number of letter tiles requested 101 102 return tilesToSend; 103 104 } 105 106 }
• ScrabbleTest.java
1 import java.util.LinkedList; 2 3 public class ScrabbleTest { 4 5 public static void main(String[] args){ 6 7 // How you create a new instance of Singleton 8 9 Singleton newInstance = Singleton.getInstance(); 10 11 // Get unique id for instance object 12 13 System.out.println("1st Instance ID: " + System.identityHashCode(newInstance)); 14 15 // Get all of the letters stored in the List 16 17 System.out.println(newInstance.getLetterList()); 18 19 LinkedList<String> playerOneTiles = newInstance.getTiles(7); 20 21 System.out.println("Player 1: " + playerOneTiles); 22 23 System.out.println(newInstance.getLetterList()); 24 25 // Try to make another instance of Singleton 26 // This doesn't work because the constructor is private 27 28 // Singleton instanceTwo = new Singleton(); 29 30 // Try getting a new instance using getInstance 31 32 Singleton instanceTwo = Singleton.getInstance(); 33 34 // Get unique id for the new instance object 35 36 System.out.println("2nd Instance ID: " + System.identityHashCode(instanceTwo)); 37 38 // This returns the value of the first instance created 39 40 System.out.println(instanceTwo.getLetterList()); 41 42 // Player 2 draws 7 tiles 43 44 LinkedList<String> playerTwoTiles = newInstance.getTiles(7); 45 46 System.out.println("Player 2: " + playerTwoTiles); 47 48 } 49 50 }
• ScrabbleTestThreads.java
1 public class ScrabbleTestThreads{ 2 3 public static void main(String[] args){ 4 5 // Create a new Thread created using the Runnable interface 6 // Execute the code in run after 10 seconds 7 8 Runnable getTiles = new GetTheTiles(); 9 10 Runnable getTilesAgain = new GetTheTiles(); 11 12 // Call for the code in the method run to execute 13 14 new Thread(getTiles).start(); 15 new Thread(getTilesAgain).start(); 16 17 } 18 19 }
• GetTheTiles.java
1 import java.util.LinkedList; 2 3 public class GetTheTiles implements Runnable { 4 5 public void run(){ 6 7 // How you create a new instance of Singleton 8 9 Singleton newInstance = Singleton.getInstance(); 10 11 // Get unique id for instance object 12 13 System.out.println("1st Instance ID: " + System.identityHashCode(newInstance)); 14 15 // Get all of the letters stored in the List 16 17 System.out.println(newInstance.getLetterList()); 18 19 LinkedList<String> playerOneTiles = newInstance.getTiles(7); 20 21 System.out.println("Player 1: " + playerOneTiles); 22 23 System.out.println("Got Tiles"); 24 } 25 26 }
Builder
What is the Builder Design Pattern?
• Pattern used to create objects made from a bunch of other objects.
• When you want to build an object made up from other objects.
• When you want the creation of these parts to be independent of the main object.
• Hide the creation of the parts from the client so both aren't dependent.
• The builder knows the specifics and nobody else dose.
Sample Code
• RobotPlan.java
1 // This is the interface that will be returned from the builder 2 3 public interface RobotPlan{ 4 5 public void setRobotHead(String head); 6 7 public void setRobotTorso(String torso); 8 9 public void setRobotArms(String arms); 10 11 public void setRobotLegs(String legs); 12 13 }
• Robot.java
1 // The concrete Robot class based on the RobotPlan interface 2 3 public class Robot implements RobotPlan{ 4 5 private String robotHead; 6 private String robotTorso; 7 private String robotArms; 8 private String robotLegs; 9 10 public void setRobotHead(String head) { 11 12 robotHead = head; 13 14 } 15 16 public String getRobotHead(){ return robotHead; } 17 18 19 public void setRobotTorso(String torso) { 20 21 robotTorso = torso; 22 23 } 24 25 public String getRobotTorso(){ return robotTorso; } 26 27 28 public void setRobotArms(String arms) { 29 30 robotArms = arms; 31 32 } 33 34 public String getRobotArms(){ return robotArms; } 35 36 37 public void setRobotLegs(String legs) { 38 39 robotLegs = legs; 40 41 } 42 43 public String getRobotLegs(){ return robotLegs; } 44 45 46 47 }
• RobotBuilder.java
1 // Defines the methods needed for creating parts 2 // for the robot 3 4 public interface RobotBuilder { 5 6 public void buildRobotHead(); 7 8 public void buildRobotTorso(); 9 10 public void buildRobotArms(); 11 12 public void buildRobotLegs(); 13 14 public Robot getRobot(); 15 16 }
• OldRobotBuilder.java
1 // The concrete builder class that assembles the parts 2 // of the finished Robot object 3 4 public class OldRobotBuilder implements RobotBuilder { 5 6 private Robot robot; 7 8 public OldRobotBuilder() { 9 10 this.robot = new Robot(); 11 12 } 13 14 public void buildRobotHead() { 15 16 robot.setRobotHead("Tin Head"); 17 18 } 19 20 public void buildRobotTorso() { 21 22 robot.setRobotTorso("Tin Torso"); 23 24 } 25 26 public void buildRobotArms() { 27 28 robot.setRobotArms("Blowtorch Arms"); 29 30 } 31 32 public void buildRobotLegs() { 33 34 robot.setRobotLegs("Rollar Skates"); 35 36 } 37 38 public Robot getRobot() { 39 40 return this.robot; 41 } 42 43 44 45 }
• RobotEngineer.java
1 // The director / engineer class creates a Robot using the 2 // builder interface that is defined (OldRobotBuilder) 3 4 public class RobotEngineer { 5 6 private RobotBuilder robotBuilder; 7 8 // OldRobotBuilder specification is sent to the engineer 9 10 public RobotEngineer(RobotBuilder robotBuilder){ 11 12 this.robotBuilder = robotBuilder; 13 14 } 15 16 // Return the Robot made from the OldRobotBuilder spec 17 18 public Robot getRobot(){ 19 20 return this.robotBuilder.getRobot(); 21 22 } 23 24 // Execute the methods specific to the RobotBuilder 25 // that implements RobotBuilder (OldRobotBuilder) 26 27 public void makeRobot() { 28 29 this.robotBuilder.buildRobotHead(); 30 this.robotBuilder.buildRobotTorso(); 31 this.robotBuilder.buildRobotArms(); 32 this.robotBuilder.buildRobotLegs(); 33 34 } 35 36 }
• TestRobotBuilder.java
1 public class TestRobotBuilder { 2 3 public static void main(String[] args){ 4 5 // Get a RobotBuilder of type OldRobotBuilder 6 7 RobotBuilder oldStyleRobot = new OldRobotBuilder(); 8 9 // Pass the OldRobotBuilder specification to the engineer 10 11 RobotEngineer robotEngineer = new RobotEngineer(oldStyleRobot); 12 13 // Tell the engineer to make the Robot using the specifications 14 // of the OldRobotBuilder class 15 16 robotEngineer.makeRobot(); 17 18 // The engineer returns the right robot based off of the spec 19 // sent to it on line 11 20 21 Robot firstRobot = robotEngineer.getRobot(); 22 23 System.out.println("Robot Built"); 24 25 System.out.println("Robot Head Type: " + firstRobot.getRobotHead()); 26 27 System.out.println("Robot Torso Type: " + firstRobot.getRobotTorso()); 28 29 System.out.println("Robot Arm Type: " + firstRobot.getRobotArms()); 30 31 System.out.println("Robot Leg Type: " + firstRobot.getRobotLegs()); 32 33 } 34 35 }
Prototype
What is the Prototype Design Pattern?
• Creating new objects (instances) by cloning (copying) other objects.
• Allows for adding of any subclass instance of a known super class at run time.
• When there are numerous potential classes that you want to only use if needed at runtime.
• Reduces the need for creating subclasses.
Sample Code
• Animal.java
1 // By making this class cloneable you are telling Java 2 // that it is ok to copy instances of this class 3 // These instance copies have different results when 4 // System.identityHashCode(System.identityHashCode(bike)) 5 // is called 6 7 public interface Animal extends Cloneable { 8 9 public Animal makeCopy(); 10 11 }
• Sheep.java
1 public class Sheep implements Animal { 2 3 public Sheep(){ 4 5 System.out.println("Sheep is Made"); 6 7 } 8 9 public Animal makeCopy() { 10 11 System.out.println("Sheep is Being Made"); 12 13 Sheep sheepObject = null; 14 15 try { 16 17 // Calls the Animal super classes clone() 18 // Then casts the results to Sheep 19 20 sheepObject = (Sheep) super.clone(); 21 22 } 23 24 // If Animal didn't extend Cloneable this error 25 // is thrown 26 27 catch (CloneNotSupportedException e) { 28 29 System.out.println("The Sheep was Turned to Mush"); 30 31 e.printStackTrace(); 32 33 } 34 35 return sheepObject; 36 } 37 38 public String toString(){ 39 40 return "Dolly is my Hero, Baaaaa"; 41 42 } 43 44 }
• CloneFactory.java
1 public class CloneFactory { 2 3 // Receives any Animal, or Animal subclass and 4 // makes a copy of it and stores it in its own 5 // location in memory 6 7 // CloneFactory has no idea what these objects are 8 // except that they are subclasses of Animal 9 10 public Animal getClone(Animal animalSample) { 11 12 // Because of Polymorphism the Sheeps makeCopy() 13 // is called here instead of Animals 14 15 return animalSample.makeCopy(); 16 17 } 18 19 }
• TestCloning.java
1 public class TestCloning { 2 3 public static void main(String[] args){ 4 5 // Handles routing makeCopy method calls to the 6 // right subclasses of Animal 7 8 CloneFactory animalMaker = new CloneFactory(); 9 10 // Creates a new Sheep instance 11 12 Sheep sally = new Sheep(); 13 14 // Creates a clone of Sally and stores it in its own 15 // memory location 16 17 Sheep clonedSheep = (Sheep) animalMaker.getClone(sally); 18 19 // These are exact copies of each other 20 21 System.out.println(sally); 22 23 System.out.println(clonedSheep); 24 25 System.out.println("Sally HashCode: " + System.identityHashCode(System.identityHashCode(sally))); 26 27 System.out.println("Clone HashCode: " + System.identityHashCode(System.identityHashCode(clonedSheep))); 28 } 29 30 }
作者:netoxi
出处:http://www.cnblogs.com/netoxi
本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。