JAVA设计模式---原型模式

来源:互联网 发布:php公开课 编辑:程序博客网 时间:2024/05/17 03:46

原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。这就是选型模式的用意。

原型模式分为⑴简单形式⑵登记形式

原型模式可以是深克隆也可以是浅克隆。

1.简单形式的原型模式


⑴Client:客户端请求

⑵Prototype:这是一个抽象角色,通常是JAVA接口或JAVA抽象类

⑶ConcretePrototype:被复制的对象,需要实现Prototype接口

举个栗子:

大学有一个学霸,大家都要抄他作业,

这个类是作业的抽象父类,定义了一些作业都要实现的方法。

package com.designpattern.prototype1;public abstract class Homework implements Cloneable {    public abstract Object clone();    public abstract void show();}
数学作业的类要实现自己的复制逻辑,因为数学作业和编程作业的抄袭的方法肯定是不一样的。
package com.designpattern.prototype1;import java.util.Date;public class MathHomework extends Homework{    /**     * 这里只是用一个日期类来表示一下深度复制     */    private Date A = new Date();    private int a = 1;    public void show() {        System.out.println("Math clone");    }    /**     * 实现自己的克隆方法     */    public Object clone(){        MathHomework m = null;        /**         * 深度复制         */        m = (MathHomework) this.clone();        m.A = (Date)this.getA().clone();        return m;    }    public Date getA(){        return A;    }}
⑶客户端就可以使用学霸的作业抄袭了

package com.designpattern.prototype1;public class Main {    public static void main(String[] args){        /**         * 建立一个学霸,全班同学的作业就靠他了         */        MathHomework xueba = new MathHomework();        /**         * 学渣都是从学霸那复制来的         */        MathHomework xuezha = (MathHomework)xueba.clone();        xuezha.show();    }
2.登记形式
作为原型模式的第二种形式,它多了一个原型管理器(PrototypeManager)角色,该角色的作用是:创建具体原型类的对象,并记录每一个被创建的对象。


接口:

package protype2;public interface Prototype {public Prototype clone();    public String getName();    public void setName(String name);}
ConcretePrototype1:

package protype2;public class ConcretePrototype1 implements Prototype {private String name;    public Prototype clone(){        ConcretePrototype1 prototype = new ConcretePrototype1();        prototype.setName(this.name);        return prototype;    }    public String toString(){        return "Now in Prototype1 , name = " + this.name;    }    @Override    public String getName() {        return name;    }    @Override    public void setName(String name) {        this.name = name;    }}
ConcretePrototype2:
package protype2;public class ConcretePrototype2 implements Prototype {    private String name;    public Prototype clone(){        ConcretePrototype2 prototype = new ConcretePrototype2();        prototype.setName(this.name);        return prototype;    }    public String toString(){        return "Now in Prototype2 , name = " + this.name;    }    @Override    public String getName() {        return name;    }    @Override    public void setName(String name) {        this.name = name;    }}
管理器(就一个hashmap):

package protype2;import java.util.HashMap;import java.util.Map;public class PrototypeManager {/**     * 用来记录原型的编号和原型实例的对应关系     */    private static Map<String,Prototype> map = new HashMap<String,Prototype>();    /**     * 私有化构造方法,避免外部创建实例     */    private PrototypeManager(){}    /**     * 向原型管理器里面添加或是修改某个原型注册     * @param prototypeId 原型编号     * @param prototype    原型实例     */    public synchronized static void setPrototype(String prototypeId , Prototype prototype){        map.put(prototypeId, prototype);    }    /**     * 从原型管理器里面删除某个原型注册     * @param prototypeId 原型编号     */    public synchronized static void removePrototype(String prototypeId){        map.remove(prototypeId);    }    /**     * 获取某个原型编号对应的原型实例     * @param prototypeId    原型编号     * @return    原型编号对应的原型实例     * @throws Exception    如果原型编号对应的实例不存在,则抛出异常     */    public synchronized static Prototype getPrototype(String prototypeId) throws Exception{        Prototype prototype = map.get(prototypeId);        if(prototype == null){            throw new Exception("您希望获取的原型还没有注册或已被销毁");        }        return prototype;    }}
Client:
package protype2;public class Client {  public static void main(String[]args){        try{                                       Prototype p1 = new ConcretePrototype1();            PrototypeManager.setPrototype("p1", p1);            //获取原型来创建对象            Prototype p11 = PrototypeManager.getPrototype("p1").clone();            p11.setName("张三");            System.out.println("第一个实例:" + p11);                                    //有人动态的切换了实现            Prototype p2 = new ConcretePrototype2();            PrototypeManager.setPrototype("p2", p2);            //重新获取原型来创建对象            Prototype p22 = PrototypeManager.getPrototype("p2").clone();            p22.setName("李四");            System.out.println("第二个实例:" + p22);                                                                   //有人注销了这个原型            PrototypeManager.removePrototype("p1");            //再次获取原型来创建对象            Prototype p5 = PrototypeManager.getPrototype("p1").clone();            p5.setName("王五");            System.out.println("第三个实例:" + p5);        }catch(Exception e){            e.printStackTrace();        }    }}

输出:

第一个实例:Now in Prototype1 , name = 张三第二个实例:Now in Prototype2 , name = 李四java.lang.Exception: 您希望获取的原型还没有注册或已被销毁at protype2.PrototypeManager.getPrototype(PrototypeManager.java:39)at protype2.Client.main(Client.java:31)


3.两种模式的区别

如果需要创建的原型对象数目较少而且比较固定的话,可以采取第一种形式。在这种情况下,原型对象的引用可以由客户端自己保存。
如果要创建的原型对象数目不固定的话,可以采取第二种形式。在这种情况下,客户端不保存对原型对象的引用,这个任务被交给管理员对象。在复制一个原型对象之前,客户端可以查看管理员对象是否已经有一个满足要求的原型对象。如果有,可以直接从管理员类取得这个对象引用;如果没有,客户端就需要自行复制此原型对象。









原创粉丝点击