设计模式 之 原型模式
描述
通过复制现有的对象实例来创建新的对象实例。
使用场景
- 需要clone对象
- 创建对象的成本比较大
实现步骤
1、想要支持对象的clone,对象需要实现 Cloneable
2、并且重写 clone() 方法
代码案例
package com.foruo.learn.designmode.cloneable;
/**
* 案例对象
*
* 想要支持对象的clone,对象需要实现 Cloneable
* 并且重写 clone() 方法
*
* @author GaoYuan
* @date 2018/5/14 上午8:54
*/
public class DemoEntity implements Cloneable{
private String id;
private String name;
private String msg;
public DemoEntity(String msg){
this.msg = msg;
}
public DemoEntity(){}
/**
* 执行clone
* 注意,需要考虑到 浅拷贝 与 深拷贝 的情况
* @author GaoYuan
* @date 2018/5/14 上午8:56
*/
@Override
protected DemoEntity clone(){
DemoEntity demoEntity = null;
try{
demoEntity = (DemoEntity)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return demoEntity;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "DemoEntity{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", msg='" + msg + '\'' +
'}';
}
}
测试代码
package com.foruo.learn.designmode.cloneable;
/**
* 原型 clone写法
* @author GaoYuan
* @date 2018/5/14 上午8:51
*/
public class TestMain {
public static void main(String[] args){
//填写相同不变的数据
DemoEntity demoEntity = new DemoEntity("消息内容");
DemoEntity demo;
int i = 0;
while(i<10){
//执行clone,并填写变化的数据
demo = demoEntity.clone();
demo.setId(""+i);
demo.setName("高元"+i);
System.out.println(demo);
i++;
}
}
}
优缺点
优点:
- 原型模型比直接new一个对象效率高,因为操作的是内存中的二进制流,当复制大对象时,性能的差别就比较明显了。
- 可以循环外预先赋值相同的属性值,而不用循环中重复赋值;
缺点:
- 使用原型模式时不能有final对象。
- Object类的clone方法只会拷贝对象中的基本数据类型,对于数组,引用对象等只能另行拷贝。(需要进行深拷贝)
JDK中的使用场景
例如:
javax.servlet.http.Cookie
package javax.servlet.http;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
public class Cookie implements Cloneable, Serializable {
/**省略了其余代码*/
public Cookie(String name, String value) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
lStrings.getString("err.cookie_name_blank"));
}
if (!isToken(name) ||
name.equalsIgnoreCase("Comment") || // rfc2019
name.equalsIgnoreCase("Discard") || // 2019++
name.equalsIgnoreCase("Domain") ||
name.equalsIgnoreCase("Expires") || // (old cookies)
name.equalsIgnoreCase("Max-Age") || // rfc2019
name.equalsIgnoreCase("Path") ||
name.equalsIgnoreCase("Secure") ||
name.equalsIgnoreCase("Version") ||
name.startsWith("$")) {
String errMsg = lStrings.getString("err.cookie_name_is_token");
Object[] errArgs = new Object[1];
errArgs[0] = name;
errMsg = MessageFormat.format(errMsg, errArgs);
throw new IllegalArgumentException(errMsg);
}
this.name = name;
this.value = value;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
}
}
可以看到最核心的几处地方
- 实现了 Cloneable
- 重写了 clone()
- 也有个和我们写的案例差不多的有参数的构造器
码云
博客
https://my.oschina.net/gmarshal/blog/1811901
欢迎关注我的个人微信订阅号:(据说这个头像程序猿专用)