国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

一文分清Java開發(fā)中容易混淆的四大設計模式

原創(chuàng)
開發(fā) 前端
為什么先說工廠模式呢?因為“工廠”這個概念在我們代碼中到處都體現(xiàn)著,很多設計模式也離不開它,以它作為基礎演進,所以先要學習它。什么是“工廠”?就像我們生活中的工廠是一樣的,就是生產(chǎn)某些“物品”的地方。

作者 | 蔡柱梁

可能很多人認為設計模式只有面試時用到,這也不能算錯吧。但是如果僅僅只是面試時背背八股文,在實際工作中遇到了應該使用,卻不知道要用,那么你的代碼能有多好也是自欺欺人的了。那么什么時候應該使用設計模式呢?

換個角度說吧,大家覺得設計模式是怎么出來的?其實就是大牛們寫代碼多了,覺得一些高度重復或相似的地方,可以做到更好的“高內(nèi)聚”,“低耦合”。他們不斷改進,然后對他們的這些設計思路進行總結,最后得到的就是我們現(xiàn)在的設計模式。本文就給大家介紹幾個常用的設計模式。

1.工廠模式

為什么先說工廠模式呢?因為“工廠”這個概念在我們代碼中到處都體現(xiàn)著,很多設計模式也離不開它,以它作為基礎演進,所以先要學習它。什么是“工廠”?就像我們生活中的工廠是一樣的,就是生產(chǎn)某些“物品”的地方。

在 Java 代碼中,我們用各式各樣的對象做各種事情,而這個過程中,我們往往是不關心創(chuàng)建過程的,僅僅關注它有那些方法可使用,提供了什么功能。這時,我們可以使用工廠模式進行解耦——創(chuàng)建的行為放在工廠里,而使用的人專注于使用工廠產(chǎn)生的工具。在下面的模板方法、策略模式、適配器模式中,都能看到工廠模式的身影。

我們所說的工廠模式一般有兩種:

  • 工廠方法
  • 抽象工廠

(1)工廠方法

工廠方法模式是一種創(chuàng)建型設計模式, 其在父類中提供一個創(chuàng)建對象的方法, 允許子類決定實例化對象的類型。

工廠方法的具體實現(xiàn)思路是:

  • 制定一個創(chuàng)建對象 A 的接口工廠
  • 這個工廠的實現(xiàn)類構建 A 的子類,如:A1、A2、A3……

通過這種方式實現(xiàn)對象和對象的創(chuàng)建的分離,可能覺得很雞肋吧?下面通過場景對比說明它的好處。

用傳統(tǒng)做法與使用了工廠方法的場景對比:

  • 傳統(tǒng)寫代碼
  • 我需要用到某個類,比如 A1,我就 new A1 出來,然后進行業(yè)務操作。有一天產(chǎn)品告訴我這段邏輯需要增加一個 A2 的業(yè)務操作邏輯,我就得通過條件判斷增加邏輯??墒?A1 和 A2 在業(yè)務抽象上是一致的,僅僅是實現(xiàn)細節(jié)不同(舉個例子:好比運輸,我用貨車運輸是運輸,我用火車運輸也是運輸,也就是說運輸是目的,我的實現(xiàn)方式可以多樣化)。這時,通過 if/else 或 switch 來寫就不符合開閉原則了。
  • 用了工廠方法寫代碼
  • 我代碼上一開始就寫著是運輸工具,用這個運輸工具運輸(注意這里是抽象概念運輸工具而已)。這樣,我就可以根據(jù)業(yè)務計算得到的條件(如:公路/鐵路/海運/空運)丟給工廠,工廠給我返回具體的運輸工具就行(反正子類能強轉成父類)。

使用了工廠方法后,我的業(yè)務代碼不需要關注具體的運輸工具是什么,然后再去看它怎么運輸,后續(xù)產(chǎn)品加再多運輸工具,transport()的這段代碼都不會被干擾,符合了開閉原則。

偽代碼如下:


public interface TransportToolFactory {
TransportTool createTool();
}

public class TruckTransportToolFactory implements TransportToolFactory {
@Override
public TransportTool createTool() {
...
}
}

public class BoatTransportToolFactory implements TransportToolFactory {
@Override
public TransportTool createTool() {
...
}
}

