三種工廠模式(簡單工廠、工廠方法、抽象工廠)

来源:http://www.cnblogs.com/hhh2016/archive/2016/10/12/5946380.html
-Advertisement-
Play Games

一、簡單工廠模式 簡單工廠模式,提供了一種創建對象的便捷方法。創建者通過不同的類型參數,創建相對應的對象。 實現代碼如下: 優點: 在創建固定類型的對象時,比較簡單好用。 缺點: 1. 在添加對象類型時,需要更改Creator類裡面的函數,違反了軟體設計中的開閉原則。 2. Creator類依賴於具 ...


一、簡單工廠模式

簡單工廠模式,提供了一種創建對象的便捷方法。創建者通過不同的類型參數,創建相對應的對象。

實現代碼如下:

 public class Product
    {
        public virtual void Funtion()
        {}
    }

    public class ProductA : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class ProductB : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class Creator
    {
        public static Product Create(string type)
        {
            switch (type)
            { 
                case "A":
                    return new ProductA();
                case "B":
                    return new ProductB();
                default:
                    return null;           
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Product pa = Creator.Create("A");
        }
    }

優點:

在創建固定類型的對象時,比較簡單好用。

缺點:

1. 在添加對象類型時,需要更改Creator類裡面的函數,違反了軟體設計中的開閉原則。

2. Creator類依賴於具體類ProductA,和ProductB,在具體類變化時直接影響Creator類,耦合性過強。

工廠模式

         工廠模式將對象的創建延遲到了具體的子類裡面實現。這樣,我們創建子類對象時,不需要知道具體的子類,只需獲取到相應的類型的工廠即可。同時,工廠模式消除了簡單工廠方法所具有高耦合性,且滿足軟體的設計原則。

         工廠模式,解決了創建多個、同類對象的複雜問題。比如我們需要創建100個ProductA種類的對象,如果不使用工廠模式,我們需要new出100個ProductA對象來;通過工廠模式,只需要調用FactoryA多次就能夠完成對象的創建。

1. 實現方法

1)工廠模式最常用的結構類圖:

實現代碼(C#)如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Factory
{
    public class Product
    {
        public virtual void Funtion()
        { }
    }

    public class ProductA : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class ProductB : Product
    {
        public override void Funtion()
        {
            base.Funtion();
        }
    }

    public class Factory
    {
        virtual public Product Create()
        {
            return null;
        }
    }

    public class FacotryA : Factory
    {
        public override Product Create()
        {
            return new ProductA();
        }
    }

    public class FactoryB : Factory
    {
        public override Product Create()
        {
            return new ProductB();
        }
    }

    class FactoryMode
    {
        static void Main(string[] args)
        {
            FacotryA fa = new FacotryA();
            FactoryB fb = new FactoryB();

            Product pa = fa.Create();
            Product pb = fb.Create();
        }
    }
}

工廠模式的問題在於,每添加一種新的Product必須添加與之相對應的Factory類。比如,現在需要增加一種對象ProductC,同時需要添加FactoryC類來創建ProductC的對象。這樣的話,如果需要添加N多種對象,同時就必須添加與之對應的N種工廠類,增加了編碼量和繁瑣程度,如下圖。

2)使用類模板 

         在需要添加多種對象時,採用模版的方式,可以避免創建過多的工廠子類。

此處,只需要定義一個類模板template<class TheProduct> ConcreteFactoy,只要是從Product基類派生的對象類型,都可以通過這個類模板實現。

以下是實現代碼(C++).

 

#include "stdafx.h"
#include <iostream>

using namespace std;

class Product
{
public:
    virtual void Function() = 0;
};

class ProductA : public Product
{
public:
    void Function();
};

void ProductA::Function()
{
    cout << "Create ProductA..." << endl;
}

class Factory
{
public:
    virtual Product* Create() = 0;
};

template<class TheProduct>
class ConcreteFactroy : public Factory
{
public:
    virtual Product* Create();
};

template<class TheProduct> 
Product* ConcreteFactroy<TheProduct>::Create()
{
    return new TheProduct;
}


int _tmain(int argc, _TCHAR* argv[])
{
    ConcreteFactroy<ProductA> MyFactory; 
    Product* pa = MyFactory.Create();
    pa->Function();

    return 0;
}

 

3. 抽象工廠

         抽象工廠模式,用於創建一組相關或獨立的對象。通過此模式,用戶不需要知道具體的對象類型,只需找到創建的工廠類即可。抽象工廠與工廠方法的區別主要如下:

         工廠方法中的工廠類只能創建一種對象,如FactoryA -> ProductA。

         抽象工廠中的工廠類可以創建多種類型的對象, Factory1 -> {product1, product2, …,productN}

