代碼示例:https://github.com/elfc/patterns
分類
創(chuàng)建型
意圖
用原型實(shí)例指定創(chuàng)建對象的種類舀凛,并且通過拷貝這些原型創(chuàng)建新的對象。
動(dòng)機(jī)
考慮一個(gè)五金配件商(Hardware)可以生產(chǎn)螺絲(ScrewHardware)和螺母(NutHardware)途蒋, 生產(chǎn)所采用的模型猛遍、樣式、材料都一樣只是大小不同号坡,每生產(chǎn)一個(gè)螺絲或螺母創(chuàng)建一個(gè)對象懊烤,這些實(shí)例只是在初始化對象的時(shí)候大小有所不同,這樣做會(huì)產(chǎn)生大量的重復(fù)操作宽堆,解決辦法是可以生成一個(gè)管理類(PrototypeManager)腌紧,讓這個(gè)管理類來拷貝或者“克隆”一個(gè)Hardware, 我們稱這個(gè)實(shí)例為一個(gè)原型。
適用性
- 當(dāng)一個(gè)系統(tǒng)應(yīng)該獨(dú)立于它的產(chǎn)品創(chuàng)建畜隶、構(gòu)成和表示時(shí)壁肋,要使用Prototype模式
- 當(dāng)要實(shí)例化的類是在運(yùn)行時(shí)刻指定時(shí),例如動(dòng)態(tài)裝載
- 為了避免創(chuàng)建一個(gè)與產(chǎn)品類平行的工廠類層次時(shí)
- 當(dāng)一個(gè)類的實(shí)例只能有幾種狀態(tài)組合中的一種時(shí)籽慢。建立相應(yīng)數(shù)據(jù)的原型并克隆它們可能比每次用合適的狀態(tài)手工實(shí)例化該類更方便一些
結(jié)構(gòu)
參與者
- Prototype(Hardware)
-- 聲明一個(gè)克隆自身的接口浸遗。 - ConcretePrototype(ScrewHardware、NutHardware)
-- 實(shí)現(xiàn)一個(gè)克隆自身的操作箱亿。 - Client
-- 讓一個(gè)原型克隆自身從而創(chuàng)建一個(gè)新的對象
效果
- 對客戶隱藏了具體的產(chǎn)品類跛锌,因此減少了客戶知道的名字的數(shù)目。
- 客戶無需改變即可使用與特定應(yīng)用相關(guān)的類届惋。
- 運(yùn)行時(shí)刻增加和刪除產(chǎn)品髓帽。
- 改變值以指定新對象
Tips
注意深拷貝與淺拷貝
代碼示例
/**
* @author chunyuliu
*/
@Data
public abstract class Hardware implements Cloneable {
/** 大小 */
int size;
/** 模型 */
String model;
/** 樣式 */
String style;
/** 材料 */
String material;
@Override
public Hardware clone() {
Hardware clone = null;
try {
clone = (Hardware) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
/**
* @author chunyuliu
*/
@Data
public class ScrewHardware extends Hardware {
/** 大小 */
int size;
/** 模型 */
String model;
/** 樣式 */
String style;
/** 材料 */
String material;
}
/**
* @author chunyuliu
*/
@Data
public class NutHardware extends Hardware {
/** 大小 */
int size;
/** 模型 */
String model;
/** 樣式 */
String style;
/** 材料 */
String material;
}
/**
* @author chunyuliu
*/
public class PrototypeManager {
private static Hashtable<String, Hardware> hardwareMap
= new Hashtable<String, Hardware>();
public static Hardware getHardware(String hardwareId) {
return hardwareMap.get(hardwareId).clone();
}
/**
* 加載不同類型的原型
*/
public static void load() {
Hardware screw = new ScrewHardware();
screw.setModel("螺絲模型");
screw.setStyle("花紋");
screw.setMaterial("不銹鋼");
hardwareMap.put("screw", screw);
Hardware nut = new NutHardware();
nut.setModel("螺母模型");
nut.setStyle("花紋");
nut.setMaterial("不銹鋼");
hardwareMap.put("nut", nut);
}
}
/**
* @author chunyuliu
*/
public class PrototypeTest {
@Test
public void screwHardwareTest() {
PrototypeManager.load();
// 生產(chǎn)小號螺絲
Hardware screwSmallSize = PrototypeManager.getHardware("screw");
screwSmallSize.setSize(1);
System.out.println(screwSmallSize);
// 生產(chǎn)中號螺絲
Hardware screwMiddleSmall = PrototypeManager.getHardware("screw");
screwMiddleSmall.setSize(2);
System.out.println(screwMiddleSmall);
// 生產(chǎn)小號螺母
Hardware nutSmallSize = PrototypeManager.getHardware("nut");
nutSmallSize.setSize(1);
System.out.println(nutSmallSize);
}
}