目录
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
概述
最近在YouTube上看了一套不错的,同时翻看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 object11 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 objects36 // When we use new we are not being dynamic37 38 EnemyShip ufoShip = new UFOEnemyShip();39 40 doStuffEnemy(ufoShip);41 42 System.out.print("\n");43 44 // -----------------------------------------45 46 // This allows me to make the program more dynamic47 // It doesn't close the code from being modified48 // and that is bad!49 50 // Defines an input stream to watch: keyboard51 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 class88 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 + "\n");13 14 EnemyShip theBoss = MakeUFOs.orderTheShip("UFO BOSS");15 System.out.println(theBoss + "\n");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 parts13 // are based on the String entered. After the ship is made14 // we execute multiple methods in the EnemyShip Object15 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 knows11 // what types of weapons and engines a regular UFO12 // needs. The EnemyShip object is returned & given a name13 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 knows22 // what types of weapons and engines a Boss UFO23 // needs. The EnemyShip object is returned & given a name24 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 ship13 14 public ESWeapon addESGun() {15 return new ESUFOGun(); // Specific to regular UFO16 }17 18 // Defines the engine object to associate with the ship19 20 public ESEngine addESEngine() {21 return new ESUFOEngine(); // Specific to regular UFO22 }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 ship13 14 public ESWeapon addESGun() {15 return new ESUFOBossGun(); // Specific to Boss UFO16 }17 18 // Defines the engine object to associate with the ship19 20 public ESEngine addESEngine() {21 return new ESUFOBossEngine(); // Specific to Boss UFO22 }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 engine18 // when it is printed the String defined in toString goes19 // on the screen20 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 up40 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 ship11 // must have a weapon and engine assigned. That 12 // object also states the specific parts needed13 // to make a regular UFO versus a Boss UFO14 15 public UFOEnemyShip(EnemyShipFactory shipFactory){16 17 this.shipFactory = shipFactory;18 19 }20 21 // EnemyShipBuilding calls this method to build a 22 // specific UFOEnemyShip23 24 void makeShip() {25 26 System.out.println("Making enemy ship " + getName());27 28 // The specific weapon & engine needed were passed in29 // shipFactory. We are assigning those specific part30 // objects to the UFOEnemyShip here31 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 ship11 // must have a weapon and engine assigned. That 12 // object also states the specific parts needed13 // to make a Boss UFO versus a Regular UFO14 15 public UFOBossEnemyShip(EnemyShipFactory shipFactory){16 17 this.shipFactory = shipFactory;18 19 }20 21 // EnemyShipBuilding calls this method to build a 22 // specific UFOBossEnemyShip23 24 void makeShip() {25 26 // TODO Auto-generated method stub27 28 System.out.println("Making enemy ship " + getName());29 30 // The specific weapon & engine needed were passed in31 // shipFactory. We are assigning those specific part32 // objects to the UFOBossEnemyShip here33 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 here11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen14 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 here11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen14 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 here11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen14 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 here11 12 // When the field that is of type ESUFOGun is printed 13 // the following shows on the screen14 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 LinkedListletterList = new LinkedList (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 getLetterList(){ 79 80 return firstInstance.letterList; 81 82 } 83 84 public LinkedList getTiles(int howManyTiles){ 85 86 // Tiles to be returned to the user 87 88 LinkedList tilesToSend = new LinkedList (); 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 requested101 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 object12 13 System.out.println("1st Instance ID: " + System.identityHashCode(newInstance));14 15 // Get all of the letters stored in the List16 17 System.out.println(newInstance.getLetterList());18 19 LinkedListplayerOneTiles = 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 Singleton26 // This doesn't work because the constructor is private27 28 // Singleton instanceTwo = new Singleton();29 30 // Try getting a new instance using getInstance31 32 Singleton instanceTwo = Singleton.getInstance();33 34 // Get unique id for the new instance object35 36 System.out.println("2nd Instance ID: " + System.identityHashCode(instanceTwo));37 38 // This returns the value of the first instance created39 40 System.out.println(instanceTwo.getLetterList());41 42 // Player 2 draws 7 tiles43 44 LinkedList 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 execute13 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 object12 13 System.out.println("1st Instance ID: " + System.identityHashCode(newInstance));14 15 // Get all of the letters stored in the List16 17 System.out.println(newInstance.getLetterList());18 19 LinkedListplayerOneTiles = 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 spec17 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 engineer10 11 RobotEngineer robotEngineer = new RobotEngineer(oldStyleRobot);12 13 // Tell the engineer to make the Robot using the specifications14 // of the OldRobotBuilder class15 16 robotEngineer.makeRobot();17 18 // The engineer returns the right robot based off of the spec19 // sent to it on line 1120 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 Sheep19 20 sheepObject = (Sheep) super.clone();21 22 }23 24 // If Animal didn't extend Cloneable this error 25 // is thrown26 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 Animals14 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 instance11 12 Sheep sally = new Sheep();13 14 // Creates a clone of Sally and stores it in its own15 // memory location16 17 Sheep clonedSheep = (Sheep) animalMaker.getClone(sally);18 19 // These are exact copies of each other20 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
出处:本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。