设计模式7-原型模式

来源:互联网 发布:黑客帝国文字矩阵 编辑:程序博客网 时间:2024/06/08 11:10

    原型模式其实是利用对象克隆来实现的,相对而言比较简单,使用克隆可以节约大量的资源。下面使用银行发对账单的邮件的例子,类图如下:



    类图中AdvTemplate是广告信的模板,一般都是从数据库取出;Mail类是一封邮件类。

   广告信模板代码如下:

package com.jack.prototype;/** * Created by jack on 2017/8/3. * 广告信模板 */public class AdvTemplate {    //广告信名称    private String advSubject = "招商银行信用卡活动";    //广告信内容    private String advContext = "将举行国庆抽奖活动,消费满100,送10000000积分";    public String getAdvSubject() {        return advSubject;    }    public void setAdvSubject(String advSubject) {        this.advSubject = advSubject;    }    public String getAdvContext() {        return advContext;    }    public void setAdvContext(String advContext) {        this.advContext = advContext;    }}


邮件类代码如下:

package com.jack.prototype;/** * Created by jack on 2017/8/3. * 邮件类 */public class Mail implements Cloneable{    /**     * 收件人     */    private String receiver;    /**     * 邮件名称     */    private String subject;    /**     * 称谓     */    private String appellation;    /**     * 邮件内容     */    private String context;    /**     * 邮件尾部     */    private String tail;    /**     * 构造函数     * @param advTemplate     */    public Mail(AdvTemplate advTemplate){        this.context = advTemplate.getAdvContext();        this.subject = advTemplate.getAdvSubject();    }    public String getReceiver() {        return receiver;    }    public void setReceiver(String receiver) {        this.receiver = receiver;    }    public String getSubject() {        return subject;    }    public void setSubject(String subject) {        this.subject = subject;    }    public String getAppellation() {        return appellation;    }    public void setAppellation(String appellation) {        this.appellation = appellation;    }    public String getContext() {        return context;    }    public void setContext(String context) {        this.context = context;    }    public String getTail() {        return tail;    }    public void setTail(String tail) {        this.tail = tail;    }    @Override    protected Mail clone() throws CloneNotSupportedException {        Mail mail = null;        try {            mail = (Mail) super.clone();        }catch (Exception e){            e.printStackTrace();        }        return mail;    }}


测试邮件发送的代码如下:

package com.jack.prototype;import java.util.Random;/** * Created by jack on 2017/8/3. */public class MainTest4 {    public static void main(String[] args) throws CloneNotSupportedException {        int maxCount = 8;        int i = 0;        //把模板定义出来        Mail mail = new Mail(new AdvTemplate());        mail.setTail("招商银行版权所有");        while (i < maxCount) {            //使用克隆,原型模式            Mail cloneMail = mail.clone();            //下面时每个邮件不同的地方            cloneMail.setAppellation(getRandString(5)+"先生(女生)");            cloneMail.setReceiver(getRandString(5)+"@"+getRandString(8));            //发送邮件            sendMail(cloneMail);            i++;        }    }    /**     * 发送邮件     * @param mail     */    public static void sendMail(Mail mail){        System.out.println("标题:"+mail.getSubject()+"\t收件人:"+mail.getReceiver()+"\t....发送成功!!!");    }    /**     * 获得指定长度的随机字符串     * @param maxLength     * @return     */    public static String getRandString(int maxLength){        String source = "abcdefghijklmnopqrstuvwxyz";        StringBuffer sb = new StringBuffer();        Random random = new Random();        for (int i = 0 ;i < maxLength;i++){            sb.append(source.charAt(random.nextInt(source.length())));        }        return sb.toString();    }}


   测试程序输入如下:

标题:招商银行信用卡活动收件人:ytbyi@imyjuipe....发送成功!!!标题:招商银行信用卡活动收件人:covuz@zogjxyji....发送成功!!!标题:招商银行信用卡活动收件人:xauak@ehpvnkic....发送成功!!!标题:招商银行信用卡活动收件人:vqere@enrhzmgk....发送成功!!!标题:招商银行信用卡活动收件人:bepne@fxjheubf....发送成功!!!标题:招商银行信用卡活动收件人:lihni@zlsjrspk....发送成功!!!标题:招商银行信用卡活动收件人:pgzro@aipappjy....发送成功!!!标题:招商银行信用卡活动收件人:frwcr@juhqjlql....发送成功!!!


   上面使用了克隆技术,也就是原型模式,因为发送邮件一般是多线程的,进行发送邮件的过程中里面的信息可能随时改变,利用克隆技术可以拷贝对象的复制,改变不影响原对象。这种不通过new关键字产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。原型模式的核心就是clone方法,该方法是Object类里面的方法,通过该方法进行对象的拷贝,通过Cloneable接口来表示这个对象是可拷贝的。在JVM中具有这个标记的对象才有可能被拷贝。那怎么才能从有可能拷贝转换为可以被拷贝呢?方法是覆盖clone方法。


    原型模式的优点:

1,性能优良,原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好的体现其优点。

2,逃避构造函数的约束,者既是优点又是缺点,直接在内存中拷贝,构造函数不会执行。优点就是减少了约束,缺点也就是减少了约束,需要大家在实际应用时考虑。

  

原型模式的使用场景:

1,自由优化场景,类初始化需要消化非常多的资源

2,性能和安全要求的场景,通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式

3,一个对象多个修改者的场景,一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用