Java二十三設計模式之------工廠方法模式

一、工廠方法模式(Factory Method)

工廠方法模式有三種

1、普通工廠模式就是建立一個工廠類,對實現了同一接口的一些類進行實例的創建。首先看下關系圖:

舉例如下:(我們舉一個發送郵件和短信的例子)

首先,創建二者的共同接口:

  1. public?interface?Sender?{??
  2. ????public?void?Send();??
  3. }??

其次,創建實現類:

  1. public?class?MailSender?implements?Sender?{??
  2. ????@Override??
  3. ????public?void?Send()?{??
  4. ????????System.out.println("this?is?mailsender!");??
  5. ????}??
  6. }?
  1. public?class?SmsSender?implements?Sender?{??
  2. ??
  3. ????@Override??
  4. ????public?void?Send()?{??
  5. ????????System.out.println("this?is?sms?sender!");??
  6. ????}??
  7. }??

最后,建工廠類:

  1. public?class?SendFactory?{??
  2. ??
  3. ????public?Sender?produce(String?type)?{??
  4. ????????if?("mail".equals(type))?{??
  5. ????????????return?new?MailSender();??
  6. ????????}?else?if?("sms".equals(type))?{??
  7. ????????????return?new?SmsSender();??
  8. ????????}?else?{??
  9. ????????????System.out.println("請輸入正確的類型!");??
  10. ????????????return?null;??
  11. ????????}??
  12. ????}??
  13. }??

我們來測試下:

  1. public?class?FactoryTest?{??
  2. ??
  3. ????public?static?void?main(String[]?args)?{??
  4. ????????SendFactory?factory?=?new?SendFactory();??
  5. ????????Sender?sender?=?factory.produce("sms");??
  6. ????????sender.Send();??
  7. ????}??
  8. }??

輸出:this is sms sender!

2、多個工廠方法模式是對普通工廠方法模式的改進,在普通工廠方法模式中,如果傳遞的字符串出錯,則不能正確創建對象,而多個工廠方法模式是提供多個工廠方法,分別創建對象。關系圖:

將上面的代碼做下修改,改動下SendFactory類就行,如下:

public?class?SendFactory?{ ?
public?Sender?produceMail(){ ?
  1. ????????return?new?MailSender();??
  2. ????}??
  3. ??????
  4. ????public?Sender?produceSms(){??
  5. ????????return?new?SmsSender();??
  6. ????}??
  7. }??

測試類如下:

  1. public?class?FactoryTest?{??
  2. ??
  3. ????public?static?void?main(String[]?args)?{??
  4. ????????SendFactory?factory?=?new?SendFactory();??
  5. ????????Sender?sender?=?factory.produceMail();??
  6. ????????sender.Send();??
  7. ????}??
  8. }??

輸出:this is mailsender!

2.2、靜態工廠方法模式,將上面的多個工廠方法模式里的方法置為靜態的,不需要創建實例,直接調用即可。

  1. public?class?SendFactory?{??
  2. ??????
  3. ????public?static?Sender?produceMail(){??
  4. ????????return?new?MailSender();??
  5. ????}??
  6. ??????
  7. ????public?static?Sender?produceSms(){??
  8. ????????return?new?SmsSender();??
  9. ????}??
  10. }??
[java]?view plaincopy
  1. public?class?FactoryTest?{??
  2. ??
  3. ????public?static?void?main(String[]?args)?{??????
  4. ????????Sender?sender?=?SendFactory.produceMail();??
  5. ????????sender.Send();??
  6. ????}??
  7. }??

輸出:this is mailsender!

總體來說,工廠模式適合:凡是出現了大量的產品需要創建,并且具有共同的接口時,可以通過工廠方法模式進行創建。在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創建對象,第三種相對于第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。

3、抽象工廠模式(Abstract Factory)

工廠方法模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程序,必須對工廠類進行修改,這違背了閉包原則,所以,從設計角度考慮,有一定的問題,如何解決?就用到抽象工廠模式,創建多個工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。因為抽象工廠不太好理解,我們先看看圖,然后就和代碼,就比較容易理解。

請看例子:

  1. public?interface?Sender?{??
  2. ????public?void?Send();??
  3. }??

兩個實現類:

  1. public?class?MailSender?implements?Sender?{??
  2. ????@Override??
  3. ????public?void?Send()?{??
  4. ????????System.out.println("this?is?mailsender!");??
  5. ????}??
  6. }?
  1. public?class?SmsSender?implements?Sender?{??
  2. ??
  3. ????@Override??
  4. ????public?void?Send()?{??
  5. ????????System.out.println("this?is?sms?sender!");??
  6. ????}??
  7. }??

