想升职加薪,Java开发者应学习原型设计模式的要点

原型模式是指通过拷贝原型对象创建新的对象,它在23种设计模式中相对来说简单一些。

原型模式的核心在于拷贝原型对象,JDK的实现拷贝的方式是直接基于内存二进制流进行拷贝,无需再经历耗时的对象初始化过程,性能提升很多。

拷贝的目的是避免复杂的属性赋值和耗时的对象构建。下面来看原型模式的类结构图

想升职加薪,Java开发者应学习原型设计模式的要点

原型模式类结构图

从上面的UML图中,我们可以发现原型模式主要包含3个角色:

  • 客户(Client):客户类提出创建对象的请求
  • 抽象原型(ProtoType):规定拷贝接口
  • 原型实现类:(ConcreteProtoType):能被拷贝的对象

相信大家,曾经看到过下面的代码:

想升职加薪,Java开发者应学习原型设计模式的要点

示例代码

这样的代码虽然工整,命名也规范,注释可能写的也全面。这就是原型模式的产生的需求场景。它能帮我解决什么问题呢?

原型模式的需求场景:

1、类初始化消耗资源较多

2、new 产生的一个对象需要繁琐的过程(数据准备,权限访问等)

3、构造函数复杂

4、循环体中产生大量对象时

在 Spring 框架中,原型模式应用非常广泛。例如 scope = "prototype" ,在我们经常用的JSON.parseObject() 也是一种原型模式。

原型模式的Java实现方式可以分2种:浅拷贝和深拷贝。

浅拷贝

<code>@Data
public class User implements Cloneable {

private int age;
private String name;
private List<string> hobbies;

@override
public User clone(){

try {

return (User)super.clone();
} catch (Exception e) {
//TODO: handle exception
return null;
}
}
}/<string>/<code>

通过实现Cloneable接口的Clone() 方法得到拷贝类,改变原型对象age,String值,拷贝对象不会跟着改变,相互独立。但是细心的朋友会发现,调用原型对象hobbies.add()方法添加新元素,拷贝对象的hobbies也会跟着变化。这是为什么呢? 这是因为List<string>属于引用类型成员变量,虽然拷贝形成了新的变量,但是指向的还是内存推中的原List对象。/<string>

深拷贝

<code>@Data
public class User implements Cloneable {

private int age;
private String name;
private List<string> hobbies;

@override
public User clone(){

try {
return (User)super.clone();
} catch (Exception e) {
//TODO: handle exception
return null;
}
}

//clone接口
public User DeepClone(){
try {
User newUser = this.clone();
newUser.hobbies = (List)((ArrayList)newUser.hobbies).clone();
rerurn newUser;
} catch (Exception e) {

//TODO: handle exception
}
}

//反序列化
public User DeepClone2(){
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeeObject(this);

ByteArraryInputStream bis = new ByteArraryInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (User)ois.readObject();
} catch (Exception e) {
//TODO: handle exception
}
}
}/<string>/<code>

有兴趣的朋友可以分别测试deepClone() 和 deepClone2() 方法,都可以实现深度克隆。

通过反序列化可以实现对象深度克隆这个很容易理解。但是对ArrayLis<string>变量做clone(),为什么也能实现深度克隆,我们看一下ArrayList源代码自然就明白了。/<string>

想升职加薪,Java开发者应学习原型设计模式的要点

ArrayList克隆方法

我们发现ArrayList遍历了所有元素,被进行了copy。

总结原型模式

优点:

1、java自带原型模式基于内存二进制流拷贝,比直接new一个对象性能提升很多

2、可以使用深度克隆保存对象的状态,简化创建对象的过程

缺点:

1、需要为每个类配置克隆方法

2、克隆方法位于类的内部,修改代码违背开闭原则


分享到:


相關文章: