《大話設(shè)計(jì)模式》閱讀筆記和總結(jié)双吆。原書是C#編寫的,本人用Java實(shí)現(xiàn)了一遍蕉拢,包括每種設(shè)計(jì)模式的UML圖實(shí)現(xiàn)和示例代碼實(shí)現(xiàn)眯牧。
目錄:設(shè)計(jì)模式
Github地址:DesignPattern
說明
定義:原型模式(Prototype),用原型實(shí)例指定創(chuàng)建對(duì)象的種類外恕,并且通過拷貝這些原型創(chuàng)建新的對(duì)象杆逗。
UML圖:
代碼實(shí)現(xiàn):
原型類
我們這里使用java api中Cloneable接口
具體原型類
class ConcretePrototype1 implements Cloneable{
private String id;
public ConcretePrototype1(String id){
this.id = id;
}
public String getId(){
return id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
客戶端代碼
public class PrototypePattern {
public static void main(String[] args) throws CloneNotSupportedException {
ConcretePrototype1 p1 = new ConcretePrototype1("I");
ConcretePrototype1 c1 = (ConcretePrototype1) p1.clone();
System.out.println("Cloned():"+c1.getId());
}
}
運(yùn)行結(jié)果
Cloned():I
示例
例子:用程序模擬寫簡(jiǎn)歷,要求有一個(gè)簡(jiǎn)歷類鳞疲,必要有姓名罪郊,可以設(shè)置性別和年齡,可以設(shè)置工作經(jīng)歷尚洽,最終需要三份簡(jiǎn)歷悔橄。
UML圖:
代碼實(shí)現(xiàn):
工作經(jīng)歷類
public class WorkExperence implements Serializable {
private String workDate;
private String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
簡(jiǎn)歷類
public class Resume implements Cloneable,Serializable{
private String name;
private String sex;
private int age;
private WorkExperence workExperence;
public Resume(){
workExperence = new WorkExperence();
}
public void display() {
System.out.println(this.getName() + " " + this.getSex() + " "
+ this.getAge() + "\n工作經(jīng)歷: "
+ this.getWorkExperence().getWorkDate() + " "
+ this.getWorkExperence().getCompany());
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public WorkExperence getWorkExperence() {
return workExperence;
}
public void setWorkExperence(String workDate,String company) {
workExperence.setCompany(company);
workExperence.setWorkDate(workDate);
}
}
客戶端調(diào)用
public class Main {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
copy();
}
public static void copy() throws CloneNotSupportedException {
Resume resumeA = new Resume();
resumeA.setName("大鳥");
resumeA.setAge(25);
resumeA.setSex("男");
resumeA.setWorkExperence("2015-2016","A公司");
Resume resumeB = (Resume) resumeA.clone();
resumeB.setWorkExperence("2016-2017","B公司");
Resume resumeC = (Resume) resumeA.clone();
resumeC.setWorkExperence("2017-2018","C公司");
resumeA.display();
resumeB.display();
resumeC.display();
}
}
運(yùn)行結(jié)果
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
我們發(fā)現(xiàn),設(shè)置的工作經(jīng)歷并沒有正確的顯示翎朱。原因是:如果復(fù)制的字段是值類型的橄维,則對(duì)該字段執(zhí)行逐位復(fù)制,如果字段是引用類型拴曲,則復(fù)制引用但不復(fù)制引用的對(duì)象争舞,因此原始對(duì)象及其復(fù)本引用同一對(duì)象。
深拷貝實(shí)現(xiàn)
UML圖:
代碼實(shí)現(xiàn):
簡(jiǎn)歷類增加deepClone()方法
public class Resume implements Cloneable,Serializable{
// ……
public Object deepClone() throws IOException, ClassNotFoundException {
// 將對(duì)象寫入流內(nèi)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 從流內(nèi)讀出對(duì)象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();
}
}
客戶端代碼
public class Main {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
copy();
System.out.println("==============");
deepCopy();
}
public static void copy() throws CloneNotSupportedException {
Resume resumeA = new Resume();
resumeA.setName("大鳥");
resumeA.setAge(25);
resumeA.setSex("男");
resumeA.setWorkExperence("2015-2016","A公司");
Resume resumeB = (Resume) resumeA.clone();
resumeB.setWorkExperence("2016-2017","B公司");
Resume resumeC = (Resume) resumeA.clone();
resumeC.setWorkExperence("2017-2018","C公司");
resumeA.display();
resumeB.display();
resumeC.display();
}
public static void deepCopy() throws IOException, ClassNotFoundException {
Resume resumeA = new Resume();
resumeA.setName("大鳥");
resumeA.setAge(25);
resumeA.setSex("男");
resumeA.setWorkExperence("2015-2016","A公司");
Resume resumeB = (Resume) resumeA.deepClone();
resumeB.setWorkExperence("2016-2017","B公司");
Resume resumeC = (Resume) resumeA.deepClone();
resumeC.setWorkExperence("2017-2018","C公司");
resumeA.display();
resumeB.display();
resumeC.display();
}
}
運(yùn)行結(jié)果:
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司
==============
大鳥 男 25
工作經(jīng)歷: 2015-2016 A公司
大鳥 男 25
工作經(jīng)歷: 2016-2017 B公司
大鳥 男 25
工作經(jīng)歷: 2017-2018 C公司