介绍
用原型实例指定创建对象的种类,并且通过复制原型已有的对象用于创建新的对象。
理解
原型实例便是我们需要复制的类的实例,原型说的是可以被复制的那个对象。这是一种构建实例的方式,用于对对象进行复制,而形成一个新的实例。
我们知道Obejct
对象的clone()
方法可以对对象进行克隆,但是clone()
方法是protected
类型的,protected
类型的访问权限是:同一个类、同一个包、不同包的子类,而不允许不包的非子类访问。实际上,所有的类都会潜在的继承Object类,所以均是Object的子类,那么在所有类的内部均可以直接调用clone()
方法,或者重写该方法,让其支持在其他类中调用。
但是,clone()
方法并不能执行成功,而是会报出java.lang.CloneNotSupportedException
。其实在clone()
方法的源码中解释了这个原因。
如果对象的类不支持 Cloneable 接口。重写 clone 方法的子类也会抛出此异常,表示实例无法被克隆。
所以需要实现Cloneable
接口。
实现步骤:
- 创建原型
- 实现
Cloneable
接口 - 重写
clone()
方法
实现
以发邮件作为例子,通原型模式,减少邮件实例的创建时间。
Email类
package cn.sh.designepattern;
/**
* @Author song
* @Version 0.0.1
* @Date 2025/5/6 10:49
* @Contact 643947568@qq.com
*/
public class Email implements Cloneable{
private String receiver;
private String sender;
private String subject;
private String content;
public Email(String subject, String content) {
this.content = content;
this.subject = subject;
}
//重要-------------------!!!------------
@Override
public Email clone() {
try {
Email clone = (Email) super.clone();
// TODO: copy mutable state here, so the clone can't change the internals of the original
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
测试
package cn.sh.designepattern;
/**
* @Author song
* @Version 0.0.1
* @Date 2025/5/6 10:42
* @Contact 643947568@qq.com
*/
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Email email = new Email("活动通知", "会员88折,截止时间5月1日");
Email clone = email.clone();
System.out.println(email.hashCode());
System.out.println(clone.hashCode());
for (int i = 0; i < 10; i++) {
Email clone1 = email.clone();
clone1.setSender("test");
clone1.setReceiver("接收方:" + i);
System.out.println("发送邮件" + clone1);
}
}
}
效果
990368553
1096979270
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:0', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:1', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:2', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:3', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:4', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:5', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:6', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:7', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:8', sender='test', subject='活动通知'}
发送邮件Email{content='会员88折,截止时间5月1日', receiver='接收方:9', sender='test', subject='活动通知'}
应用
原型模式可能很容易的创建一个对象的许多个实例,在实际运用中,对于需要new出很多个相同类型对象的情况,比较实用。