深入了解设计模式之原型模式(一)

假设我们需要做一个邮件发送系统,发送给银行客户的人,具体类图如下:

 具体代码实例如下:

Mail:

public class Mail {
    private String receiver;
    private String subject;
    private String appellation;
    private String context;
    private String tail;
    public Mail(AdvTemplate advTemplate){
        this.subject = advTemplate.getAdvSubject();
        this.context = advTemplate.getAdvContext();
    }

    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;
    }

AdvTemplate:

public class AdvTemplate {
    private String advSubject = "老许抽奖活动";
    private String advContext = "抽奖就送100w";

    public String getAdvContext() {
        return advContext;
    }

    public String getAdvSubject() {
        return advSubject;
    }
}

测试类如下:

public class Client {
    private static final int MAX_COUNT = 6;
    public static void main(String[] args) {
        int i  = 0;
        mail.setTail("老许版权所有...");
        while ( i < MAX_COUNT ){
            Mail mail = new Mail(new AdvTemplate());
            mail.setReceiver(getRandomString(5)+"@"+getRandomString(8)+".com");
            mail.setAppellation(getRandomString(5)+"先生(女士)");
            i++;
            sendEmail(mail);
        }
    }

    public static void sendEmail(Mail mail){
        System.out.println("标题"+mail.getSubject()+"\t收件人"+mail.getReceiver()+"\t发送成功...");
    }
    public static String getRandomString(int num){
        String source ="abcdefghijklmnopqrskuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < num; i++) {
            sb.append(source.charAt(random.nextInt(source.length())));
        }
        return sb.toString();
    }
}

测试结果如下:

 

由于是随机数,每次运行都有所差异,不管怎么样,我们这个发送程序是编写出来了,也能正常发送。我们再来仔细地想想,这个程序是否有问题?Look here,这是一个线程在运行,也就是你发送的是单线程的,那按照一封邮件发出去需要0.02秒(够小了,你还要到数据库中取数据呢),600万封邮件需要33个小时,也就是一个整天都发送不完,今天的没发送完,明天的账单又产生了,日积月累,激起甲方人员一堆抱怨,那怎么办?

好办,把sendMail修改为多线程,但是只把sendMail修改为多线程还是有问题的呀,产生第一封邮件对象,放到线程1中运行,还没有发送出去;线程2也启动了,直接就把邮件对 象mail的收件人地址和称谓修改掉了,线程不安全了。说到这里,你会说这有N多种解决办 法,其中一种是使用一种新型模式来解决这个问题:通过对象的复制功能来解决这个问题, 类图稍做修改:

 我们来看修改后的邮件类:

public class Mail implements Cloneable{
    private String receiver;
    private String subject;
    private String appellation;
    private String context;
    private String tail;
    public Mail(AdvTemplate advTemplate){
        this.subject = advTemplate.getAdvSubject();
        this.context = advTemplate.getAdvContext();
    }

    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() {
        Mail mail = null;
        try {
             mail = (Mail)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return mail;
    }
}

修改后的场景类:

 public static void main(String[] args) {
        Mail mail = new Mail(new AdvTemplate());
        int i  = 0;
        mail.setTail("老许版权所有...");
        while ( i < MAX_COUNT ){
            Mail clone = mail.clone();
            clone.setReceiver(getRandomString(5)+"@"+getRandomString(8)+".com");
            clone.setAppellation(getRandomString(5)+"先生(女士)");
            i++;
            sendEmail(mail);
        }
    }

把对象复制一份,产生一个新的对象,和原有对象一样,然后再修改细节的数据,如设置称谓、设置收件人地址等。这种不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。

原型模式定义:

原型模式(Prototype Pattern)的简单程度仅次于单例模式和迭代器模式。正是由于简单,使用的场景才非常地多,其定义如下:

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)

原型模式通用源码:

public class PrototypeClass implements Cloneable{ 
//覆写父类Object方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null; 
try {
prototypeClass = (PrototypeClass)super.clone(); 
} catch (CloneNotSupportedException e) {
return prototypeClass;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有个金丝熊叫老许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值