public class Transport {
private TransportToolFactory factory;

public Transport(int way) {
if (way == 0) {
factory = new TruckTransportToolFactory();
}
...
}

public void transport() {
TransportTool tool = factory.createTool();
// 繼續(xù)業(yè)務處理
}
}

簡單說下“簡單工廠”,偽代碼如下:

public void transport() {
int way = getWay();// 經(jīng)過計算也好,前端傳過來也好,反正得到了具體的運輸方式
TransportTool tool = new TransportToolFactory(way).createTool();
// 繼續(xù)業(yè)務處理
}

public TransportTool createTool() {
if (way == 0) {
// 貨車
}
...
}

不過簡單工廠的缺點很明顯:

沒有做到單一職責,從上面的例子不難看出,汽車、輪船、飛機、大炮都包了,如果業(yè)務足夠復雜,這個工廠類真的是誰維護誰知道!

(2)抽象工廠

抽象工廠模式是一種創(chuàng)建型設計模式, 它能創(chuàng)建一系列相關的對象, 而無需指定其具體類。

在我看來,JDBC 對抽象工廠模式的應用就十分經(jīng)典。DB 有很多種,但是在不同的公司選擇可能都不太一樣,有些是 MySQL,有些是 Oracle,甚至有些是 SQL Sever 等等。但是對于我們開發(fā)而言,這些都是 DB,如果它們的連接,提交事務,回滾事務等細節(jié)都需要我們注意的話(不同 DB 的具體實現(xiàn)處理會有差異),這顯然是很麻煩的,而且我們也不關心。我們要的只是使用 Connection 創(chuàng)建 Session,Session 開啟事務等等。

如果有一個類可以將這一系列共性的行為都提取出來(如連接,事務處理等),我們只要使用這個抽象類和它提供的方法就好了。事實上,JDBC 也的確是這么做的,我們在配置好具體的數(shù)據(jù)庫配置后,在代碼上只要用接口 Factory 創(chuàng)建連接、會話,開啟事務……

首先,連接是個對象,會話也是對象,事務也是,創(chuàng)建這些對象的方法都抽象到一個工廠里面,而這個工廠本身也只是一個接口定義,這就是所謂的抽象工廠;如果這時我使用的是MySQL,那么剛剛羅列的那些對象都是MySQL定制化的一系列相關對象,這就是所謂的“能創(chuàng)建一系列相關的對象”。

2.模板方法模式

模板方法模式是一種行為設計模式,它在超類中定義了一個算法的框架, 允許子類在不修改結構的情況下重寫算法的特定步驟。

模板方法的核心在于抽象上行為性質(zhì)一樣,實際行為上有差別。

舉個例子:

我們產(chǎn)品常常要收集各式各樣的數(shù)據(jù)來分析用戶行為。有時他們?yōu)榱诵蕰o開發(fā)一堆電子文檔(如 CSV、DOC、TXT等等,這些文檔記錄著類似的數(shù)據(jù),但是數(shù)據(jù)結構肯定是不同的),讓開發(fā)按照他們要求開發(fā)個系統(tǒng)功能可以導入,按他們的要求統(tǒng)計這些數(shù)據(jù)。

對于開發(fā)而言,代碼是差不多的,都要導入文件,解析文件,邏輯計算后入庫。偏偏我們導入文件后,解析文件代碼不同,邏輯計算有時也會有差異,但是對于最后一步落庫卻大概率是一樣的。對于這種類型的業(yè)務場景,我們可以定個類去規(guī)定好這些流程,上游調(diào)用時就是調(diào)用我這個類的子類,子類會根據(jù)自己的業(yè)務場景重寫自己需要的流程節(jié)點的邏輯。

3.策略模式

策略模式是一種行為設計模式, 它能讓你定義一系列算法, 并將每種算法分別放入獨立的類中, 以使算法的對象能夠相互替換。

舉例子說明:

我們接入一個審批流組件,我們自己后臺也要留一份提審的記錄(方便查詢和回溯),現(xiàn)在我們希望我們做的這個功能通用性要強一些,也就是可以做到讓其他功能想加入這個審批流程就加入,如:功能鑒權的授權,工作流配置等等。