兩個工廠類:

  1. public?class?SendMailFactory?implements?Provider?{??
  2. ??????
  3. ????@Override??
  4. ????public?Sender?produce(){??
  5. ????????return?new?MailSender();??
  6. ????}??
  7. }?
  1. public?class?SendSmsFactory?implements?Provider{??
  2. ??
  3. ????@Override??
  4. ????public?Sender?produce()?{??
  5. ????????return?new?SmsSender();??
  6. ????}??
  7. }??

在提供一個接口:

  1. public?interface?Provider?{??
  2. ????public?Sender?produce();??
  3. }??

測試類:

  1. public?class?Test?{??
  2. ??
  3. ????public?static?void?main(String[]?args)?{??
  4. ????????Provider?provider?=?new?SendMailFactory();??
  5. ????????Sender?sender?=?provider.produce();??
  6. ????????sender.Send();??
  7. ????}??
  8. }??

其實這個模式的好處就是,如果你現在想增加一個功能:發及時信息,則只需做一個實現類,實現Sender接口,同時做一個工廠類,實現Provider接口,就OK了,無需去改動現成的代碼。這樣做,拓展性較好!

以上內容引自于 ? https://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html

轉載于:https://www.cnblogs.com/wuxinyiwu/p/8057645.html

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

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

相關文章

無法轉化為項目財富的技術或功能就是垃圾

技術人員可能有個習慣,也可以叫通病,發現一個新技術,或者新的想法,會把某個現有的東西做的更好,或者可以增加某個功能讓系統看上去更完美。 如果這是一個產品,那么大家都會鼓勵你去做,如果我們…

ibatis oracle function,IBATIS調用oracle function(函數)的步驟實例

