簡體   English   中英

可擴展工廠設計模式

[英]Extendable factory design pattern

以下是我的導入工廠類。 如果我想添加新的 ImportTypes,那么只需在 ImportTypes 枚舉中添加新類型並在工廠類中添加一個案例,它就可以正常工作。

我的問題是如何使它更獨立且易於擴展。 假設用戶想要添加一個新的 ImportType 然后他編寫自己的 DLL 並實現接口而不是更改代碼...有什么好的建議/想法嗎?

導入類型

enum ImportTypes
{
   DefaultImport,
   C2CImport
}

導入接口

public interface IImportService
{
   void Import(Argument arguments, ImportDefinition config);
}

進口工廠

class ImportFactory
    {
    public static IImportService GetService(ImportTypes type)
    {
       switch (type)
       {
           case ImportTypes.DefaultImport:
               return new DefaultImportService();

           case ImportTypes.C2CImport:
               return new C2CImportService();
       }

       return null;
    }
}

測試

IImportService docImportService = ImportFactory.GetService(ImportTypes.DefaultImport);

為此,您需要支持在運行時注冊新服務。 因此,您不能使用enum ,因為這些服務是事先未知的; 它們需要通過例如字符串來引用:

class ImportServiceHandler
{
    private readonly Dictionary<string, Type> _importServices =
        new Dictionary<string, Type>();

    public ImportServiceHandler()
    {
        RegisterService("DefaultImport", typeof(DefaultImportService));
        RegisterService("C2CImport", typeof(C2CImportService));
    }

    public void RegisterService(string name, Type serviceType)
    {
        if (!serviceType.IsAssignableFrom(typeof(IImportService)))
        {
            throw new ArgumentException("Type specified doesn't implement IImportService", nameof(serviceType));
        }
        _importServices.Add(name, serviceType);
    }

    public IImportService GetService(string name)
    {
        if (_importServices.ContainsKey(name))
        {
            return (IImportService)Activator.CreateInstance(_importServices[name]);
        }
        return null;
    }
}

這是一種方法...

在您的 switch 語句中,“默認”將處理任何無法識別的類型。 該類型將在您的程序配置中查找。 用戶必須將他們的類型和路徑添加到實現該類型的程序集。 他們需要實現你的接口。 然后默認情況會加載程序集並實例化對象並將其返回給您。

您將使用 AppDomain.CurrentDomain.Load() 加載程序集。 您將使用 {Assembly}.CreateInstance() 來實例化您的對象。

class ImportFactory
{
  public static IImportService GetService(ImportTypes type)
  {
     switch (type)
     {
         case ImportTypes.DefaultImport:
             return new DefaultImportService();
         case ImportTypes.C2CImport:
             return new C2CImportService();
         default:
             return CustomImportService(type);
     } 
     return null;
  }
}

CustomImportService 看起來像這樣......

IImportService CustomImportService(ImportTypes type)
{
    var assmBytes = GetAssemblyIDByType(type);  // you would implement this based on your configuration approach
    var assm = AppDomain.CurrentDomain.Load(assmBytes);
    var obj = (IImportService)assm.CreateInstance("IImportService");
    return obj;
}

這當然只是一個開始,需要努力。

您可以使用原型模式。

創建一個在運行時接收導入類型的類,並返回這些對象的克隆。
它將允許您在運行時加載 ImportTypes,並且不需要更改工廠類。

http://www.dofactory.com/net/prototype-design-pattern

這個鏈接顯示了這個想法。

你可以有這樣的東西:(為清楚起見省略了錯誤處理)

public class Factory {

    //store how different objects are created
    private IDictionary<string, Func<IImportService>> mappings = new Dictionary<string, Func<IImportService>>()

    public void Register(string key, Func<IImportService> expression) 
    {
         mappings[key] = expression;
    }

    public IImportService GetService(string key)
    {
         return mappings[key]();
    }
}

這可以按以下方式使用:

factory.Register("service", () => new MyCustomImportService());

如果您在編譯時知道所需的類型,則可以提供在簽名中采用該類型的覆蓋。 Register<MyCustomImportService>(...)GetService<MyCustomImportService> 在這一點上,考慮是否需要一些輕量級的 IoC 容器可能會很有用

我很想知道當您使用枚舉來決定要返回哪個實現時,如何制作可擴展的工廠模式。 這意味着每次有人用新的實現邏輯構建一個新的 DLL 時,您都必須重構原始代碼(也許這是一個苛刻的描述,因為您所做的只是添加一個新的枚舉元素),並重新構建它。 這有點違背了目的。

我強烈建議不要這樣做。 事實上,我看不出工廠模式如何被認為非常適合您想要做的事情,這更符合可插拔框架的路線,該框架只知道它必須按照要求返回IImportService實現調用代碼。

這種應用程序設計確實需要一種基於依賴注入的方法。 也許像MEF東西? 您可以通過像這樣定義依賴項來擺脫困境:

[Export("C2CImport", typeof(IImportService))]
public class C2CImportService : IImportService

除了[Import]將依賴添加到您想要的代碼中,您還可以像這樣手動解析依賴:

myCompositionContainer.GetExports<IImportService>("C2CImport");

( https://msdn.microsoft.com/en-us/library/dd833299(v=vs.110).aspx )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM