Java开发中一般情况下通过使用new 关键字创建对象,但是有时也会在“不指定类名的前提下生成实例”的需求:
对象种类繁多,无法将它们整合到一个类中时
需要处理的对象太多,如果将它们分别作为一个类,需要编写的类文件太多。
难以根据类生成实例时
生成实例的过程太复杂,很难根据类来生成实例。
想解耦框架与生成的实例时
想让生成实例的框架不依赖与具体的类,这时就不能指定类名来生成实例,而要事先“注册”一个“原型”实例,然后通过复制该实例来生成新的实例。
学习根据实例来生成实例的Prototype模式。
在Java语言中可以通过clone的方式创建实例的副本。
实现Cloneable接口的类的实例可以调用clone方法进行复制,clone方法的返回值是复制出来的新的实例。
(clone方法内部所进行的处理是分配与要复制的实例同样大小的内存空间,接着将要复制的实例中的字段的值复制到所要分配的内存空间中去)
角色:
Prototype原型:负责定义用于复制现在实例来生成实例的方法,本示例中,Product来扮演。
ConcretePrototype具体的原型:负责实现用于复制现在实例来生成实例的方法,本示例中, MessageBox与UnderLinePen类来扮演。
client使用者:负责使用复制实例的方法生成实例,本示例中,Manager来扮演。
优点:
不用根据类来生成实例。
作为组件复用,一旦代码中出现要使用的类的名称,就无法与该类分离开来,也就无法实现复用。
代码:
public interface Product extends Cloneable { public abstract void use(); public abstract Product createClone(); }
public class UnderLinePen implements Product { @Override public void use() { System.out.println("使用UnderLinePen"); } @Override public Product createClone() { Product p = null; try { p = (Product) clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } }
public class MessageBox implements Product { @Override public void use() { System.out.println("使用MessageBox"); } @Override public Product createClone() { Product p = null; try { p = (Product) clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } }
public class Manager { private HashMap<String,Object> registerMap = new HashMap<>(); public void register(String className,Product product) { registerMap.put(className,product); } public Product create(String prototypeName) { Product p = (Product) registerMap.get(prototypeName); return p.createClone(); } }
public class Main { public static void main(String[] args) { Manager manager = new Manager(); manager.register("message",new MessageBox()); manager.register("underLine",new UnderLinePen()); Product message = manager.create("message"); message.use(); Product underLine = manager.create("underLine"); underLine.use(); } }
结果:
使用MessageBox
使用UnderLinePen