創(chuàng)建重復(fù)對(duì)象-場(chǎng)景體驗(yàn)
??今天來一個(gè)大客戶,他要求幫他下100個(gè)訂單。每個(gè)訂單除了用戶ID,和用戶名不同之外,其他個(gè)人信息完全相同。
訂單類
public class Order{
//id 主鍵,無實(shí)際意義
private String id;
//訂單編號(hào)
private String orderNo;
//產(chǎn)品編碼
private String productNo;
//產(chǎn)品名稱
private String productName;
//產(chǎn)品類型
private String productType;
//訂單購(gòu)買數(shù)量
private Integer num;
//用戶id
private String userId;
//用戶名稱
private String userName;
//用戶電話號(hào)碼
private String tel;
//用戶住址
private String address;
//購(gòu)買店鋪,用于識(shí)別改訂單是在哪一個(gè)店鋪下的單。
private Store store;
}
//商店類
public class Store{
//店鋪id
private String id;
//店鋪名稱
private String name;
//店鋪負(fù)責(zé)人
private String head;
//店鋪地址
private Strign address;
}
制造數(shù)據(jù):
public void copyOrder(){
//專賣店
Store store = new Store();
store.setId("dp001");
store.setName("地球村專賣店");
store.setHead("村長(zhǎng)");
store.setAddress("東風(fēng)東街001號(hào)");
//第一個(gè)訂單
Order order = new Order();
order.setId("111111");
order.setOrderNo("dd001");
order.setProductNo("cp001");
order.setProductName("產(chǎn)品1");
order.setProductType("工具類");
order.setNum(50);
order.setUserId("U001");
order.setUserName("用戶1");
order.setTel("17660887362");
order.setAddress("地球村-種花家");
order.setStore(store);
//第二個(gè)訂單
Order order1 = new Order();
order.setId("111112");
order.setOrderNo("dd002");
order.setProductNo(order.getProductNo());
order.setProductName(order.getProductName());
order.setProductType(order.getProductType());
order.setNum(order.getNum());
order.setUserId("U002");
order.setUserName("用戶2");
order.setTel(order.getTel());
order.setAddress(order.getAddress());
order.setStore(store);
...
還要100個(gè)
}
??上面的代碼就是現(xiàn)狀,當(dāng)然也可以使用構(gòu)造方法,但是過程都是一樣的需要大量重復(fù)的代碼。非常不美觀。
解決方案(原型模式)
原型模式可以理解為:將一個(gè)完整對(duì)象的復(fù)制創(chuàng)建過程抽離成一個(gè)方法,使我們要?jiǎng)?chuàng)建一個(gè)相同對(duì)象的時(shí)候不需要再依次賦值。
模擬底層實(shí)現(xiàn):
public class Order{
//id 主鍵,無實(shí)際意義
private String id;
//訂單編號(hào)
private String orderNo;
//產(chǎn)品編碼
private String productNo;
//產(chǎn)品名稱
private String productName;
//產(chǎn)品類型
private String productType;
//訂單購(gòu)買數(shù)量
private Integer num;
//用戶id
private String userId;
//用戶名稱
private String userName;
//用戶電話號(hào)碼
private String tel;
//用戶住址
private String address;
//購(gòu)買店鋪,用于識(shí)別改訂單是在哪一個(gè)店鋪下的單。
private Store store;
public Order clone(){
Order order1 = new Order();
order1.setId(this.id);
order1.setOrderNo(this.orderNo);
order1.setProductNo(this.productNo);
order1.setProductName(this.productName);
order1.setProductType(this.productType);
order1.setNum(this.num);
order1.setUserId(this.userId);
order1.setUserName(this.userName);
order1.setTel(this.tel);
order1.setAddress(this.address);
order1.setStore(this.store);
return order1;
}
}
我們使用的時(shí)候:
public void copyOrder(){
//專賣店
Store store = new Store();
store.setId("dp001");
store.setName("地球村專賣店");
store.setHead("村長(zhǎng)");
store.setAddress("東風(fēng)東街001號(hào)");
//第一個(gè)訂單
Order order = new Order();
order.setId("111111");
order.setOrderNo("dd001");
order.setProductNo("cp001");
order.setProductName("產(chǎn)品1");
order.setProductType("工具類");
order.setNum(50);
order.setUserId("U001");
order.setUserName("用戶1");
order.setTel("17660887362");
order.setAddress("地球村-種花家");
order.setStore(store);
//第二個(gè)訂單
Order order1 = order.clone();
order.setId("111112");
order.setOrderNo("dd002");
order.setUserId("U002");
order.setUserName("用戶2");
...
之后的100個(gè)相同
}
通過上述方法使原本賦值操作的工作量大量減少,只需要關(guān)注自己個(gè)性化的賦值即可。
上面的clone方法是完全我自己寫的用來模擬的,Java為我們提供了更好的實(shí)現(xiàn),不需要我們?nèi)プ錾厦鏌o聊的賦值工作:
只需要Order類實(shí)現(xiàn)Cloneable接口,重寫clone方法,在這個(gè)方法里面調(diào)用supper.clone()方法就好了。
public class Order{
//id 主鍵,無實(shí)際意義
private String id;
//訂單編號(hào)
private String orderNo;
//產(chǎn)品編碼
private String productNo;
//產(chǎn)品名稱
private String productName;
//產(chǎn)品類型
private String productType;
//訂單購(gòu)買數(shù)量
private Integer num;
//用戶id
private String userId;
//用戶名稱
private String userName;
//用戶電話號(hào)碼
private String tel;
//用戶住址
private String address;
//購(gòu)買店鋪,用于識(shí)別改訂單是在哪一個(gè)店鋪下的單。
private Store store;
@Override
public Order clone(){
Order order1 = new Order();
try {
order1 = (Order) super.clone();
}catch (Exception e){
System.out.println(e.getMessage());
}
return order1;
}
}
??有興趣的未來大佬們可以去看一下clone的源碼,這里用的super.clone()是Object中的clone方法。這個(gè)方法是native的方法(本地方法)。Java中,用native關(guān)鍵字修飾的函數(shù)表明該方法的實(shí)現(xiàn)并不是在Java中去完成,而是由C/C++去完成,并被編譯成了.dll,由Java去調(diào)用。方法的具體實(shí)現(xiàn)體在dll文件中,對(duì)于不同平臺(tái),其具體實(shí)現(xiàn)應(yīng)該有所不同。用native修飾,即表示操作系統(tǒng),需要提供此方法,Java本身需要使用。
??clone主要做的就是開創(chuàng)新的空間,將原對(duì)象的數(shù)據(jù)復(fù)制過去,再給返回引用。在Java里面所有的類如果重寫clone方法就都是個(gè)性化的處理了。但是需要注意的是這個(gè)native的clone是淺拷貝。也就是在對(duì)象中還有對(duì)象的話,內(nèi)部的對(duì)象clone之后還是原來的對(duì)象。
以咱們的代碼舉例:
??在Order類中有一個(gè)屬性是Store的實(shí)例。在上面的clone執(zhí)行之后如果改變clone之后的實(shí)例中的store屬性,原本的order中的store屬性也會(huì)改變。
在上面“copyOrder”代碼的最后一行增加如下:
System.out.println("order2"+order1);
System.out.println("order:"+order);
System.out.println("改變前order1:"+order1.getStore());
System.out.println("改變前order:"+order.getStore());
order1.getStore().setAddress("地球村-鷹醬家門頭房");
System.out.println("改變后order1:"+order1.getStore());
System.out.println("改變前order:"+order.getStore());
可以看到,我們只改變了order1實(shí)例中store的address屬性,但是order的對(duì)應(yīng)屬性也跟著一起變了。
如何解決上面的淺拷貝?
原型模式定義
??原型模式(Prototype Pattern)用于創(chuàng)建重復(fù)的對(duì)象,同時(shí)又能保證性能。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式之一。
??這種模式是實(shí)現(xiàn)了一個(gè)原型接口,該接口用于創(chuàng)建當(dāng)前對(duì)象的克隆。當(dāng)直接創(chuàng)建對(duì)象的代價(jià)比較大時(shí),則采用這種模式。例如,一個(gè)對(duì)象需要在一個(gè)高代價(jià)的數(shù)據(jù)庫操作之后被創(chuàng)建。我們可以緩存該對(duì)象,在下一個(gè)請(qǐng)求時(shí)返回它的克隆,在需要的時(shí)候更新數(shù)據(jù)庫,以此來減少數(shù)據(jù)庫調(diào)用。文章來源:http://www.zghlxwxcb.cn/news/detail-606284.html
定義是引用自:菜鳥教程-原型模式文章來源地址http://www.zghlxwxcb.cn/news/detail-606284.html
到了這里,關(guān)于創(chuàng)造型模式-原型模式(場(chǎng)景體驗(yàn)-》方案解決===代碼圖解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!