想升職加薪,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、克隆方法位於類的內部,修改代碼違背開閉原則


分享到:


相關文章: