【設計模式 06】原型模式(克隆??)

原型模式(clone?)

Prototype pattern refers to creating duplicate object while keeping performance in mind. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.

參考:

  1. tutorialspoint | prototype_pattern
  2. 博客園 | 原型模式
  3. 博客園 | Java深拷貝與序列化

原型模式是通過復制已有對象來快速創建新對象的方法,它適用于創建那些實例化很慢的對象,比如數據庫連接對象,在創建好這樣的對象后,我們可以緩存一份,下次需要這種對象時,我們可以直接返回一個該對象的拷貝。

使用場景

  1. 需要大量相似對象時,如果在類中需要大量相似的對象,并且這些對象中有很多屬性都是一樣的,只有個別屬性需要定制時,可以使用原型模式,因為直接從內從中復制對象比new一個新對象的性能要高得多。
  2. 如果一個對象的實例化過程很耗時耗力,可以使用原型模式。

Java Cloneable接口

Java中提供了一個標記接口Cloneable,類如果實現了這個接口就可以使用Object類中定義的clone方法

如果沒有實現Cloneable接口,直接調用clone()會拋出CloneNotSupportedException

Object clone()會返回當前對象的一個淺拷貝

深拷貝和淺拷貝

根據不同的對象類型,拷貝的內容也各不相同:

  1. 基本數據類型,如int,char等,直接拷貝
  2. 對于字符串,拷貝時只復制引用,當字符串的值改變時,會從字符串池中重新生成新的字符串,最終結果和拷貝值一樣
  3. 對于對象,拷貝時只復制引用,如果要復制值,需要使用深拷貝
