網站首頁 編程語言 正文
一、動機(Motivation)
在軟件系統創建過程中,經常面臨著“某個對象”的創建工作:由于需求的變化,這個對象(的具體實現)經常面臨著劇烈的變化,但是它卻擁有比較穩定的接口。
如何應對這種變化?如何提供一種“封裝機制”來隔離出“這個易變對象”的變化,從而保持系統中“其他依賴對象的對象”不隨著需求改變而改變?
二、意圖(Intent)
定義一個用于創建對象的接口,讓子類決定實例化哪一個類。Factory Method使得一個類的實例化延遲到子類。——《設計模式》GoF
三、結構(Structure)
四、模式的組成
可以看出,在工廠方法模式的結構圖有以下角色:
(1)、抽象工廠角色(Creator):?充當抽象工廠角色,定義工廠類所具有的基本的操作,任何具體工廠都必須繼承該抽象類。
(2)、具體工廠角色(ConcreteCreator):充當具體工廠角色,該類必須繼承抽象工廠角色,實現抽象工廠定義的方法,用來創建具體產品。
(3)、抽象產品角色(Product):充當抽象產品角色,定義了產品類型所有具有的基本操作,具體產品必須繼承該抽象類。
(4)、具體產品角色(ConcreteProduct):充當具體產品角色,實現抽象產品類對定義的抽象方法,由具體工廠類創建,它們之間有一一對應的關系。
五、工廠方法模式的代碼實現
【簡單工廠模式】的問題是:如果有新的需求就需要修改工廠類里面創建產品對象實例的那個方法的實現代碼,在面向對象設計一個原則就是哪里有變化,我就封裝哪里。
為了應對改變,我們需要把Car先變成抽象類。
public abstract class Car
{
public abstract void startup();
public abstract void run();
public abstract void stop();
}
internal class BenzCar : Car
{
public override void startup()
{
Console.WriteLine("BenzCar Startup!");
}
public override void run()
{
Console.WriteLine("BenzCar Running!");
}
public override void stop()
{
Console.WriteLine("BenzCar Stopped!");
}
}
internal class HondaCar : Car
{
public override void startup()
{
Console.WriteLine("HondaCar Startup!");
}
public override void run()
{
Console.WriteLine("HondaCar Running!");
}
public override void stop()
{
Console.WriteLine("HondaCar Stopped!");
}
}
public abstract class CarFactory
{
public abstract Car CreatCar();
}
internal class BenzCarFactory : CarFactory
{
public override Car CreatCar()
{
return new BenzCar();
}
}
internal class HondaCarFactory : CarFactory
{
public override Car CreatCar()
{
return new HondaCar();
}
}
我們在客戶程序使用的時候,把所有的Car都換成抽象的AbstractCar,這樣客戶程序就不需要了解具體測試的是哪個Car了。客戶程序如下:
internal class CarTestFrameWork
{
public void DoTest(CarFactory carFactory)
{
Car car = carFactory.CreatCar();
car.startup();
car.run();
car.stop();
}
}
在應用程序調用的時候,傳入客戶程序的工廠應該是具體的HongqiCarFactory工廠。當想換具體Car的時候,只需要創建一個新的Car繼承自AbstractCar,并新建一個具體CarFactory工廠繼承自抽象CarFactory。然后在具體的應用中把具體的Car工廠參數修改即可。當然,完全可以讓具體應用的代碼也不用修改,把變化轉嫁到配置文件中去。
internal class Test
{
public static void Main()
{
CarTestFrameWork cf = new CarTestFrameWork();
cf.DoTest(new BenzCarFactory());
cf.DoTest(new HondaCarFactory());
}
}
六、Factory Method模式的幾個要點
Factory Method模式主要用于隔離類對象的使用者和具體類型之間的耦合關系。面對一個經常變化的具體類型,緊耦合關系會導致軟件的脆弱。
Factory Method模式通過面向對象的手法,將所要創建的具體對象工作延遲到子類,從而實現一種擴展(而非更改)的策略,較好地解決了這種緊耦合關系。
- Factory Method模式解決“單個對象”的需求變化;
- AbstractFactory模式解決“系列對象”的需求變化;
- Builder模式解決“對象部分”的需求變化;
1、工廠方法模式的優點:
(1)、 在工廠方法中,用戶只需要知道所要產品的具體工廠,無須關系具體的創建過程,甚至不需要具體產品類的類名。
(2)、在系統增加新的產品時,我們只需要添加一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。
2、工廠方法模式的缺點:
(1)、每次增加一個產品時,都需要增加一個具體類和對象實現工廠,是的系統中類的個數成倍增加,在一定程度上增加了系統的復雜度,同時也增加了系統具體類的依賴。這并不是什么好事。
3、工廠方法模式使用的場景:
(1)、一個類不知道它所需要的對象的類。在工廠方法模式中,我們不需要具體產品的類名,我們只需要知道創建它的具體工廠即可。
(2)、一個類通過其子類來指定創建那個對象。在工廠方法模式中,對于抽象工廠類只需要提供一個創建產品的接口,而由其子類來確定具體要創建的對象,在程序運行時,子類對象將覆蓋父類對象,從而使得系統更容易擴展。
(3)、將創建對象的任務委托給多個工廠子類中的某一個,客戶端在使用時可以無須關心是哪一個工廠子類創建產品子類,需要時再動態指定。
七、.NET中實現了工廠方法的類
.NET 類庫中也有很多實現了工廠方法的類,例如Asp.net中,處理程序對象是具體用來處理請求,當我們請求一個*.aspx的文件時,此時會映射到System.Web.UI.PageHandlerFactory類上進行處理,而對*.ashx的請求將映射到System.Web.UI.SimpleHandlerFactory類中(這兩個類都是繼承于IHttpHandlerFactory接口的),關于這點說明我們可以在“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Web.Config”文件中找到相關定義,具體定義如下:
<add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True"/> <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True"/> <add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True"/>
配置文件截圖了一部分,有時間大家可以自己去研究一下。
下面我們就具體看下工廠方法模式在Asp.net中是如何實現的,如果對一個Index.aspx頁面發出請求時,將會調用PageHandlerFactory中GetHandler方法來創建一個Index.aspx對象,它們之間的類圖關系如下:
原文鏈接:https://www.cnblogs.com/springsnow/p/11303491.html
相關推薦
- 2022-04-14 Django執行指定腳本的幾種方法_python
- 2022-06-09 Nginx隱藏式跳轉(瀏覽器URL跳轉后保持不變)_nginx
- 2022-05-25 yarn : 無法加載文件
- 2022-08-03 python判定文件目錄是否存在及創建多層目錄_python
- 2023-08-30 liunx shell腳本并發控制詳解
- 2022-09-02 docker搭建redis哨兵集群并且整合springboot的實現_docker
- 2022-09-09 python如何利用turtle繪制正方形_python
- 2022-04-22 electron設置最小大小和最大大小
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支