《設計模式》工廠方法模式

1.工廠方法模式(Factory Method)定義

定義一個用于創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。

1.1 UML圖:

主要有4個對象:

  • 抽象工廠(Abstract Creator):提供一個創建產品的接口。調用者可以通過它訪問具體工廠的工廠方法。
  • 具體工廠(Concrete Creator):繼承自抽象工廠,并實現其創建對象的方法。
  • 抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能。
  • 具體產品(Concrete Product):實現了抽象產品中所定義的接口,由具體工廠來創建,與同具體工廠之間是一一對應的。
    在這里插入圖片描述

2.工廠方法模式舉例:

業務場景:需要實現一個商場收銀系統,有四種策略,

  1. 正常結賬
  2. 打折
  3. 滿減
  4. 先打折再滿減
    簡單工廠模式 -> 工廠方法模式:

簡單工廠模式UML圖:簡單工廠 + 策略模式 + 裝飾模式 具體實現邏輯,見裝飾模式 -> 2.裝飾模式舉例:
在這里插入圖片描述
工廠方法模式UML:策略模式 + 裝飾模式 + 工廠方法模式
在這里插入圖片描述

2.2 核心代碼:

ISale接口

public interface ISale {public double acceptCash(double price,int num);}

IFactory接口

public interface IFactory {public ISale createSalesModel(); //創建銷售模式}

CashContex:

public class CashContext {private ISale cs;   //聲明一個ISale接口對象//通過構造方法,傳入具體的收費策略public CashContext(int cashType){IFactory fs=null;switch(cashType) {case 1://原價fs = new CashRebateReturnFactory(1d,0d,0d);break;case 2://8折fs = new CashRebateReturnFactory(0.8d,0d,0d);break;case 3://7折fs = new CashRebateReturnFactory(0.7d,0d,0d);break;case 4://滿300100fs = new CashRebateReturnFactory(1,300d,100d);break;case 5://先打8,再滿300100fs = new CashRebateReturnFactory(0.8d,300d,100d);break;case 6://先滿20050,再打7折fs = new CashReturnRebateFactory(0.7d,200d,50d);break;}this.cs = fs.createSalesModel();}public double getResult(double price,int num){//根據收費策略的不同,獲得計算結果return this.cs.acceptCash(price,num);}
}

CashRebateReturnFactory

public class CashRebateReturnFactory implements IFactory {private double moneyRebate = 1d;private double moneyCondition = 0d;private double moneyReturn = 0d;public CashRebateReturnFactory(double moneyRebate,double moneyCondition,double moneyReturn){this.moneyRebate=moneyRebate;this.moneyCondition=moneyCondition;this.moneyReturn=moneyReturn;}//先打x折,再滿m返npublic ISale createSalesModel(){CashNormal cn = new CashNormal();CashReturn cr1 = new CashReturn(this.moneyCondition,this.moneyReturn);CashRebate cr2 = new CashRebate(this.moneyRebate);cr1.decorate(cn);   //用滿m返n算法包裝基本的原價算法cr2.decorate(cr1);  //打x折算法裝飾滿m返n算法return cr2;         //將包裝好的算法組合返回}
}

CashReturnRebateFactory

public class CashReturnRebateFactory implements IFactory {private double moneyRebate = 1d;private double moneyCondition = 0d;private double moneyReturn = 0d;public CashReturnRebateFactory(double moneyRebate,double moneyCondition,double moneyReturn){this.moneyRebate=moneyRebate;this.moneyCondition=moneyCondition;this.moneyReturn=moneyReturn;}//先滿m返n,再打x折public ISale createSalesModel(){CashNormal cn2 = new CashNormal();CashRebate cr3 = new CashRebate(this.moneyRebate);CashReturn cr4 = new CashReturn(this.moneyCondition,this.moneyReturn);cr3.decorate(cn2);  //用打x折算法包裝基本的原價算法cr4.decorate(cr3);  //滿m返n算法裝飾打x折算法return cr4;         //將包裝好的算法組合返回}
}

CashSuper

public class CashSuper implements ISale {protected ISale component;//裝飾對象public void decorate(ISale component) {this.component=component;}public double acceptCash(double price,int num){double result = 0d;if (this.component != null){//若裝飾對象存在,則執行裝飾的算法運算result = this.component.acceptCash(price,num);    }return result;}
}

CashReturn

public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利條件private double moneyReturn = 0d;    //返利值//返利收費。初始化時需要輸入返利條件和返利值。//比如“滿300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//計算收費時,當達到返利條件,就原價減去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return super.acceptCash(result,1);   }}

CashRebate

public class CashRebate extends CashSuper {private double moneyRebate = 1d;//打折收費。初始化時必需輸入折扣率。八折就輸入0.8public CashRebate(double moneyRebate){this.moneyRebate = moneyRebate;}//計算收費時需要在原價基礎上乘以折扣率public double acceptCash(double price,int num){double result = price * num * this.moneyRebate;return super.acceptCash(result,1);}}

CashNormal

public class CashNormal implements ISale {//正常收費,原價返回public double acceptCash(double price,int num){return price * num; }    
}

DemoTest

public class Demotest {public static void main(String[] args){System.out.println("**********************************************");System.out.println("工廠方法模式");System.out.println();int discount = 0; 		//商品折扣模式double price = 0d; 		//商品單價int num = 0;			//商品購買數量double totalPrices = 0d;//當前商品合計費用double total = 0d;		//總計所有商品費用Scanner sc = new Scanner(System.in);do {System.out.println("商品折扣模式如下:");System.out.println("1.正常收費");System.out.println("2.打八折");System.out.println("3.打七折");System.out.println("4.滿300送100");System.out.println("5.先打8折,再滿300送100");System.out.println("6.先滿200送50,再打7折");System.out.println("請輸入商品折扣模式:");discount = Integer.parseInt(sc.nextLine());System.out.println("請輸入商品單價:");price = Double.parseDouble(sc.nextLine());System.out.println("請輸入商品數量:");num = Integer.parseInt(sc.nextLine());System.out.println();if (price>0 && num>0){//根據用戶輸入,將對應的策略對象作為參數傳入CashContext對象中CashContext cc = new CashContext(discount);//通過Context的getResult方法的調用,可以得到收取費用的結果//讓具體算法與客戶進行了隔離totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println();System.out.println("單價:"+ price + "元 數量:"+ num +" 合計:"+ totalPrices +"元");System.out.println();System.out.println("總計:"+ total+"元");System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

輸出結果:
在這里插入圖片描述

3. 工廠方法模式的優缺點;