public class Out implements Cloneable{private String outName;private In in;public Out(String outName) {this.outName = outName;}public void setIn(In in) {this.in = in;}@Overridepublic String toString() {return "Out{" +"outName='" + outName + '\'' +", in=" + in +'}';}@Overrideprotected Out clone() throws CloneNotSupportedException {return (Out) super.clone();}public static void main(String[] args) {Out out = new Out("out");In in = new In("in name");out.setIn(in);Out out1 = null;try {// in 是一個object類型,所以在調用clone()時只復制了in的引用out1 = out.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}assert out1 != null;// 改變out1.in的name也會改變out中in的nameout1.in.setName("out1 in");System.out.println(out);System.out.println(out1);}
}
/*
Out{outName='out', in=In{name='out1 in'}}
Out{outName='out', in=In{name='out1 in'}}
*/

深拷貝 DeepCopy

Java中實現深拷貝可以手動拷貝object類型的屬性,但如果這個類型中還有object類型,就會很麻煩。

@Override
protected DCOut clone() throws CloneNotSupportedException {DCOut copy = (DCOut) super.clone();In copyIn = (In) this.in.clone();copy.setIn(copyIn);return copy;
}

還可以使用Serializable接口,通過序列化,將堆中的對象數據信息復制一份到堆外,再反序列化成新的克隆對象

import java.io.*;public class DeepClone implements Serializable {private Object obj;public DeepClone(Object obj){this.obj = obj;}public Object deepClone() {Object result = null;//序列化ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = null;try {oos = new ObjectOutputStream(baos);oos.writeObject(obj);} catch (IOException e) {e.printStackTrace();}// 反序列化ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream  ois = null;try {ois = new ObjectInputStream(bais);result = ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return result;}
}

python中的深拷貝和淺拷貝

In [1]: import copyIn [2]: a = [i for i in range(10)]In [3]: b = copy.copy(a)In [4]: a is b
Out[4]: FalseIn [5]: c = [[1, 2], [3, 4]]In [6]: d = copy.copy(c)In [7]: d is c
Out[7]: FalseIn [8]: d[0] is c[0]
Out[8]: TrueIn [9]: e = copy.deepcopy(c)In [10]: e[0] is c[0]
Out[10]: FalseIn [11]:

python內置的copy模塊提供了深拷貝和淺拷貝的功能,python中淺拷貝只會拷貝父對象,不會拷貝父對象內部的子對象

python切片屬于淺拷貝

《大話設計模式》里簡歷的例子

package pers.junebao.prototype_pattern;import pers.junebao.prototype_pattern.deep_copy.DeepClone;import java.io.Serializable;public class Resume implements Cloneable, Serializable {private String name;private String education;private String sex;Resume(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void setEducation(String education) {this.education = education;}public void setSex(String sex) {this.sex = sex;}public void print(){System.out.println("name: " + this.name);System.out.println("sex : " + this.sex);System.out.println("education: " + this.education);}@Overridepublic Resume clone() {Resume resume = null;// 深拷貝resume = (Resume) DeepClone.deepClone(this);return resume;}
}
package pers.junebao.prototype_pattern;public class Main {public static void main(String[] args) {Resume resume = new Resume("JuneBao");resume.setSex("男");resume.setEducation("本科");Resume resume1 = resume.clone();resume1.setSex("女");resume.print();resume1.print();}
}

GitHub | 完整代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457430.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457430.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457430.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2016OSC源創會年終盛典-綜合技術專場-張小剛

2019獨角獸企業重金招聘Python工程師標準>>> 綜合技術專場 講師/SPEAKERS 張小剛 網易云負載均衡項目負責人 《網易蜂巢負載均衡技術實踐》從網易蜂巢中的實踐出發,分享網易蜂巢負載均衡服務從無到有,從私有云到公有云過程中的技術實踐。重點…

python策略模式包含角色_詳解Python設計模式之策略模式

雖然設計模式與語言無關,但這并不意味著每一個模式都能在每一門語言中使用。《設計模式:可復用面向對象軟件的基礎》一書中有 23 個模式,其中有 16 個在動態語言中“不見了,或者簡化了”。1、策略模式概述策略模式:定義…

mysql 日期

數據類型 數據類型格式date YYYY-MM-DD datetime YYYY-MM-DD HH:MM:SS timestamp YYYY-MM-DD HH:MM:SS year YYYY 或 YY 具體實現的函數 1、now() 返回當前的日期和時間 SELECT NOW(); 2、curdate() 返回當前的日期 SELECT CURdate(); 3、curtime()返回當…

【Go】panic: reflect: call of reflect.Value.FieldByName on ptr Value

產生原因 調用 FieldByName()方法時,調用者與預期類型不相符。 // 錯誤代碼 func setNewArticleInfoToCache(article *Article) {fields : []string{"Title", "Abstract", "ID", "AuthorID", "CreateTime",}im…

超完整的 Chrome 瀏覽器客戶端調試大全

2019獨角獸企業重金招聘Python工程師標準>>> 引言 “工欲善其事,必先利其器” 沒錯,這句話個人覺得說的特別有道理,舉個例子來說吧,厲害的化妝師都有一套非常專業的刷子,散粉刷負責定妝,眼影刷負…

PHP 獲取服務器詳細信息【轉】

碰到此問題,做下記錄 獲取系統類型及版本號: php_uname() (例:Windows NT COMPUTER 5.1 build 2600)只獲取系統類型: php_uname(s) (或&#xff1…

HIVE攻略 JFK_Hive安裝及使用攻略

目錄Hive的安裝Hive的基本使用:CRUDHive交互式模式數據導入數據導出Hive查詢HiveQLHive視圖Hive分區表1. Hive的安裝系統環境裝好hadoop的環境后,我們可以把Hive裝在namenode機器上(c1)。hadoop的環境,請參考:讓Hadoop跑在云端系列文章&#…

MySQL 為什么用索引,為什么是 B+樹,怎么用索引

MySQL 索引 A database index is a data structure that improves the speed of operations in a table. Indexes can be created using one or more columns, providing the basis for both rapid random lookups and efficient ordering of access to records. 為什么需要索…

頁面加載完畢執行多個JS函數

通常我們需要在打開頁面時加載腳本,這些腳本必須在頁面加載完畢后才可以執行,因為這時候DOM才完整,可以利用window.onload確保這一點,如:window.οnlοadfirstFunction;這腳本的意思是在頁面完畢后執行firstFunction函…

Servlet 生命周期、工作原理

Servlet 生命周期:Servlet 加載--->實例化--->服務--->銷毀。init():在Servlet的生命周期中,僅執行一次init()方法。它是在服務器裝入Servlet時執行的,負責初始化Servlet對象。可以配置服務器&…

【Go 并發控制】上下文 context 源碼

Context 在 Go 服務中,往往由一個獨立的 goroutine 去處理一次請求,但在這個 goroutine 中,可能會開啟別的 goroutine 去執行一些具體的事務,如數據庫,RPC 等,同時,這一組 goroutine 可能還需要…

js設置全局變量ajax中賦值

js設置全局變量,在ajax中給予賦值賦值不上問題解決方案 方案一、 //在全局或某個需要的函數內設置Ajax異步為false,也就是同步. $.ajaxSetup({async : false}); //然后再進行你的Ajax操作 $.post(地址, 參數, function(data, status) { if (status &q…

iOS開發UI篇—模仿ipad版QQ空間登錄界面

一、實現和步驟 1.一般ipad項目在命名的時候可以加一個HD,標明為高清版 2.設置項目的文件結構,分為home和login兩個部分 3.登陸界面的設置 (1)設置第一個控制器和自定義的控制器類(登陸)關聯 (2&#xff09…

click傳值vue_對vue下點擊事件傳參和不傳參的區別詳解

如下所示:{{btn_text1}}{{btn_text2}}var _vm new Vue({data : {btn_text1 : 點擊1 ,btn_text2 : 點擊2},methods : {test_click1 : function (e) {console.log(test_click1--------------------------) ;console.log(e) ;// 輸出結果:MouseEvent {isTr…

【Golang 源碼】sync.Map 源碼詳解

sync.Map 不安全的 map go 中原生的 map 不是并發安全的&#xff0c;多個 goroutine 并發地去操作一個 map 會拋出一個 panic package main import "fmt" func main() {m : map[string]int {"1": 1, "2": 2,}// 并發寫for i : 0; i < 100;…

oracle中scn(系統改變號)

系統scn&#xff1a; select checkpoint_change# from v$database; 文件scn&#xff1a; select name,checkpoint_change# from v$datafile; 結束scn&#xff1a; select name,last_change# from v$datafile; 數據文件頭部scn…

sicktim571操作手冊_SICK激光傳感器TIM310操作說明書

SICK激光傳感器TIM310操作說明書最近更新時間&#xff1a;2015/1/23 13:31:29提 供 商&#xff1a;資料大小&#xff1a;1.2MB文件類型&#xff1a;PDF 文件下載次數&#xff1a;709次資料類型&#xff1a;瀏覽次數&#xff1a;5192次相關產品&#xff1a;詳細介紹&#xff1a;…

Tengine 安裝配置全過程

在先前的文章中介紹過Tengine&#xff0c;先前只是使用了運維人員配置好的內容&#xff0c;未自己進行過安裝配置。周末閑來無事&#xff0c;對于Tengine進行了嘗試性的安裝。記錄下面方便以后再做改進。Tengine官網上有個非常簡單的教程&#xff0c;中間并未涉及到一些常用的設…

【Go】sync.WaitGroup 源碼分析

WaitGroup sync.WaitGroup 用于等待一組 goroutine 返回&#xff0c;如&#xff1a; var wg sync.WaitGroup{}func do() {time.Sleep(time.Second)fmt.Println("done")wg.Done() }func main() {go do()go do()wg.Add(2)wg.Wait()fmt.Println("main done"…

什么是響應式設計?為什么要做響應式設計?響應式設計的基本原理是什么?...

頁面的設計和開發應當根據用戶行為以及設備環境&#xff08;系統平臺、屏幕尺寸、屏幕定向等&#xff09;進行相應的響應和調整。具體的實踐方式由多方面組成&#xff0c;包括彈性網格和布局、圖片、css media query的使用等。無論用戶正在使用筆記本還是iPad&#xff0c;我們的…