成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

設計模式 - Prototype 原型模式

開發 前端
在設計模式的系列文章中,我們前面已經寫了工廠模式、單列模式、建造者模式,在針對創建型模式中,今天想跟大家分享的是原型模式。

[[400064]]

前言

在設計模式的系列文章中,我們前面已經寫了工廠模式、單列模式、建造者模式,在針對創建型模式中,今天想跟大家分享的是原型模式

其實原型模式在我們的代碼中是很常見的,但是又容易被我們所忽視的一種模式,那么什么是原型模式呢?

原型模式其實就是一種克隆對象的方法,在我們的編碼時候是很常見的,比如我們常用的的BeanUtils.copyProperties就是一種對象的淺copy,其實現在我們實例化對象操作并不是特別耗費性能,所以在針對一些特殊場景我們還是需要克隆那些已經實例化的對象的:

  • 依賴外部資源或硬件密集型操作,比如數據庫查詢,或者一些存在IO操作的場景
  • 獲取相同對象在相同狀態的拷貝從而不需要重復創建獲取狀態的操作的情況

看下我們的類圖:

在上面的圖中我們可以看出原型模式其實很簡單:

  • 第一個是抽象原型(prototype)聲明clone方法,可以是接口可以是基類,在簡單的場景下我們都可以不用基類直接具體類就可以了。
  • 第二個就是具體原型類(concreteprototype)實現或者擴展clone方法,當我們在具體的原型類中的對象方法時,就會返回一個基類的抽象原型對象

針對上面理論知識,我們還是實際的舉一個例子吧!

舉例

假設現在我們有這么一種場景,公司搞一場活動有五萬個商品參加此次活動,我們需要從后臺能定時同步每個商品的銷量,方便我們為后面的活動做商品分析,我們要怎么處理這個銷量同步問題?

首先在這里銷量和庫存都是屬于熱點數據,但肯定都是相互隔離的因為庫存是要求實時性很高的,銷量可以允許有短暫延時,只要能保證數據能夠最終一致性就行,所以下單的同時我們可以根據一個MQ去更新我們數據庫里的商品銷量。

在我們去查看銷量的時候我們不能每次都是去查DB所以我們可以通過redis緩存來處理,同時我們在緩存中記錄一下我們當前查詢的更新時間。

再次查詢時通過redis數據里面的更新時間,作為查詢條件去查詢DB中的更新時間大于我們當前redis中的記錄時間,這樣就減少了SQL的掃表的行數(更新的數據與全量數據相比,更新的數據量還是占少數的)

基于上面流程我們開始寫demo了

在這里demo中我們先是創建了一個ItemSold類,以及一個SkuSold類同時ItemSold重寫Cloneable里面的clone方法。然后在最后的測試類mian方法中我調用了clone方法,copy一個新的商品銷量類。

細心的同學在看結果的時候不知道有沒有發現一個問題?在for循環里面,我分別打印出來的ItemSold 以及 SkuSold對象他們的內存地址。

復制出來的SkuSold的內存地址居然和原型地址一樣,ItemSold的復制就和原型地址不一樣了,針對這個問題這里我們就要聊聊原型模式的兩種實現淺拷貝和深拷貝了。

  • 這里說明一下我們在for循環里面是做數據convert,一般來說我們不會引用底層模型來做返回結果模型,需要做一層轉化,來達到防腐的效果。為了體現深淺拷貝,所以寫的比較簡單,具體還是需要自己根據實際情況來做。

淺拷貝和深拷貝

  • 淺拷貝:當拷貝對象只包含簡單的數據類型比如int、float 或者不可變的對象(字符串)時,就直接將這些字段復制到新的對象中。而引用的對象并沒有復制而是將引用對象的地址復制一份給克隆對象
  • 深拷貝:不管拷貝對象里面簡單數據類型還是引用對象類型都是會完全的復制一份到新的對象中

舉個例子這就好比兩兄弟大家買衣服可以一人一套,然后房子大家住在一套房子里(淺拷貝),當兩個人成家立業了,房子分開了一人一套互不影響(深拷貝)

看完這張圖,大家也就明白了,上面的demo是一個淺拷貝,那么我們要怎么做才能實現深拷貝呢?

首先我們先來看下 Java的提供的Cloneable 接口

看接口上面的解釋大致可以理解為:

  • 一個類實現了Cloneable接口,來實現這個類的clone方法從而可以合法地對該類實例進行按字段復制,假設這個類沒有實現Cloneable接口的實例上調用Object的clone()方法,則會導致拋出CloneNotSupporteddException異常。

