5、原型模式
通過復制現有對象來創建新對象,避免從零開始構建,就像 “復印文件” 一樣。
克隆的核心是復用現有對象狀態
用 克隆熊貓 舉例,秒懂原理
假設你有一只熊貓對象(屬性:名字、年齡、毛色),想快速創建 10 只一模一樣的熊貓:
不用原型模式: 每次 new 一個熊貓,手動設置所有屬性(名字 =“盼盼”,年齡 = 3 歲,毛色 = 黑白…),重復勞動。
用原型模式: 直接復制(克隆)已有的熊貓對象,新對象會繼承所有屬性,只需修改少數不同的地方(比如名字改成 “圓圓”)。
原型模式的核心角色(3 步走)
- 原型(Prototype): 定義克隆自己的接口(如
clone()
方法)。 - 具體原型(Concrete Prototype): 實現克隆邏輯,比如熊貓類。
- 客戶端(Client): 通過復制原型創建新對象。
為什么要用原型模式?
場景對比:
創建復雜對象時: 比如一個游戲角色有 100 個屬性,從零創建容易出錯,復制現有角色更高效。
需要多次創建相似對象時: 比如電商網站生成 100 個 “默認地址” 模板,復制比新建更快。
核心優勢
- 減少重復初始化: 直接復制現有對象狀態,比 new 對象后再設值更高效。
- 方便擴展對象類型: 新增角色時,只需復制現有原型并修改部分屬性,無需修改創建邏輯。
- 隔離對象創建細節: 客戶端不用知道對象如何構建,只需復制原型。
代碼示例
// 1. 原型接口:實現Cloneable接口并覆蓋clone方法
class Panda implements Cloneable {private String name;private int age;private String color = "黑白"; // 共享屬性,所有熊貓默認毛色相同public Panda(String name, int age) {this.name = name;this.age = age;}// 克隆方法(淺拷貝)@Overrideprotected Panda clone() throws CloneNotSupportedException {return (Panda) super.clone();}// setter/getterpublic void setName(String name) { this.name = name; }public String getName() { return name; }public void setAge(int age) { this.age = age; }public int getAge() { return age; }public String getColor() { return color; }
}// 2. 客戶端:復制原型創建新對象
public class PrototypeDemo {public static void main(String[] args) throws CloneNotSupportedException {// 初始原型:熊貓“盼盼”Panda original = new Panda("盼盼", 3);// 克隆出熊貓“圓圓”Panda clone1 = original.clone();clone1.setName("圓圓");clone1.setAge(2);// 克隆出熊貓“團團”Panda clone2 = original.clone();clone2.setName("團團");clone2.setAge(4);// 輸出結果System.out.println("原型:" + original.getName() + ",年齡:" + original.getAge() + ",毛色:" + original.getColor());System.out.println("克隆1:" + clone1.getName() + ",年齡:" + clone1.getAge() + ",毛色:" + clone1.getColor());System.out.println("克隆2:" + clone2.getName() + ",年齡:" + clone2.getAge() + ",毛色:" + clone2.getColor());}
}
深拷貝 vs 淺拷貝
- 淺拷貝: 只復制對象本身,不復制其引用的對象(如上面的
clone()
方法)。
→ 若原型中有數組或集合,克隆對象會和原型共享該數據,修改會互相影響。 - 深拷貝: 遞歸復制所有引用的對象(需手動實現)。
→ 如序列化對象后再反序列化,確保克隆對象完全獨立。
- 原型模式和工廠模式的區別
- 工廠模式:根據參數 “新建” 對象(從無到有)。
- 原型模式:根據現有對象 “復制” 新對象(從有到有)。
- 實際場景舉例
- 游戲中復制 NPC:怪物、NPC 的屬性通過復制原型快速生成。
- Spring 框架中的
Bean
復制:通過BeanUtils.cloneBean()
復制對象。