Java設計模式之原型模式詳細解讀
一、介紹
原型模式屬于創(chuàng)建型設計模式,用于創(chuàng)建重復的對象,且同時又保證了性能。
該設計模式的好處是將對象的創(chuàng)建與調用方分離。
其目的就是**根據(jù)一個對象(稱為原型)創(chuàng)建一個與其完全相同的對象(當然內(nèi)存地址不同)。**原對象被認為是新對象的原型。
二、實現(xiàn)步驟
原型模式的實現(xiàn)步驟如下:
- 應用原型模式的類要實現(xiàn)Cloneable接口。
- 應用原型模式的類要重寫Object類定義的clone()方法。
- 通過調用對象的clone()方法,獲得一個與該對象相同的對象。
在重寫Object類定義的clone()方法時,直接通過調用super.clone()即可得到一個新對象,如下所示
@Override public Object clone() { try { Object obj = super.clone(); return obj; } catch (CloneNotSupportedException e) { throw new AssertionError(); } }
而super.clone()調用的其實就是在Object類中定義的方法
public class Object { // ... protected native Object clone() throws CloneNotSupportedException; // ... }
該方法由native關鍵字修飾,表明其具體實現(xiàn)邏輯在JVM中已經(jīng)完成了,我們無需知道其細節(jié),只需知道調用該方法后將返回一個具有相同屬性的對象即可。也正因此,該方式要比我們創(chuàng)建實例再初始化實例的性能好。
另外,該方法顯式地拋出了CloneNotSupportedException異常,要求我們在調用clone()方法的對象必須實現(xiàn)Cloneable接口,否則將拋出該異常。
注意:調用super.clone()時,只能夠滿足淺拷貝,如果要實現(xiàn)深拷貝,則需要我們根據(jù)實際情況重寫clone()的具體邏輯而不是調用super.clone()。
三、案例
我們創(chuàng)建一個Person類,實現(xiàn)Cloneable接口,并重寫clone()方法。
public class Person implements Cloneable{ private String name; private Integer age; private String sex; // 省略get、set方法 @Override public Person clone() { try { Person person = (Person) super.clone(); return person; } catch (CloneNotSupportedException e) { throw new AssertionError(); } } }
然后進行測試
public class PrototypeTest { public static void main(String[] args) { Person person = new Person(); person.setName("name"); person.setAge(1); person.setSex("男"); Person clone = person.clone(); System.out.println("獲得的新對象:" + clone); } }
得到的輸出如下,可以發(fā)現(xiàn),通過clone()方法可以獲得一個與原對象具有相同屬性的新對象。
四、應用
原型模式在實際應用中不是很廣泛,因為絕大多數(shù)實例要么是有狀態(tài)的(例如持有文件、遠程鏈接等),則無法應用原型模式;要么是無狀態(tài)的,此時應用單例模式更合適。
思來想去,基于原型模式創(chuàng)建重復對象的作用,我們可以利用該模式模擬細胞分裂。
五、細胞分裂
按照上面案例,我們新建一個細胞類Cell
public class Cell implements Cloneable{ // 當前細胞為第num次分裂所得,細胞分裂是一個1變2,2變4,4變8的過程, private Integer num = 0; @Override public Cell clone() { try { // 每當克隆一次,num+1 num++; Cell clone = (Cell) super.clone(); return clone; } catch (CloneNotSupportedException e) { throw new AssertionError(); } } }
演示細胞分裂過程
public static void cellDivision() { // 第一個細胞 Cell cell1 = new Cell(); System.out.println("cell1:" + cell1); // cell1 通過自我復制, 產(chǎn)生一個新細胞 cell2 Cell cell2 = cell1.clone(); System.out.println("第一次分裂后:"); System.out.println("cell1:" + cell1); System.out.println("cell2:" + cell2); // cell1、cell2 通過自我復制, 產(chǎn)生新細胞 cell3、cell4 Cell cell3 = cell1.clone(); Cell cell4 = cell2.clone(); System.out.println("第二次分裂后:"); System.out.println("cell1:" + cell1); System.out.println("cell2:" + cell2); System.out.println("cell3:" + cell3); System.out.println("cell4:" + cell4); }
輸出如下:
此時如果要計算當前一共有多少個細胞,就可以通過 2 n u m 2^{num} 2num得到結果。
六、改造細胞分裂邏輯
我們將N個細胞(無論分裂多少次)作為一個整體,假設該整體中所有細胞同時分裂,則可以將該細胞整體進行抽象。如下所示,新建一個細胞整體類Cells。
- 實現(xiàn)Cloneable接口,表示該細胞整體可進行復制分裂。
- 重寫clone()方法,該細胞整體分裂的過程,其實就是所有個體在分裂,最后將其整合即可
public class Cells implements Cloneable{ // 該細胞整體中的所有細胞個體 private List<Cell> cellList = new ArrayList<>(); // 添加一個細胞 public void addCell(Cell cell) { cellList.add(cell); } // 該細胞整體復制分裂的過程 @Override public Cells clone() { try { System.out.println("第" + (cellList.get(0).getNum()+1) + "次分裂..."); // 新增的細胞數(shù)量和原細胞數(shù)量相同 List<Cell> clonedCellList = new ArrayList<>(cellList.size()); for (Cell cell : cellList) { // 將每一個細胞分裂得到的新細胞添加到clonedCellList集合中 clonedCellList.add(cell.clone()); } // 新細胞與原細胞合并 cellList.addAll(clonedCellList); // 復制該細胞整體 Cells clone = (Cells) super.clone(); clone.setCellList(cellList); System.out.println("分裂后得到細胞數(shù):" + cellList.size()); return clone; } catch (CloneNotSupportedException e) { throw new AssertionError(); } } }
下面我們對該細胞整體的分裂過程進行演示
public static void cellDivision() { // 第一個細胞 Cell cell = new Cell(); // 向該細胞整體中添加第一個細胞 Cells cells = new Cells(); cells.addCell(cell); // 細胞分裂10次 for (int i = 0; i < 10; i++) { cells = cells.clone(); } }
輸出如下:
七、總結
- 原型模式用于創(chuàng)建具有相同屬性的重復對象。
- 原型模式的實現(xiàn)就是實現(xiàn)Cloneable接口 + 重寫clone()方法實現(xiàn)的。
- Object類的clone()方法實現(xiàn)由JVM實現(xiàn),性能較好。但僅能實現(xiàn)淺拷貝。
到此這篇關于Java設計模式之原型模式詳細解讀的文章就介紹到這了,更多相關Java原型模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot?Web開發(fā)之請求響應、分層解耦問題記錄
在?Spring?Boot?的?Web?請求響應處理中,Servlet?起著關鍵的作用,Servlet?是?Java?Web?開發(fā)中的基本組件,主要負責處理客戶端的請求并生成響應,這篇文章主要介紹了SpringBoot?Web開發(fā)之請求響應,分層解耦,需要的朋友可以參考下2024-08-08