JAVA设计模式之原型模式
2017-12-13 15:04
387 查看
1. 什么是原型模式?
原型模式(Prototype Pattern)用原型对象指定创建对象的种类,并且通过-拷贝这些原型来创建新的对象。原型模式用于创建重复的对象,同时又能保证性能。原型模式属于创建型模式。
原型模式要求原型对象实现一个“克隆”自身的方法,通过调用这个方法来创建一个新的实例对象。
说到“克隆”就不得不提深克隆和浅克隆,请参考另一片文章《java克隆之深克隆和浅克隆》。
原型模式有两种不同的实现方式:(1)简单形式;(2)登记形式;
登记形式适用于原型对象有多个的情景,将原型对象的管理交给原型管理器(PrototypeManager),原型管理器对象中有一个Map专门用来保存已经创建的原型对象。
2. 角色
简单形式类图
登记形式类图
抽象原型角色(Prototype):可以是一个抽象类或接口,主要定义原型类需要实现的接口方法,一般这个方法为“克隆”方法。
具体原型角色(ConcretePrototype):提供抽象原型角色具体的实现。此角色是用来“克隆”复制的角色。
原型管理器角色(PrototypeManager):此角色只有在登记形式的原型模式才有,主要用一个Map集合来管理ConcretePrototype类,将客户端从原型对象的创建中剥离开来,使客户端不用关心原型对象是如何被创建的。
3. 优点
(1)使用原型模式创建重复对象比用new关键之创建对象性能上要好得多,提高系统性能。(2)简化对象的创建。
4. 缺点
(1)如果使用浅克隆方式实现原型模式,必须要求原型对象实现Cloneable 接口,如果某个原型对象没有实现Cloneable接口则会抛出CloneNotSupportedException异常。(2)如果是采用深克隆实现原型模式,则必须要求所有原型对象支持序列化和反序列化,必须实现Serializable接口。如果某个原型不支持序列化,则不能通过此方式实现原形模式。
5. 使用场景
(1)系统重复创建相同对象时可以考虑使用原型模式。(2)在一个循环体内创建相同对象可以考虑使用原型模式。
(3)通过new关键字创建对象需要复杂的前期准备时可以考虑使用原型模式。
6. 示例代码
以下统一采用登记形式来实现原型模式,并提供“深克隆”和“浅克隆”两种写法。6.1 浅克隆
(1)原型接口类/** *原型公共接口 */ public interface Prototype { public Prototype clone(); }
(2)具体原型类
/** * 具体的原型类A */ public class ConcretePrototypeA implements Prototype,Cloneable { private String name; private int age; public ConcretePrototypeA(String name,int age) { this.name=name; this.age=age; } @Override public Prototype clone() { Prototype prototype=null; try { prototype=(Prototype) super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return prototype; } @Override public String toString() { return "ConcretePrototypeA [name=" + name + ", age=" + age + "]"; } } /** * 具体的原型类B */ public class ConcretePrototypeB implements Prototype,Cloneable { private float height; private float weight; public ConcretePrototypeB(float height,float weight) { this.height=height; this.weight=weight; } @Override public Prototype clone() { Prototype prototype=null; try { prototype=(Prototype) super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return prototype; } @Override public String toString() { return "ConcretePrototypeB [height=" + height + ", weight=" + weight + "]"; } }
(3)原型管理器类
/** * 原型管理类 * 主要用于存在多个原型的情况下。 */ public class PrototypeManager { private static HashMap<String, Prototype> prototypeMap=new HashMap<String,Prototype>(); /** * 获取某个具体原型的克隆对象 */ public static Prototype getClone(String prototypeName){ return prototypeMap.get(prototypeName).clone(); } /** * 初始化原型缓存,将所有原型对象都先初始化以待使用。 */ public static void getPrototypeInstance(){ Prototype A=new ConcretePrototypeA("leitao", 25); Prototype B=new ConcretePrototypeB(5f, 2.5f); prototypeMap.put("ConcretePrototypeA", A); prototypeMap.put("ConcretePrototypeB", B); } }
(4)测试
public class Client { public static void main(String[] args) { //初始化原型对象 PrototypeManager.getPrototypeInstance(); //获得A对象的克隆对象 ConcretePrototypeA A1=(ConcretePrototypeA) PrototypeManager.getClone("ConcretePrototypeA"); ConcretePrototypeA A2=(ConcretePrototypeA) PrototypeManager.getClone("ConcretePrototypeA"); System.out.println("A1="+A1+",A2="+A2); System.out.println("A1==A2:"+(A1==A2)); System.out.println("----------------"); //获得B对象的克隆对象 ConcretePrototypeB B1=(ConcretePrototypeB) PrototypeManager.getClone("ConcretePrototypeB"); ConcretePrototypeB B2=(ConcretePrototypeB) PrototypeManager.getClone("ConcretePrototypeB"); System.out.println("B1="+B1+",B2="+B2); System.out.println("B1==B2:"+(B1==B2)); } }
(5)测试结果
A1=ConcretePrototypeA [name=leitao, age=25],A2=ConcretePrototypeA [name=leitao, age=25] A1==A2:false ---------------- B1=ConcretePrototypeB [height=5.0, weight=2.5],B2=ConcretePrototypeB [height=5.0, weight=2.5] B1==B2:false
6.2 深克隆
(1)原型接口类/** *原型公共接口 */ public interface Prototype { public Prototype clone(); }
(2)具体原型类
/** * person原型类 */ public class Person implements Prototype,Serializable { private static final long serialVersionUID = 3426430684192068358L; private Phone phone; private String name; public Person(Phone phone, String name) { this.phone = phone; this.name = name; } public Phone getPhone() { return phone; } public void setPhone(Phone phone) { this.phone = phone; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Prototype clone() { Prototype prototype=null; try { ByteArrayOutputStream bos=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois=new ObjectInputStream(bis); prototype=(Prototype) ois.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return prototype; } @Override public String toString() { return "Person [phone=" + phone + ", name=" + name + "]"; } } /** * 手机原型类 * 因为此处使用序列化实现深克隆,没有使用Object的clone, * 因此phone对象可以不用实现Prototype接口 */ public class Phone implements Serializable{ private static final long serialVersionUID = -2376123551216737075L; private String number; public Phone(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } @Override public String toString() { return "Phone [number=" + number + "]"; } }
(3)原型管理器类
/** * 原型管理类 * 主要用于存在多个原型的情况下。 */ public class PrototypeManager { private static HashMap<String, Prototype> prototypeMap=new HashMap<String,Prototype>(); /** * 获取某个具体原型的克隆对象 */ public static Prototype getClone(String prototypeName){ return prototypeMap.get(prototypeName).clone(); } /** * 初始化原型缓存,将所有原型对象都先初始化以待使用。 */ public static void getPrototypeInstance(){ Prototype A=new Person(new Phone("123"), "保安"); Prototype B=new Person(new Phone("456"), "门卫"); Prototype C=new Person(new Phone("789"), "保洁"); prototypeMap.put("保安", A); prototypeMap.put("门卫", B); prototypeMap.put("保洁", C); } }
(4)测试
public class Client { public static void main(String[] args) { //初始化原形对象 PrototypeManager.getPrototypeInstance(); Person A1= (Person) PrototypeManager.getClone("保安"); Person A2=(Person) PrototypeManager.getClone("保安"); System.out.println("A1="+A1+",A2="+A2); System.out.println("A1==A2:"+(A1==A2)); System.out.println("----------------"); A1.getPhone().setNumber("852"); System.out.println("当A1更改自己的电话号码的时候,不影响A2的电话号码:"); System.out.println("A1="+A1+",A2="+A2); System.out.println("A1==A2:"+(A1==A2)); System.out.println("----------------"); Person B=(Person) PrototypeManager.getClone("保洁"); Person C=(Person) PrototypeManager.getClone("门卫"); System.out.println("B="+B+",C="+C); System.out.println("B==C:"+(B==C)); } }
(5)测试结果
A1=Person [phone=Phone [number=123], name=保安],A2=Person [phone=Phone [number=123], name=保安] A1==A2:false ---------------- 当A1更改自己的电话号码的时候,不影响A2的电话号码: A1=Person [phone=Phone [number=852], name=保安],A2=Person [phone=Phone [number=123], name=保安] A1==A2:false ---------------- B=Person [phone=Phone [number=789], name=保洁],C=Person [phone=Phone [number=456], name=门卫] B==C:false
参考文章http://www.runoob.com/design-pattern/prototype-pattern.html
http://www.cnblogs.com/java-my-life/archive/2012/04/11/2439387.html
【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】
相关文章推荐
- Java 设计模式——原型模式(Prototype)
- iOS与java原型设计模式对比
- Java设计模式之原型模式(Prototype模式)介绍
- java设计模式之原型模式
- java设计模式之原型模式
- Java设计模式之从[魔兽世界副本]分析原型(Prototype)模式
- [译]Java 设计模式之原型
- java设计模式——原型模式(Prototype)
- java设计模式学习笔记--原型模式(浅克隆和深克隆)
- java设计模式3.建造者模式、原型模式
- java设计模式---prototype(原型)模式
- 【java设计模式】原型模式
- Java设计模式菜鸟系列(十六)原型模式建模与实现
- Java设计模式:Prototype(原型)
- Java设计模式之——原型模式
- Java设计模式之原型模式
- Java设计模式(5)创建型:原型模式
- java-设计模式-创建模式-原型模式prototype
- java设计模式(工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式、适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式,。 行为型模式,共十一种:策略模式、模板方法)