C# 工廠模式學習

工廠模式(Factory Pattern)是一種創建型設計模式,它提供了一種創建對象的接口,而不是通過具體類來實例化對象。工廠模式可以將對象的創建過程封裝起來,使代碼更具有靈活性和可擴展性。

工廠模式有幾種常見的實現方式:

  1. 簡單工廠模式(Simple Factory Pattern): 簡單工廠模式通過一個工廠類來決定創建哪種具體類的實例。這個工廠類通常提供一個靜態方法,根據傳入的參數創建相應的對象。

  2. 工廠方法模式(Factory Method Pattern): 工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法使一個類的實例化延遲到其子類。

  3. 抽象工廠模式(Abstract Factory Pattern): 抽象工廠模式提供一個接口,用于創建相關或依賴對象的家族,而無需明確指定具體類。通過使用抽象工廠模式,一個類可以實例化一組相關對象,而不需要知道它們的具體類。

簡單工廠模式示例

假設我們有一個動物園項目,需要創建不同的動物對象:

// 動物接口
public interface IAnimal
{void Speak();
}// 具體的動物類
public class Dog : IAnimal
{public void Speak(){Console.WriteLine("Woof!");}
}public class Cat : IAnimal
{public void Speak(){Console.WriteLine("Meow!");}
}// 簡單工廠類
public static class AnimalFactory
{public static IAnimal CreateAnimal(string animalType){switch (animalType.ToLower()){case "dog":return new Dog();case "cat":return new Cat();default:throw new ArgumentException("Unknown animal type");}}
}// 使用示例
class Program
{static void Main(string[] args){IAnimal animal = AnimalFactory.CreateAnimal("dog");animal.Speak();  // 輸出:Woof!}
}

工廠方法模式示例

假設我們有一個動物園項目,不同的子類需要創建不同的動物對象:

// 動物接口
public interface IAnimal
{void Speak();
}// 具體的動物類
public class Dog : IAnimal
{public void Speak(){Console.WriteLine("Woof!");}
}public class Cat : IAnimal
{public void Speak(){Console.WriteLine("Meow!");}
}// 工廠接口
public interface IAnimalFactory
{IAnimal CreateAnimal();
}// 具體工廠類
public class DogFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Dog();}
}public class CatFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Cat();}
}// 使用示例
class Program
{static void Main(string[] args){IAnimalFactory factory = new DogFactory();IAnimal animal = factory.CreateAnimal();animal.Speak();  // 輸出:Woof!}
}

抽象工廠模式示例

假設我們有一個動物園項目,需要創建一組相關的對象(例如,動物及其食物):

// 動物接口
public interface IAnimal
{void Speak();
}// 具體的動物類
public class Dog : IAnimal
{public void Speak(){Console.WriteLine("Woof!");}
}public class Cat : IAnimal
{public void Speak(){Console.WriteLine("Meow!");}
}// 食物接口
public interface IFood
{void Get();
}// 具體的食物類
public class DogFood : IFood
{public void Get(){Console.WriteLine("Dog food");}
}public class CatFood : IFood
{public void Get(){Console.WriteLine("Cat food");}
}// 抽象工廠接口
public interface IAnimalFactory
{IAnimal CreateAnimal();IFood CreateFood();
}// 具體工廠類
public class DogFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Dog();}public IFood CreateFood(){return new DogFood();}
}public class CatFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Cat();}public IFood CreateFood(){return new CatFood();}
}// 使用示例
class Program
{static void Main(string[] args){IAnimalFactory factory = new DogFactory();IAnimal animal = factory.CreateAnimal();IFood food = factory.CreateFood();animal.Speak();  // 輸出:Woof!food.Get();      // 輸出:Dog food}
}

以上是三種工廠模式的基本示例,可以根據具體需求選擇合適的工廠模式來實現代碼的創建和管理。如果希望在增加新動物類型時盡量減少對現有類的修改,推薦使用工廠方法模式。工廠方法模式的設計使得每新增一種動物,只需增加一個對應的工廠類和具體的動物類,而無需修改已有的代碼,從而符合開閉原則(即對擴展開放,對修改關閉)。

使用工廠方法模式

下面是一個更完善的工廠方法模式示例,展示了如何在增加新動物時,盡量減少對現有代碼的修改。

// 動物接口
public interface IAnimal
{void Speak();
}// 具體的動物類
public class Dog : IAnimal
{public void Speak(){Console.WriteLine("Woof!");}
}public class Cat : IAnimal
{public void Speak(){Console.WriteLine("Meow!");}
}// 新增的動物類
public class Bird : IAnimal
{public void Speak(){Console.WriteLine("Tweet!");}
}// 工廠接口
public interface IAnimalFactory
{IAnimal CreateAnimal();
}// 具體工廠類
public class DogFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Dog();}
}public class CatFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Cat();}
}// 新增的動物工廠類
public class BirdFactory : IAnimalFactory
{public IAnimal CreateAnimal(){return new Bird();}
}// 使用示例
class Program
{static void Main(string[] args){List<IAnimalFactory> factories = new List<IAnimalFactory>{new DogFactory(),new CatFactory(),new BirdFactory()  // 新增的工廠只需在這里添加};foreach (var factory in factories){IAnimal animal = factory.CreateAnimal();animal.Speak();}}
}

在這個示例中,新增一種動物只需:

  1. 創建新的具體動物類,例如?Bird
  2. 創建對應的工廠類,例如?BirdFactory
  3. 在使用的地方添加新的工廠實例,例如在?factories?列表中添加?new BirdFactory()

這樣做的好處是每增加一個新動物類型,不需要修改現有的工廠類或具體的動物類,只需要添加新的類和工廠即可,從而降低了代碼修改的風險和復雜度。

使用反射和配置來進一步減少修改

如果希望在增加動物時連代碼都不需要改動,可以考慮使用反射和配置文件的方式。通過配置文件定義動物類型和對應的工廠類,然后使用反射動態加載:

// 動物接口和具體的動物類(同上)// 工廠接口和具體工廠類(同上)// 使用反射加載工廠類
class Program
{static void Main(string[] args){// 假設配置文件中定義了動物類型和對應的工廠類var factoryTypes = new List<string>{"DogFactory","CatFactory","BirdFactory"  // 配置文件中新增的工廠類};var factories = new List<IAnimalFactory>();foreach (var factoryType in factoryTypes){var type = Type.GetType(factoryType);if (type != null && typeof(IAnimalFactory).IsAssignableFrom(type)){var factory = (IAnimalFactory)Activator.CreateInstance(type);factories.Add(factory);}}foreach (var factory in factories){IAnimal animal = factory.CreateAnimal();animal.Speak();}}
}

接口與繼承結合使用

工廠模式主要使用了接口、繼承,在C#中,接口和繼承是面向對象編程的重要概念。接口定義了一組方法和屬性,而繼承允許一個類從另一個類繼承其成員。接口可以實現多重繼承,而類只能繼承一個基類。通常情況下,接口和繼承可以結合使用,以充分利用它們各自的優點。通過這種方式,基類可以提供一些通用的實現,而接口可以定義特定的行為。

// 接口
public interface IAnimal
{void Speak();void Eat();
}// 基類
public class Animal
{public void Sleep(){Console.WriteLine("Sleeping...");}
}// 派生類實現接口
public class Dog : Animal, IAnimal
{public void Speak(){Console.WriteLine("Woof!");}public void Eat(){Console.WriteLine("Dog is eating.");}
}public class Cat : Animal, IAnimal
{public void Speak(){Console.WriteLine("Meow!");}public void Eat(){Console.WriteLine("Cat is eating.");}
}// 使用示例
class Program
{static void Main(string[] args){IAnimal dog = new Dog();dog.Speak(); // 輸出:Woof!dog.Eat();   // 輸出:Dog is eating.IAnimal cat = new Cat();cat.Speak(); // 輸出:Meow!cat.Eat();   // 輸出:Cat is eating.// 使用基類方法Animal animalDog = (Animal)dog;animalDog.Sleep(); // 輸出:Sleeping...Animal animalCat = (Animal)cat;animalCat.Sleep(); // 輸出:Sleeping...}
}

總結

  • 接口:定義了一組必須實現的方法和屬性,沒有實現代碼。支持多重繼承,使得類可以實現多個接口。
  • 繼承:用于從現有類創建新類,繼承基類的成員。每個類只能有一個基類,但可以實現多個接口。
  • 結合使用:通過將接口和繼承結合使用,可以實現代碼的高復用性和靈活性。

通過上述示例,可以看到如何使用接口和繼承來設計靈活且可擴展的應用程序結構。這樣既能充分利用基類的通用功能,又能通過接口實現特定的行為。

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

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

相關文章

Go 如何通過 Kafka 客戶端庫 生產與消費消息

文章目錄 0.前置說明1. confluent-kafka-go2. sarama3. segmentio/kafka-go4. franz-go選擇建議 1.啟動 kafka 集群2.安裝 confluent-kafka-go 庫3.創建生產者特殊文件說明如何查看.log文件內容 4.創建消費者 0.前置說明 Go 語言中有一些流行的 Kafka 客戶端庫。以下是幾個常用…

【Uniapp小程序】自定義導航欄uni-nav-bar滾動漸變色

效果圖 新建activityScrollTop.js作為mixins export default {data() {return {navBgColor: "rgba(0,0,0,0)", // 初始背景顏色為完全透明navTextColor: "rgba(0,0,0,1)", // 初始文字顏色};},onPageScroll(e) {// 設置背景const newAlpha Math.min((e.s…

踩坑:6年后為何不用GraphQL了?

GraphQL 是一項令人難以置信的技術&#xff0c;自從我在 2018 年首次開始將其投入生產以來&#xff0c;它就吸引了很多人的注意力。 在一大堆無類型的 JSON REST API 上構建了許多 React SPA 之后&#xff0c;我發現 GraphQL 是一股清新的空氣。 然而&#xff0c;隨著時間的推…

mybatis用map接收返回對象,不想讓數據類型為tinyint自動轉換為boolean,如何處理

在 MyBatis 中&#xff0c;當使用 Map 來接收查詢結果時&#xff0c;MyBatis 會根據列的數據類型自動選擇合適的 Java 類型來映射這些值。默認情況下&#xff0c;如果數據庫列是 TINYINT(1)&#xff0c;MyBatis 可能會錯誤地將其映射為 boolean&#xff0c;因為它經常被誤解為只…

PPP認證兩種:PAP和CHAP,兩次握手和三次握手

CHAP&#xff08;Challenge-Handshake Authentication Protocol&#xff0c;質詢握手認證協議&#xff09;的設計理念是增強網絡認證過程的安全性。在CHAP的三次握手過程中&#xff0c;不直接傳送用戶的明文密碼&#xff0c;以此來提高安全性&#xff0c;具體步驟如下&#xff…

開源大模型源代碼

開源大模型的源代碼可以在多個平臺上找到&#xff0c;以下是一些知名的開源大模型及其源代碼的獲取方式&#xff1a; 1. **艾倫人工智能研究所的開放大語言模型&#xff08;Open Language Model&#xff0c;OLMo&#xff09;**&#xff1a; - 提供了完整的模型權重、訓練代…

springboot結合mybatis使用多數據源的方式

背景 最近有一個需求&#xff0c;有兩個庫需要做同步數據&#xff0c;一個Doris庫&#xff0c;一個mysql庫&#xff0c;兩邊的表結構一致&#xff0c;這里不能使用navicat等工具提供的數據傳輸之類的功能&#xff0c;只能使用代碼做同步&#xff0c;springboot配置多數據…

如何設置手機的DNS

DNS 服務器 IP 地址 蘋果 華為 小米 OPPO VIVO DNS 服務器 IP 地址 中國大陸部分地區會被運營商屏蔽網絡導致無法訪問&#xff0c;可修改手機DNS解決。 推薦 阿里的DNS (223.5.5.5&#xff09;或 114 (114.114.114.114和114.114.115.115) 更多公開DNS參考&#xff1a; 蘋果…

ESP32-C3模組上實現藍牙BLE配網功能(1)

本文內容參考&#xff1a; 《ESP32-C3 物聯網工程開發實戰》 樂鑫科技 藍牙的名字由來是怎樣的&#xff1f;為什么不叫它“白牙”&#xff1f; 特此致謝&#xff01; 一、藍牙知識基礎 1. 什么是藍牙&#xff1f; &#xff08;1&#xff09;簡介 藍牙技術是一種無線數據和…

【緩存】OS層面緩存設計機制

操作系統的緩存設計機制是計算機體系結構中的一個重要組成部分&#xff0c;旨在提高系統的性能&#xff0c;特別是通過減少對慢速存儲設備&#xff08;如硬盤&#xff09;的訪問次數來加速數據的讀取和寫入。 以下是一些常見的操作系統緩存設計機制&#xff1a; CPU緩存&…

web學習筆記(六十一)

目錄 如何使用公共組件來編寫頁面 如何使用公共組件來編寫頁面 1.導入公共組件nav.vue import Catenav from "/components/nav.vue"; 2.在頁面插入子組件 如果使用了setup語法糖此時就可以直接在頁面插入 <Catenav ></Catenav>標簽&#xff0c; …

.NET 快速重構概要1

1.封裝集合 在某些場景中,向類的使用者隱藏類中的完整集合是一個很好的做法,比如對集合的 add/remove 操作中包 含其他的相關邏輯時。因此,以可迭代但不直接在集合上進行操作的方式來暴露集合,是個不錯的主意。 public class Order { private int _orderTotal; private Li…

Camunda BPM架構

Camunda BPM既可以單獨作為流程引擎服務存在,也能嵌入到其他java應用中。Camunda BPM的核心流程引擎是一個輕量級的模塊,可以被Spring管理或者加入到自定義的編程模型中,并且支持線程模型。 1,流程引擎架構 流程引擎由多個組件構成,如下所示: API服務 API服務,允許ja…

邏輯回歸分類算法

文章目錄 算法推導 線性回歸解決連續值的回歸預測&#xff1b;而邏輯回歸解決離散值的分類預測&#xff1b; 算法推導 邏輯回歸可以看作是兩部分&#xff0c;以0、1分類問題說明&#xff1b; 線性回歸部分 對于一個樣本 x i x_i xi?&#xff0c;有n個特征 x i ( 1 ) x_i^{(1)…

蒙自源兒童餐新品上市,引領健康美味新潮流

隨著夏日的熱烈與兒童節的歡樂氛圍到來&#xff0c;蒙自源品牌隆重推出兒童餐新品&#xff0c;以“快樂不分大小&#xff0c;誰還不是個寶寶”為主題&#xff0c;為廣大消費者帶來一場健康與美味的盛宴。新品上市活動將于5月25日舉行&#xff0c;蒙自源將以其獨特的產品魅力和創…

install

目錄 1、 install 1.1、 //creates form with validation 1.2、 onStepChanging: function (event, currentIndex, newIndex) { 1.3、 onFinishing: function (event, currentIndex) { 1.4、 //init inst

最新 HUAWEI DevEco Studio 調試技巧

最新 HUAWEI DevEco Studio 調試技巧 前言 在我們使用 HUAWEI DevEco Studio 編輯器開發鴻蒙應用時&#xff0c;免不了要對我們的應用程序進行代碼調試。我們根據實際情況&#xff0c;一般會用到以下三種方式進行代碼調試。 肉眼調試法注釋排錯調試法控制臺輸出法彈出提示法斷…

【算法實戰】每日一題:將某個序列中內的每個元素都設為相同的值的最短次數(差分數組解法,附概念理解以及實戰操作)

題目 將某個序列中內的每個元素都設為相同的值的最短次數 1.差分數組&#xff08;后面的減去前面的值存儲的位置可以理解為中間&#xff09; 差分數組用于處理序列中的區間更新和查詢問題。它存儲序列中相鄰元素之間的差值&#xff0c;而不是直接存儲每個元素的值 怎么對某…

STM32 入門教程(江科大教材)#筆記2

3-4按鍵控制LED /** LED.c**/ #include "stm32f10x.h" // Device headervoid LED_Init(void) {/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_I…

關系數據庫:關系運算

文章目錄 關系運算并&#xff08;Union&#xff09;差&#xff08;Difference&#xff09;交&#xff08;Intersection&#xff09;笛卡爾積&#xff08;Extended Cartesian Product&#xff09;投影&#xff08;projection&#xff09;選擇&#xff08;Selection&#xff09;除…