原型模式
原型模式的定義
1.定義:用原型實(shí)例來(lái)創(chuàng)建指定對(duì)象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象
原型模式其實(shí)就是從一個(gè)對(duì)象再創(chuàng)建另外一個(gè)可定制的對(duì)象,而且不需要知道任何的創(chuàng)建細(xì)節(jié)
原型模式的結(jié)構(gòu)圖
原型模式的實(shí)現(xiàn)
代碼結(jié)構(gòu)圖:二版結(jié)構(gòu)圖(驗(yàn)證深拷貝與淺拷貝)
調(diào)用關(guān)系
1.新建具體原型類(lèi),實(shí)現(xiàn)Java.lang.Cloneable接口,并提供相對(duì)應(yīng)的方法,特別注意需要實(shí)現(xiàn)Cloneable的clone方法,該方法使原型模式的關(guān)鍵
package org.example.prototype;
/**
* @author
* @date 2021/3/16 9:08
**/
public class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private String timeArea;
private String company;
public Resume(String name){
this.name=name;
}
//設(shè)置個(gè)人信息
public void setPersonalInfo(String sex,String age){
this.sex=sex;
this.age=age;
}
//設(shè)置工作經(jīng)歷
public void setWorkExperience(String timeArea,String company){
this.timeArea=timeArea;
this.company=company;
}
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 String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getTimeArea() {
return timeArea;
}
public void setTimeArea(String timeArea) {
this.timeArea = timeArea;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
//顯示
public void Display(){
System.out.println("name="+this.getName()+"age="+this.getAge()+"sex="+this.getSex()+"timeArea="+this.getTimeArea()+"company="+this.getCompany());
}
//clone方法是實(shí)現(xiàn)原型模式的關(guān)鍵
@Override
public Resume clone(){
Resume resume=null;
try{
resume= (Resume) super.clone();
}catch (Exception e){
e.printStackTrace();
}
return resume;
}
}
2.新建客戶(hù)端進(jìn)行調(diào)用
package org.example.prototype;
/**
* @author
* @date 2021/3/16 9:20
**/
public class Test {
public static void main(String[] args) {
Resume resume = new Resume("原型設(shè)計(jì)模式");
resume.setPersonalInfo("男","29");
resume.setWorkExperience("2020","run");
resume.Display();
Resume clone = resume.clone();
clone.setPersonalInfo("女","18");
clone.setWorkExperience("2021","HurryRun");
clone.Display();
}
}
3.運(yùn)行結(jié)果
**深拷貝與淺拷貝
-
深拷貝與淺拷貝征懈。Object類(lèi)的clone方法只會(huì)拷貝對(duì)象中的基本的數(shù)據(jù)類(lèi)型吁系,對(duì)于數(shù)組捌斧、容器對(duì)象、引用對(duì)象等都不會(huì)拷貝炼邀,這就是淺拷貝。如果要實(shí)現(xiàn)深拷貝剪侮,必須將原型模式中的數(shù)組拭宁、容器對(duì)象、引用對(duì)象等另行拷貝瓣俯。
因此如果是沒(méi)有實(shí)現(xiàn)Cloneable接口的對(duì)象需要自己實(shí)現(xiàn)一次如:
package org.example.prototype;
/**
* @author
* @date 2021/3/16 9:37
**/
public class WorkExperience implements Cloneable{
private String timeArea;
private String company;
public String getTimeArea() {
return timeArea;
}
public void setTimeArea(String timeArea) {
this.timeArea = timeArea;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
//實(shí)現(xiàn)深拷貝
@Override
public WorkExperience clone(){
WorkExperience workExperience=null;
try{
workExperience= (WorkExperience) super.clone();
}catch (Exception e){
e.printStackTrace();
}
return workExperience;
}
}
如果對(duì)象本身已經(jīng)實(shí)現(xiàn)了Cloneable接口只需要克隆時(shí)調(diào)用一次clone接口即可,如ArrayList
public class Prototype implements Cloneable {
private ArrayList list = new ArrayList();
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
prototype.list = (ArrayList) this.list.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
原型模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
1.使用原型模式創(chuàng)建對(duì)象比直接new一個(gè)對(duì)象在性能上好得多,因?yàn)镺bject類(lèi)的clone方法是一個(gè)本地方法,它直接操作內(nèi)存中的二進(jìn)制流,特別是復(fù)制大對(duì)象時(shí),性能的差別非常的明顯.
2.使用原型模式的另一個(gè)好處就是簡(jiǎn)化了對(duì)象的創(chuàng)建,使創(chuàng)建對(duì)象就像我們?cè)诰庉嬑臋n時(shí)的復(fù)制粘貼一樣
缺點(diǎn)
使用原型模式復(fù)制對(duì)象不會(huì)調(diào)用類(lèi)的構(gòu)造器創(chuàng)建對(duì)象,不但構(gòu)造器中的代碼無(wú)法執(zhí)行,甚至訪問(wèn)權(quán)限都對(duì)原型模式無(wú)效;