我理解的原型模式就是将对象都创建好并且缓存下来,当你需要其中的对象的时候直接clone下来,不需要new这个过程。
想要不经历new这个过程就创建对象其中之一的方法就是在堆内存中直接复制对象也就是clone方法,也就是原型模式
但是其中很多细节
(1)首先定义基类的时候要继承Cloneable接口,重写其中的clone方法,但是clone方法返回的并不是你想要的Item类,所以强制转换也是其中的一个细节
1 public abstract class Item implements Cloneable {//1 2 private String ketId; 3 protected String itemName; 4 5 public String getKetId() { 6 return ketId; 7 } 8 9 public void setKetId(String ketId) { 10 this.ketId = ketId; 11 } 12 13 public String getItemName() { 14 return itemName; 15 } 16 public Item clone(){//2 17 try { 18 return (Item) super.clone();//3 19 } catch (CloneNotSupportedException e) { 20 e.printStackTrace(); 21 } 22 return null; 23 } 24 25 }
(2)然后定义两个继承了Item的派生类
Adidas
1 public class Adidas extends Item { 2 public Adidas(){ 3 this.itemName = "Adidas"; 4 } 5 }
Nike
1 public class Nike extends Item { 2 public Nike(){ 3 this.itemName = "Nike"; 4 } 5 }
(3)然后定义缓存类
缓存类里面用一个HashTable来作为存储方式
1 public class ItemCache { 2 private static Hashtable<String, Item> itemMap = 3 new Hashtable<String,Item>(); 4 5 public static Item getItem(String keyId){ 6 Item item = itemMap.get(keyId); 7 return (Item) item.clone(); 8 } 9 //缓存方法 10 public static void addItem(){ 11 Adidas adidas = new Adidas(); 12 adidas.setKetId("1"); 13 itemMap.put( adidas.getKetId(), adidas); 14 15 Nike nike = new Nike(); 16 nike.setKetId("2"); 17 itemMap.put(nike.getKetId(), nike); 18 } 19 20 }
(4)测试类
首先要先进行缓存,也就是调用缓存类中的缓存方法,还有HashTable查询出来的兑现也要强制转换
1 public class PrototypeDemo {
2 public static void main(String[] args) {
3 ItemCache.addItem();//1
4
5 Adidas adidas = (Adidas) ItemCache.getItem("1");//2
6 System.out.println("Adidas:" + adidas.getItemName());
7 }
8 }
原型模式的弱引用问题
如果一个对象是你要clone对象的成员变量,当你clone这个对象之后该成员变量的实例化问题就是弱引用
下面是实验代码
成员变量类,name来标识这个类
1 public class SecondDemo { 2 public String name; 3 4 5 public String getName() { 6 return name; 7 } 8 9 public void setName(String name) { 10 this.name = name; 11 } 12 13 }
引用类
1 public class FirstDemo implements Cloneable { 2 SecondDemo secondDemo = new SecondDemo(); 3 4 public void setName (String name){ 5 this.secondDemo.setName(name); 6 } 7 @Override 8 public FirstDemo clone(){ 9 FirstDemo firstDemo = null; 10 try { 11 firstDemo =(FirstDemo)super.clone(); 12 } catch (CloneNotSupportedException e) { 13 e.printStackTrace(); 14 } 15 return firstDemo; 16 } 17 }
测试类
1 public class CiteDemo { 2 public static void main(String[] args) { 3 FirstDemo firstDemo = new FirstDemo(); 4 firstDemo.setName("second"); 5 FirstDemo firstDemo1 = firstDemo.clone(); 6 System.out.println(firstDemo.secondDemo.getName());//second 7 System.out.println(firstDemo1.secondDemo.getName());//second 8 } 9 }
实验证明clone出来的类还是原来的Second类,所以不会对其进行重新实例化,同时数组字段同样是弱引用,只有基本数据类型可以重新创建。