抽象工廠的問題在於,當我們需要添加新的對象AbstractProductC時,需要同時修改AbstractFactory, ConcreteFactory1和ConcreteFactory2三個類。從這個角度來看,添加新類型的對象時,與簡單工廠模式類似。這裡,我們不妨就先把抽象工廠更改為簡單工廠模式,然後再通過反射機制進行改進。通過反射,用戶只需要傳遞product子類型的名字給Factory類。Factory類根據傳入的類名字,生成類對象。無論後期添加多少種對象,都不用再添加對應的工廠類。

以下描述了,抽象工廠模式訪問資料庫,然後更改為簡單工廠模式,再使用反射機制的整個過程(摘自《大話設計模式》)。(其實,三種工廠模式都可以使用反射機制來簡化對象生成的過程。)

使用抽象工廠訪問資料庫的類圖:

 

我們將抽象工廠更改為簡單工廠模式,如下:

使用反射實現(C#),如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Reflection;


namespace AbstractFactory
{
    public interface IUser
    {
        void InsertUser(IUser user);

        IUser GetUser(string user);
    }


   public class SQLUser : IUser
   {
       public void InsertUser(IUser user)
       {
           Console.WriteLine("Access user");
       }

       public IUser GetUser(string user)
       {
           return null;
       }
   }

   public class AccessUser : IUser
   {
       public void InsertUser(IUser user)
       {
           Console.WriteLine("Access user");
       }

       public IUser GetUser(string user)
       {
           return null;
       }
   }

   public class DataAccess
   {
       private readonly string dbType = "SQL";
       public IUser CreateUser()
       {
           IUser result = null;
           switch (dbType)
           {
               case "SQL":
                   result = new SQLUser();
                   break;
               case "Access":
                   result = new AccessUser();
                   break;
               default:
                   break;
           }
           return result;
       }

       public string ReflectType { get; set; }

       public IUser CreateUserByReflection()
       {
           //(IUser)Assembly.Load(當前程式集的名稱 "Factory").CreateInstance("命名空間.類名");
           return (IUser)Assembly.Load("Factory").CreateInstance(ReflectType);         
       }
   }

    class AbstractFactory_Reflect
    {
        static void Main(string[] args)
        {
            DataAccess da = new DataAccess();
            da.ReflectType = "AbstractFactory.SQLUser";

            IUser user = null;
            user = da.CreateUserByReflection();

            SQLUser sqlUser = user as SQLUser;
            if (sqlUser == null)
            {
                Console.WriteLine("NULL...");
            }
        }
    }
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先記錄一下異常,以及異常出現的原因和解決方案 異常主要信息: 我說一下我的解決過程 我根據這個異常的提示,跟蹤到AbstractNamedValueMethodArgumentResolver的resolveArgument方法,然後從介面中看到了它的作用,就是將 處理器中的映射方法的參數進行處理 ...
  • 授權獲取二維碼類: 調取實例: ...
  • 一、資源準備 鏈接:http://pan.baidu.com/s/1mh7qUBe 密碼:p4wx 1. virtualbox.box文件放在C盤根目錄上。 2. metadata.json文件放在C盤用戶目錄上。比如我的是 C:\Users\pc 3. Git-2.9.3-64-bit.exe 下 ...
  • BaseModel 基礎Model類 其他的資料庫表類文件都基礎此類 當前鏈接的是sql service的資料庫 mysql的只需要修改query和execute就行 資料庫表的Model類 繼承 BaseModel類 實例: ...
  • 作為一個Java 初學者,對Java的理解可能有些片面,甚至有些錯誤的理解,對於觀看此處的您,希望您選擇性觀看!!! 天知道我為什麼選擇學習編程,我不愛編程,但是我既然學習了,還是會努力學習的,在此分享一些學習經驗。 訪問修飾符: 1.常用訪問修飾符: public 共有的 private 私有的 ...
  • 1.新建項目 > 選擇 web 應用程式 選擇 webApi 2. 創建一個httpmodeule類 放到app_data文件夾下 public class MyHttpModule : IHttpModule { #region IHttpModule 成員 public void Dispose ...
  • 從2005年畢業至今,畢業已經11年,正好現處於離職狀態,所以理一理些年的一些技術,一些想法,在此也分享給大家,不對的地方也請大家儘管打臉,贊同的話呢,那就點個贊吧。:) 先說一下風格,一不照本宣科,二不複製粘貼,純手打,三必須是結合實際開發的經驗或理解來整理。 ...
  • HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服務端組件、客戶端組件和 Agent 組件,廣泛適用於各種不同應用場景的 TCP/UDP/HTTP 通信系統,提供 C/C++、C#、Delphi、E(易語言)、Java、Python 等編程語言介面。HP-Socket... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...