那么我們這里怎么實現深拷貝呢?

第一種:在重寫ItemSold里面的clone方法時,再針對SkuSold也進行一次拷貝 (因為我們這里時List對象,只能是先拿到淺拷貝,再通過淺拷貝的List對象進行遍歷再調用引用對象的clone方法來實現深拷貝)

這里如果引用對象存在多級情況下我們可能就要考慮用遞歸了實現,但是代碼看上去就會復雜很多了。

第二種:通過序列化把對象寫入流中再從流中取出來

針對上面的兩種寫法其實都是可以實現的,但是不管用哪種方式,深拷貝都比淺拷貝花時間和空間,所以還是酌情考慮。其實在現在已經有很多針對淺拷貝和深拷貝的工具類

  • 深拷貝(deep copy):SerializationUtils
  • 淺拷貝(shallow copy):BeanUtils

思考

針對上面的業務場景我們也可以通過其他的方式統計商品銷量,可以再通過一個MQ去增加銷量的同時再去更新redis緩存,但是需要我們注意的是在針對一些核心業務數據和非核心業務數據盡量不要共用一個消費者組,防止影響核心數據的消費速率。同時我們在做設計的時候多想想這么做有什么優點,又有什么缺點,開發成本問題等。

其實在其他的地方我們可以用到原型模式,比如我們在發松活動的PUSH通知,針對平臺百萬、千萬、甚至上億的用戶發送通知的時候通知的內容基本都是一樣的只是推送用戶不一樣或者有些特別字段值的小改動,那我們這里就可以用原型模式來做,同時開啟多線程來做push,需要注意的是這里的線程安全問題,所以在每個線程內部去做copy對象。

總結

原型模式使用起來簡單,但是在我們每次在clone基類或者有引用對象的時候需要我們去修改原型對象的clone方法,這不符合我們開閉原則。

在一般情況下是不建議用這種模式的除非創建的對象成本特別大,或者在一些特殊場景使用,最后針對一些不常用的模式我不會詳細跟大家分享,但是我會在后面做個分享總結,后面開始為大家分享行為型模式。

我是敖丙,你知道的越多,你不知道的越多,我們下期見!

 

責任編輯:姜華 來源: 三太子敖丙
相關推薦

2020-10-21 14:29:15

原型模式

2021-10-28 19:09:09

模式原型Java

2013-11-26 17:00:08

Android設計模式

2022-09-21 08:47:05

項目多線程對象

2023-08-08 20:13:36

設計模式原型模式

2021-06-07 09:51:22

原型模式序列化

2020-06-08 08:04:49

設計模式結構型接口

2015-06-08 09:05:10

Java原型模式

2020-08-03 08:24:26

原型模式拷貝

2024-12-27 15:10:16

設計模式原型模式場景

2025-01-20 09:03:41

項目Error優化

2023-07-13 09:28:29

設計模式.NET

2016-06-07 14:28:39

Javascript原型

2021-02-01 10:01:58

設計模式 Java單例模式

2021-04-19 21:25:48

設計模式到元

2023-11-02 21:11:11

JavaScript設計模式

2022-01-12 13:33:25

工廠模式設計

2023-05-04 08:47:31

命令模式抽象接口

2020-08-21 07:23:50

工廠模式設計

2020-11-04 08:54:54

狀態模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人 在线| 久久免费小视频 | 超碰97免费观看 | 欧美8一10sex性hd| 亚洲精品av在线 | 中文天堂在线一区 | 欧美激情在线精品一区二区三区 | 国产精品v| 午夜av成人 | 久草在线在线精品观看 | 日韩一区二区三区视频 | 亚洲视频欧美视频 | 欧美视频1 | 日韩成人在线电影 | www.99热 | 国产成人精品一区二 | 少妇特黄a一区二区三区88av | 中文字幕在线视频观看 | 日韩一区中文字幕 | 国产精品久久久久久久久久三级 | 综合久久久久久久 | 国产一级片网站 | 国产蜜臀97一区二区三区 | 国产精品精品久久久 | 久久精品亚洲精品国产欧美 | 国产亚洲精品成人av久久ww | www.日韩欧美 | 日韩一区二区三区视频在线播放 | 亚洲日产精品 | 久亚州在线播放 | 国产精品不卡一区 | 亚洲精品福利视频 | 精品成人免费一区二区在线播放 | 在线区| 久久国产精品一区二区三区 | 欧美成年黄网站色视频 | 欧美天堂 | 色资源在线观看 | 亚洲最大av网站 | 国产一区二区三区免费观看视频 | 91偷拍精品一区二区三区 |