那么一開始審批時,一定是只有提審數(shù)據(jù),而我們的鑒權授權或者工作流配置肯定是沒生成到對應表的,只有審批通過后才會真的授權或者生成配置。這時問題來了,當工作流組件回調(diào)我們,難道我們每加入一個就 copy 上一個功能的回調(diào)代碼,刪掉修改審批狀態(tài)后的代碼,改改就好了嗎?這里得冗余多少代碼,哪怕你修改審批流的代碼抽取成一個方法,你也會發(fā)現(xiàn)每個回調(diào)方法里都有你那個方法。

具體偽代碼如下:

public class CallBack {
public void callback1(Param param) {
// 查詢審批記錄的合法性

// 修改審批記錄

// 處理業(yè)務邏輯1
}
public void callback1(Param param) {
// 查詢審批記錄的合法性

// 修改審批記錄

// 處理業(yè)務邏輯2
}
......
}

這種場景我們可以使用策略模式優(yōu)化,我們將處理業(yè)務邏輯當成個算法對象抽離出來,不同業(yè)務場景的回調(diào)業(yè)務處理器實現(xiàn)這個抽離接口,用策略自動分配對應的處理器即可。

偽代碼如下:

public class CallBack {
private Strategy strategy = new Strategy();
public void callback(Param param) {
// 查詢審批記錄的合法性

// 修改審批記錄

// 處理業(yè)務邏輯
strategy.getHandle(param.getServiceName()).invokeHandle();
}
}
public class Strategy {
private Map<String, Iservice> map;

static {
map = new HashMap<String, Iservice>();
map.put("Service1", new Service1());
map.put("Service2", new Service2());
......
}

public Iservice getHandle(String serviceName) {
return map.get(serviceName);
}
}
public class Service1 implements Iservice {
@Override
public void invokeHandle() {
...
}
}
public class Service2 implements Iservice {
@Override
public void invokeHandle() {
...
}
}
......

4.適配器模式

適配器模式是一種結構型設計模式, 它能使接口不兼容的對象能夠相互合作。

說到適配器,我想大家很快就想到了一個場景:

我們家庭的標準電壓是220V左右(實際會有點誤差),我們大家電自然需要這么高的電壓才能工作,但是我們小家電呢?如:手機充電,電腦等等。這些小家電往往都會有個“中介”——適配器去幫他們將標準電壓轉化成他們的適用電壓。

其實我們的適配模式也是一樣的。這里我們來看下 Spring 的實戰(zhàn)使用,上源碼:


/**
* Extended variant of the standard {@link ApplicationListener} interface,
* exposing further metadata such as the supported event and source type.
*
* <p>As of Spring Framework 4.2, this interface supersedes the Class-based
* {@link SmartApplicationListener} with full handling of generic event types.
*
* @author Stephane Nicoll
* @since 4.2
* @see SmartApplicationListener
* @see GenericApplicationListenerAdapter
*/
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
...

在 4.2 版本之前,Spring 監(jiān)聽觸發(fā)事件的監(jiān)聽器使用的是 ApplicationListener,經(jīng)過這么多迭代后,它想增強下該功能,所以又定義了一個 GenericApplicationListener。但是這里有個問題,以前實現(xiàn) ApplicationListener 的那些子類也還是要兼容的!!!全部重寫,那很累人;不兼容,作為高熱度的開源框架,這是不能接受的。這時,Spring 的作者就采用了適配模式,具體應用代碼如下:

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// 我們都知道 spring 的廣播事件都是是用了這個接口,我們看下 spring 是怎么做兼容的
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 重點在這 getApplicationListeners(event, type),看看他們是怎么 get 這個 list 的
// getApplicationListeners 是父類 AbstractApplicationEventMulticaster 的方法
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
}

AbstractApplicationEventMulticaster#getApplicationListeners 里面做了大量的性能優(yōu)化,不是本文的重點,所以這里跳過了。大家只要知道它第一次拿的地方是:

AbstractApplicationEventMulticaster#retrieveApplicationListeners 。

這就夠了,而這個方法里面給 list 添加元素的方法是:

AbstractApplicationEventMulticaster#supportsEvent(ApplicationListener, ResolvableType, Class),這才是我們要看的代碼。

protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
// 這里先看下這個 listener 是不是 GenericApplicationListener 的子類
// 不是就轉化成 GenericApplicationListener,這樣以前 ApplicationListener 的子類就能被兼容了
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

5.總結

希望上面的幾個設計模式的應用例子能給大家一點啟發(fā),能在自己工作中找到共同點去嘗試應用。不過,也不要濫用設計模式,因為一些剛起步的公司,業(yè)務方向也還不穩(wěn)定,很難去抽取共同的抽象部分又或者由于業(yè)務太簡單了,造成了過度設計,這些都是不可取的。

作者介紹

蔡柱梁,51CTO社區(qū)編輯,從事Java后端開發(fā)8年,做過傳統(tǒng)項目廣電BOSS系統(tǒng),后投身互聯(lián)網(wǎng)電商,負責過訂單,TMS,中間件等。

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2020-04-07 09:21:45

MySQL數(shù)據(jù)庫SQL

2022-06-29 11:28:57

數(shù)據(jù)指標體系數(shù)據(jù)采集

2025-01-03 09:30:01

2024-02-26 11:52:38

代理模式設計

2024-01-29 12:22:07

設計模式策略模式

2024-02-19 13:11:38

門面模式系統(tǒng)

2023-05-22 13:27:17

2024-02-27 11:59:12

享元模式對象

2024-02-04 12:04:17

2024-02-21 12:24:33

模板設計模式框架

2024-01-30 13:15:00

設計模式責任鏈

2024-02-23 12:11:53

裝飾器模式對象

2022-09-21 16:56:16

設計模式微服務架構

2023-11-02 13:33:00

Python數(shù)據(jù)結構

2024-12-31 10:36:40

AIAgent場景

2024-02-20 12:09:32

模式工廠方法接口

2024-02-22 12:13:49

適配器模式代碼

2024-02-18 12:36:09

2018-07-06 05:05:07

2010-09-15 13:35:25

SwingHibernateStruts
點贊
收藏

51CTO技術棧公眾號

