在《生化危機》系列電影中,克隆人是個頻頻出現的話題。保護傘公司為了需求復制出另一個戰(zhàn)力相當的戰(zhàn)士Alice,不惜克隆成百上千個Alice,然而直到最后,非但沒有真正克隆出另一個完美的Alice,就連Alice自己也被證實是保護傘董事的一個克隆人。
克隆人一直是飽含倫理爭議的話題,但是在軟件設計領域,克隆思想卻很受歡迎。軟件旨在用程序替代人工去做重復性的工作。歸根結底,“懶”是推動軟件發(fā)展的重要助力,原型模式就是克隆思想的重要應用之一。
一言
原型實例指定創(chuàng)建對象的種類,通過拷貝這些原型創(chuàng)建新的對象。
概述
原型模式是一種創(chuàng)建型設計模式,它允許一個對象再創(chuàng)建一個可定制的對象而無需知道如何創(chuàng)建的細節(jié)。就像愛麗絲直到最后才指導自己也是克隆人一樣,實例本身是不關注
創(chuàng)建實例的細節(jié)的。
原理
通過將一個原型對象傳給要發(fā)動創(chuàng)建的對象,要發(fā)動創(chuàng)建的對象通過請求原型對象拷貝它們自己來實施創(chuàng)建,即bean.clone()。
歡迎來到保護傘公司
職員7568你好,歡迎你加入保護傘公司,徐江博士交給你的第一個任務是,編寫代碼,復制十個愛麗絲,加油!
循規(guī)蹈矩的豪賭
小職員7568稍加思索便寫出了如下代碼:
反例代碼
Alice原型
public class Alice{
private String name;
private int age;
private String skill;
public Sheep(String name, int age, String skill) {
this.name = name;
this.age = age;
this.skill= skill;
}
//setter & getter
@Override
public String toString() {
return "Alice{" +
"name='" + name + '\'' +
", age=" + age +
", skill='" + skill+ '\'' +
'}';
}
驅動機
public class Client {
public static void main(String[] args) {
Alice alice= new Alice ("alice", 18, "極強的戰(zhàn)斗天賦");
Alice alice1= new Alice ("alice", 18, "極強的戰(zhàn)斗天賦");
Alice alice2= new Alice ("alice", 18, "極強的戰(zhàn)斗天賦");
Alice alice3= new Alice ("alice", 18, "極強的戰(zhàn)斗天賦");
Alice alice4= new Alice ("alice", 18, "極強的戰(zhàn)斗天賦");
System.out.println(alice);
System.out.println(alice1);
System.out.println(alice2);
System.out.println(alice3);
System.out.println(alice4);
}
}
不一會,職員7568就高呼自己完成了任務。
徐江博士看了看代碼,吩咐手下,“拖出去喂喪尸,什么檔次跟我在一個公司工作?”
所以,保護傘公司職員-1。
問題分析
那么究竟是什么問題導致博士那么生氣呢?
首先,要肯定上述代碼的優(yōu)勢,簡單易操作。但是,在創(chuàng)建新對象的時候總是需要重新獲取原始對象的屬性,如果創(chuàng)建的對象比較復雜時,效率會及低。而且每一次都需要重新初始化對象,靈活性太低。
淺拷貝
“老,老板,我有一個不太成熟的思路,不知道當講不當講”,職員7569瑟瑟發(fā)抖。
“ 講!”
“Java中Object類是所有類的根類,Object類提供了一個clone()方法,該方法可以將一個Java對象復制一份,但是需要實現clone的Java類必須要實現一個接口cloneable該接口表示該類能夠復制且具有復制的能力。通過這種方式,或許…”
徐博士聽著這段構想,嘴角露出了不易察覺的微笑:
“很好,但是我有一個要求,我要讓這些愛麗絲們做朋友”
代碼實現
public class Alice implements Cloneable{
private String name;
private int age;
private String skill;
public Alice friend;
public Alice (String name, int age, String skill) {
this.name = name;
this.age = age;
this.skill= skill;
}
@Override
protected Object clone(){
Alice alice = null;
try {
alice = (Alice ) super.clone();
}catch (Exception e){
System.err.println(e.getMessage());
}
return alice ;
}
@Override
public String toString() {
return "Alice{" +
"name='" + name + '\'' +
", age=" + age +
", skill='" + skill+ '\'' +
'}';
}
}
徐博士的檢查
徐博士看了看代碼,繼續(xù)吩咐手下,“拖出去,喂喪尸,什么檔次跟我待一個公司?!?br> 職員7569高呼:“我不服,我的代碼有什么問題?”
徐博士看了看他漲紅的面龐,緩緩的將Alice實例的friend屬性的哈希值打印了出來,小職員呆住了,再沒有了一絲力氣。
保護傘公司職員-1
在實體屬性發(fā)生變更時,原型模式可以以很小的改動代價實現對象的拷貝。但是,上述實現的克隆并不會將本體的對象屬性做到真正意義的克隆,只是將對象的引用復制了多份,所以我們稱之為淺克隆。
深拷貝
職員7570汗流浹背了,因為下一個就輪到他來解決這個問題,他拼命的思考,終于,他起身了。
“博士,我想到了。我們復制對象的所有基本數據類型的成員變量值,為所有引用數據類型的成員變量申請存儲空間,并復制每個引用數據類型成員變量所引用的對象,直到該對象可達的所有對象。也就是說,對象進行深拷貝要對整個對象進行拷貝?!?br> 徐博士抬頭看了看這個少年:“繼續(xù)”
小職員咽了咽口水:“對于深拷貝的實現方式,我想可以通過重寫clone方法…或者 ,或者通過對象實例化實現深拷貝?!?br> 徐博士又深深的看了一言面前這個侃侃而談的少年:“看來你不是個草包,寫寫看看吧。”
代碼實現
public class DeepCloneAbleTarget implements Serializable,Cloneable{
private static final long serivalVersionID = 1L;
private String cloneName;
private String cloneClass;
public DeepCloneAbleTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class DeepProtoType implements Serializable,Cloneable {
public String name;
public DeepCloneAbleTarget deepCloneAbleTarget;
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
deep =super.clone();
DeepProtoType deepProtoType =(DeepProtoType) deep;
deepProtoType.deepCloneAbleTarget = (DeepCloneAbleTarget) deepCloneAbleTarget.clone();
return deepProtoType;
}
public Object deepClone(){
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepProtoType copyObj = (DeepProtoType) ois.readObject();
return copyObj;
}catch (Exception e){
System.err.println(e.getMessage());
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
結
創(chuàng)建新的對象比較復雜時,可以利用原型模式簡化對象的創(chuàng)建過程,同時也能夠提高效率。不用重新初始化對象,而是動態(tài)地獲得對象運行時的狀態(tài)。如果原始對象發(fā)生變化(增加或者減少屬性),其它克隆對象的也會發(fā)生相應的變化無需修改代碼。
但是在實現深克隆的時候可能需要比較復雜的代碼。同時,需要為每一個類配備一個克隆方法,這對全新的類來說不是很難,但對已有的類進行改造時,需要修改其源代碼,違背了ocp原則。
好啦,今天在保護傘公司的打工之旅就到此為止,祝各位好運。文章來源:http://www.zghlxwxcb.cn/news/detail-812388.html
關注我,共同進步,每周至少一更?!猈ayne文章來源地址http://www.zghlxwxcb.cn/news/detail-812388.html
到了這里,關于11.什么檔次的原型模式和我寫的一樣的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!