  • 優點:
    • 可以避免創建者和具體產品之間的緊密耦合,針對工廠接口編程,而并非具體實現類。
    • 單一職責原則。可以將產品創建代碼放在程序的單一位置,從而使得代碼更容易維護。
    • 開閉原則。無需更改現有客戶端代碼,就可以在程序中引入新的產品類型。
  • 缺點:
    • 每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,增加了系統的復雜度。

4. 總結

  • 通常我們把被創建的對象稱之為【產品】, 創建【產品】的對象稱為【工廠】。
  • 當產品比較固定且數量少的情況下,只需要一個工廠類就可以,稱之為【簡單工廠】, 多個工廠時,就稱為工廠方法模式,其中工廠方法使一個類的實例化延遲到其子類,而簡單工廠實例化就是在唯一工廠類

5.參考

  • https://www.cnblogs.com/mklblog/p/18029716

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

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

相關文章

冒泡排序——簡單理解和使用

閱前聲明:如果想直接了解冒泡排序的簡化思想,請跳至文章尾部在介紹之前,我們先看一個用到該功能的實戰訓練(本人也是從中開始認識到冒泡排序這個函數定義)對于小白來說,我的思路如下:1.題目中涉…

AI應用商業化加速落地 2025智能體爆發與端側創新成增長引擎

今年以來,人工智能 (AI) 正在進入從算力投入到云服務消耗再到商業化收入,最終回到算力再投入的良性循環,而 AI 應用的起量正是推動這一飛輪效應的關鍵。7 月 31 日,國務院常務會議審議通過了《關于深入實施 “人工智能 ” 行動的意…

Pytest測試框架基礎及進階

Pytest測試框架基礎# Pytest測試框架介紹# Pytest是Python一款三方測試框架,用于編寫和運行單元測試、集成測試和功能測試。Pytest測試框架具有簡單、靈活、易于擴展等特點,被廣泛應用于Python項目的測試工作中。 Pytest主要特點: 簡單易用…

航空裝備先進加工工藝與制造技術論壇——2025成都航空裝備展

300參展企業 11500㎡展區面積 7大專業展區 12000觀眾規模15同期會議 160發言嘉賓 5000參會嘉賓 100媒體報道航空工業飛速發展,先進加工工藝與制造技術成為了支撐航空裝備性能提升、質量保障和產能優化的核心基石。為探索前沿技術路徑、凝聚行業創新力量,…

為什么品牌更愿意為新品打廣告?

品牌資源向新品廣告傾斜,可以說是市場上的普遍現象。尤其對于沒有明星產品的品牌而言,新品推廣時企業的重要曝光節點。下面就讓我們一同來了解下,為什么品牌更愿意為新品打廣告。一、市場需求更充分新品廣告往往承擔著市場教育的功能&#xf…

電子電氣架構 --- 關于整車信息安全的一些思考

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

報錯:Eplan無法打開數據庫的解決方法

詳細報錯信息:無法打開數據庫 E:\eplan\部件\Microsoft\ESS_part001.mdb。針對64位版本的EPLAN 平臺需要使用64位版本的Microsoft Office. 一、報錯及解決方法 報錯信息:無法打開數據庫 E:\eplan\部件\Microsoft\ESS_part001.mdb。針對64位版本的EPLAN 平…

深度學習篇---卷積核的權重

卷積核權重:在深度學習的卷積操作中,“卷積核的權重” 是最核心的概念之一,它決定了卷積核能從圖像中 “看到” 什么特征(比如邊緣、紋理,甚至是眼睛、車輪這樣的復雜結構)。我們可以把它理解成卷積核的 “…

SMTPman,smtp ssl助力安全高效郵件傳輸!

SMTPman,smtp ssl助力安全高效郵件傳輸!SMTPman,smtp ssl不僅僅是一種郵件協議方式,更是企業日常運營的重要支撐。通過SMTPman,smtp ssl,用戶可以獲得更快的投遞速度,更穩定的連接,以…

學習日志37 python

1 Python 和 Java 在類屬性(靜態屬性)和實例屬性的處理題目執行以下程序,輸出結果為() class Base(object):count 0def __init__(self):pass b1 Base() b2 Base() b1.count b1.count 1 print(b1.count,end" …

對于QPS的理解和簡單

QPS(Queries Per Second) 是衡量系統吞吐量的核心指標,表示每秒能處理的請求數量。以下是關于QPS的完整解析和實踐指南:一、QPS的核心公式 QPS 總請求量 / 請求總時間(秒)典型場景計算: 日請求…

【筆記ing】考試腦科學 腦科學中的高效記憶法

前言本書是拙作《高中生學習法》的修訂版。《高中生學習法》出版已有十余年。這期間,腦科學研究不斷進步,十幾年前無法解釋的事情現在已經開始逐漸明晰。同時,書中有些內容甚至已經被明確證實是錯誤的。也就是說,《高中生學習法》…

Web安全 - 構建安全可靠的API:基于國密SM2/SM3的文件上傳方案深度解析

文章目錄概述1. 緣起:挑戰與目標2 . 核心架構:非對稱簽名與摘要算法的珠聯璧合威脅模型(我們要防的攻擊)密鑰管理體系3 . 簽名與驗證:一步一解,安全閉環3.1 A系統:簽名的生成(請求前…

【MyBatis-Plus】一、快速入門

這里寫自定義目錄標題MyBatis-Plus 概述快速入門入門案例常用注解常見配置MyBatis-Plus 概述 MyBatis-Plus 簡介: MyBatis-Plus 是在 MyBatis 基礎上開發的一個 增強工具包,它簡化了 MyBatis 的開發,減少了大量重復代碼。它保持了 MyBatis …

PostgreSQL導入mimic4

一、PostgreSQL連接驗證 正確連接命令 使用psql工具連接目標數據庫,格式為:psql -h 127.0.0.1 -U 用戶名 -d 數據庫名 --password 示例(用戶名Shinelon,數據庫mimic):psql -h 127.0.0.1 -U Shinelon -d mi…

css中 hsl() 的用法

好的 👍 我來詳細介紹一下 CSS hsl() 的用法。1. 基本語法 color: hsl(hue, saturation, lightness);hue(色相) 取值范圍:0 ~ 360(角度值,代表色環的角度)0 或 360 → 紅色120 → 綠色240 → 藍…

企業級Spring事務管理:從單體應用到微服務分布式事務完整方案

企業級Spring事務管理:從單體應用到微服務分布式事務完整方案 🌟 你好,我是 勵志成為糕手 ! 🌌 在代碼的宇宙中,我是那個追逐優雅與性能的星際旅人。 ? 每一行代碼都是我種下的星光,在邏輯的土…

繼續記錄面試題

坐在工位,沒事干心慌的不行,可能也是房貸壓的。一閑下來就開始胡思亂想,無法沉下心去背那些八股文。這才剛剛接到離職通知第三天啊。而且、我還在坐班呢!!! 哎、怪不得有句老話說的,人窮志短&a…

從零開始學習:深度學習(基礎入門版)(第2天)

(一)在pycharm軟件中,用python語言,opencv庫實現以下功能(1.1)圖片的邊界填充核心流程:讀取原始圖像使用 cv2.imread() 加載名為 yueshan.png 的圖像文件統一邊界參數設定四周留白尺寸均為 50px(上下左右各…

HTTP協議-3-HTTP/2是如何維持長連接的?

先說結論:HTTP/2的“長連接” 一個TCP連接 多路復用 二進制幀 流控制 持久會話管理 它不只是“連接不斷”,更關鍵的是:在這個長連接上,可以同時并發傳輸成百上千個請求和響應,互不阻塞! 1、HTTP/2的“…