IBATIS調用oracle function(函數)的方法實例引用create or replace function getClassifiedCode(p_planCode in varchar2 -- 險種代碼,p_usageAttributeCode in varchar2 -- 使用性質代碼,p_ownershipAttributeCode in varchar2 -- 所屬性質代碼,p_vehicleTypeCode in varchar2…

一元多項式乘法算法

我認為大致算法應該是這樣的: 首先準備一個空的鏈表L。利用第一個多項式的的指針所指的節點數值乘以多項式二的每一項,將結果保存在鏈表L中。 然后將指向該節點的指針后移到下一個節點繼續進行乘法運算,將所得結果加到L中(這個操作已經在一…

堆以及stl堆的使用

概念 性質: 1.堆是一顆完全二叉樹,用數組實現。 ???2.堆中存儲數據的數據是局部有序的。 最大堆:1.任意一個結點存儲的值都大于或等于其任意一個子結點中存儲的值。 ?????2.根結點存儲著該樹所有結點中的最大值。 最小堆:1.任意一個結…

讀【36歲IT老人再次隨筆】的讀后感,你會哪些計算機語言?

論壇首頁一篇:社區“揭穿最大謊言”事件 , 我看了,也順便看了里面另一位仁兄的【36歲IT老人再次隨筆】 其中關鍵的地方就是一個例子:你會哪些計算機語言? 這個問題很有意思,確實如網友回復里說到的&#xf…

php接收vue請求數據axios,詳解vue axios用post提交的數據格式

Content-type的幾種常見類型一、是什么?是Http的實體首部字段,用于說明請求或返回的消息主體是用何種方式編碼,在request header和response header里都存在。二、幾個常用類型:1、application/x-www-form-urlencoded這應該是最常見…

數據結構中的邏輯結構簡介

數據的邏輯結構是對數據之間關系的描述,有時就把邏輯結構簡稱為數據結構。邏輯結構形式地定義為(K,R)(或(D,S)),其中,K是數據元素的有限集&#x…

applicationContext配置文件模板1

<?xml version"1.0" encoding"utf-8"?> <beans      --整個配置文件的根節點&#xff0c;包含一個或多個bean元素 xmlns    --最基本的命名空間定義 xmlns:xsi  --最基本的命名空間定義 xmlns:context  --啟動自動掃描或注解裝配…

時間復雜度的一些計算規則

一些規則(引自&#xff1a;時間復雜度計算 ) 1) 加法規則 T(n,m) T1(n) T2(n) O (max ( f(n),g(m) ) 2) 乘法規則 T(n,m) T1(n) * T2(m) O (f(n) * g(m)) 3) 一個特例&#xff08;問題規模為常量的時間復雜度&#xff09; 在大O表示法里面有一個特例&#xff0c;如…

職場新人面試誤區:我的技術好,所以你必須要請我?

這個是論壇的一個帖子。 前幾天有家軟件公司聯系到我&#xff0c;去之前電話里跟他們的項目經理聊了兩句&#xff0c;什么都明白了就沒去面試 是老板先給我打的電話&#xff0c;問我做J2EE多久了&#xff0c;期望薪水什么個范圍。。。 然后老板說&#xff0c;你稍等&#xff…

Oracle 基礎

為什么80%的碼農都做不了架構師&#xff1f;>>> Oracle DB筆錄&#xff0c;以后會不斷Add&#xff0c;歡迎留言補充! --cmd.exe(你懂得!) --[1]多個數據庫實例&#xff0c;切換選擇DB后&#xff0c;登錄操作 set ORACLE_SIDorcl --選擇DB orcl(你的DB實例名) --可在…

Linux執行命令提示Password,linux expect遠程自動登錄以及執行命令

linux遠程自動登錄以及執行命令遠程登錄該自動登錄的過程是通過shell里面expect實現的&#xff0c;類似相當于開了一個類似于cmd的命令段輸出IP和密碼。注意該腳本能夠執行的前提是安裝了expectyum install -y expect直接上腳本&#xff1a;#!/usr/bin/expect …

雙塔

## 雙塔 題目描述 有n個數字&#xff0c;要求將這n個數字分成兩部分&#xff08;兩部分可以數字個數不同&#xff09;&#xff0c;使得兩部分數字之和的差最小 輸入輸出格式 輸入&#xff1a; 第一行為n 第二行有n個數&#xff0c;即題目中所描述那樣 輸出&#xff1a; 兩部分和…

時間復雜度計算雜記

算法時間復雜度的計算 [整理] 時間復雜度算法 基本的計算步驟 時間復雜度的定義 一般情況下&#xff0c;算法中基本操作重復執行的次數是問題規模n的某個函數&#xff0c;用T(n)表示&#xff0c;若有某個輔助函數f(n)&#xff0c;使得當n趨近于無窮大時&#xff0c;T(n)/f(n…

MyBatis 在xml文件中處理大于號小于號的方法

為什么80%的碼農都做不了架構師&#xff1f;>>> 第一種方法&#xff1a;用轉義字符&#xff08;注&#xff1a;對大小寫敏感&#xff01; &#xff09; 用了轉義字符把>和<替換掉&#xff0c;然后就沒有問題了。 SELECT * FROM test WHERE 1 1 AND start_da…

linux 進程間讀寫鎖,Linux系統編程—進程間同步

我們知道&#xff0c;線程間同步有多種方式&#xff0c;比如&#xff1a;信號量、互斥量、讀寫鎖&#xff0c;等等。那進程間如何實現同步呢&#xff1f;本文介紹兩種方式&#xff1a;互斥量和文件鎖。##互斥量mutex我們已經知道了互斥量可以用于在線程間同步&#xff0c;但實際…

程序員:開汽車,難道我要知道汽車的原理才能把車開好嗎?

一個網友的迷惑&#xff1a; 我工作&#xff15;年了&#xff0c;一直做&#xff2a;&#xff12;&#xff25;&#xff25;的項目&#xff0c;前幾天去面試&#xff0c;一個人問我JDBC有幾種連接方式&#xff0c;這個問題這么多年以來我從來沒有遇見過&#xff0c;不知道大家 …

杭州某知名xxxx公司急招大量java以及大數據開發工程師

因公司戰略以及業務拓展&#xff0c;收大量java攻城獅以及大數據開發攻城獅. 職位信息&#xff1a; java攻城獅: https://job.cnblogs.com/offer/56032 大數據開發攻城獅: https://job.cnblogs.com/offer/56033 歡迎博客園的XDJM自薦和推薦&#xff01; 此招聘長期有效 歡迎留言…

35.6. /etc/dnsmasq.d/dnsmasq.address.conf

vim /etc/dnsmasq.d/dnsmasq.address.confaddress/www.mydomain.com/172.16.0.254deny domain address/www.facebook.com/127.0.0.1 address/www.google.com/127.0.0.135.6.1. 域名劫持 將域名解析到錯誤的地址&#xff0c;這樣可以屏蔽一些網站。 address/www.facebook.com/12…

請求地址操作中的(int*)

例如 float b3.14,*a&b; int *p(int *)a; 表示將指針a的類型轉換為整型指針再賦給p。