欧洲av在线精品| 亚洲成人精品视频| 亚洲精品欧美极品| 狂野欧美性猛交xxxx| 亚洲制服丝袜在线| 在线播放 亚洲| 久久一区二区中文字幕| 亚洲人午夜精品免费| 欧美狂欢多p性派对| 久久精品国产免费| 国产欧美日韩精品在线观看| 亚洲啊v在线| 欧美性猛xxx| 99蜜桃臀久久久欧美精品网站| 欧美粗暴jizz性欧美20| 免费97视频在线精品国自产拍| 在线看的av网站| 最新中文字幕一区二区三区| 日韩精品第1页| 亚洲精品在线二区| 国产欧美一区二区三区久久| 99久久99九九99九九九| 欧美一级国产精品| 在线小视频网址| 久久综合视频网| 在线观看日韩羞羞视频| 亚洲成色精品| 91久久久久久久久久久久久| 精品国产乱子伦一区二区| 中文字幕欧美视频在线| 青青草视频在线免费直播| 色狠狠一区二区三区香蕉| 国产国产人免费人成免费视频| 99精品久久99久久久久| 六月婷婷激情综合| 国产麻豆午夜三级精品| 日韩av电影免费播放| 黄色亚洲精品| 99电影在线观看| 欧美日韩国产在线观看网站 | 亚洲男人影院| 国产欧美 在线欧美| 国产成人一区| 国产精品成人国产乱一区| 欧美男男gaytwinkfreevideos| 久久久久久久久国产| 激情五月综合婷婷| 美女av一区二区| 99久久这里有精品| 欧美国产视频日韩| 欧洲亚洲成人| 日韩av电影在线播放| 女优一区二区三区| 国产一区欧美二区三区| 国产精品videosex性欧美| 亚洲一区中文字幕| 99亚洲伊人久久精品影院红桃| 精品国产乱码久久久久久108| 亚洲成人在线| 日本午夜精品一区二区| 日本亚洲天堂网| 天天操天天干天天玩| 懂色av一区二区在线播放| 少妇av一区二区三区无码| 久久综合色之久久综合| 二区中文字幕| 日本韩国精品一区二区在线观看| 国产二区视频在线观看| 91麻豆精品国产91久久久| av福利在线导航| 亚洲午夜精品久久久久久久久久久久 | 自拍视频国产精品| 91成人入口| 国产精品影院在线观看| 亚洲深夜av| 免费不卡av在线| 中文字幕国产精品一区二区| 性网站在线免费观看| 欧美日本韩国一区二区三区视频| 天堂网在线最新版www中文网| 欧美精品在线观看| 青青一区二区三区| 亚洲成人第一| 国产精品国产精品国产专区不片| 在线亚洲电影| 日韩av网址在线观看| 大伊香蕉精品在线品播放| 99超碰麻豆| 丰满放荡岳乱妇91ww| 九色中文视频| 精品国产乱码久久久久久夜甘婷婷| 成人国产一区| 成人激情视频在线播放| 蜜桃av一区二区三区电影| 国产九九在线观看| 91精品国产乱码久久蜜臀| 久久69av| 欧美日韩在线观看一区二区三区| 成人av手机在线观看| 日本护士...精品国| 日韩在线观看网址| 欧美成人69av| 国产v亚洲v天堂无码久久久| 欧美日韩视频第一区| 国产精品亚洲欧美日韩一区在线| 国产高清精品一区| 国产欧美日本一区视频| 麻豆网站在线免费观看| 欧美激情一级精品国产| 美女日韩在线中文字幕| 日本wwwwwwwzzzzz视频| 日韩一区二区中文字幕| 高清日韩中文字幕| 在线观看日韩羞羞视频| 粉嫩av一区二区三区免费野| 99精品女人在线观看免费视频| 国产日韩精品一区观看| 亚洲欧美一区二区在线观看| 自拍偷拍亚洲视频| 国产99视频精品免费视频36| 欧美国产国产综合| 成人av三级| 久久精品二区| 亚洲线精品一区二区三区| 国产91亚洲精品久久久| 欧美一区1区三区3区公司 | 久久久久久久久久久99999| 国产视频三级在线观看播放| 国内精品400部情侣激情| 久久99精品国产麻豆婷婷洗澡| 伊人75在线| 国内精品久久影院| 成人免费视频视频| heyzo高清在线| 精品一区二区三区国产| 红桃视频成人在线观看| 加勒比视频一区| 噜噜噜久久亚洲精品国产品麻豆| 日韩女优av电影在线观看| 欧美成人69| 暖暖视频在线免费观看| 国产成人综合精品| 国产精品理论在线观看| 日本在线视频一区二区三区| 国产午夜精品视频一区二区三区| 欧美日韩国产首页在线观看| 国产精品国产一区| 黄页网址在线观看| 国产成人精品久久| 一区二区三区免费| 亚洲婷婷丁香| 成年人视频在线| 97视频在线免费观看| 久久久久国产一区二区三区四区 | 五月开心婷婷久久| 亚洲品质自拍| 国产xxxxx18| 日韩av片电影专区| 亚洲人成网站影音先锋播放| 中文字幕一区图| 午夜激情av在线| 91精品国产成人| 亚洲精品乱码久久久久久| 久本草在线中文字幕亚洲| www亚洲成人| 欧美一区二区三区免费视| 亚洲欧美另类久久久精品| 久久综合影院| 亚洲а∨精品天堂在线| 91在线免费视频| 日本道精品一区二区三区| 亚洲精品日韩久久| av2020不卡| 99国产精品白浆在线观看免费| 正在播放欧美视频| 99re6这里只有精品视频在线观看| 巨大黑人极品videos精品| 欧美日韩黄色一级片| 欧美激情在线观看视频| 亚洲欧洲精品一区二区三区| 精品日产免费二区日产免费二区| 中文在线最新版天堂8| 国产精品二区在线观看| 欧美一个色资源| 成人黄色在线看| 精品淫伦v久久水蜜桃| 天天影院图片亚洲| 日本在线免费观看一区| 一本大道久久加勒比香蕉| 久久精品一区二区三区不卡| 久久超碰99| 2024短剧网剧在线观看| 成人午夜精品久久久久久久蜜臀| 性欧美视频videos6一9| 欧美综合天天夜夜久久| 国产在线视频一区二区| 国产欧美三级电影| 中文字幕在线免费| 成年女人18级毛片毛片免费| 国产91免费看片|