这是不正确的接口使用?

时间:2016-06-14 08:22:29

标签: c# interface factory

采取以下示例,我有多个“整合”#39;继承自相同' IChannelIntegration'接口

public interface IChannelIntegration
{

}

public class IntegrationA : IChannelIntegration
{

}

public class IntegrationB : IChannelIntegration
{

}

public IChannelIntegration CreateIntegration(string letter)
{
   if(letter = "A")
   {
     return new IntegrationA();
   }
   else if (letter = "B")
   {
     return new IntegrationB();
   }
   else
   {
     return null;
   }
}

我的一个集成提供了其他集成功能所不具备的功能。我需要一种在CreateIntegration函数返回的IChannelIntegration对象上调用此功能的方法。

我创建了以下用于处理这些自定义IntegrationFeatures的类集合。 IntergrationFeature接口是所有功能的衍生产品。

public interface IIntegrationFeature {}

public interface ICustomLogic : IIntegrationFeature 
{
  void DoSomething() {}
} 

//Provides a concrete implementation of the logic.
public class CustomLogic : ICustomLogic 
{
  public void DoSomething() {}
}

然后创建了另一个接口,该接口将附加到Integration类,以支持集成提供自定义功能。

public interface ISupportsFeature<T>  where T : Interfaces.IIntegrationFeature
{
    T GetFeature();
}

将按照以下方式实施;

public class IntegrationC : IChannelIntegration, ISupportsFeature<ICustomLogic>
{
    public ICustomLogic GetFeature()
    {
        return new CustomLogic ();
    }
}

这就是你如何给予集成它的特定逻辑,然后你用以下方法调用它;

public static IIntegrationFeature GetIntegrationFeature<IIntegrationFeature>()
        where IIntegrationFeature : Interfaces.IIntegrationFeature
    {
        IIntegrationFeature integrationFeature = null;

        IChannelIntegration service = CreateIntegration();

        //Attempt to cast the integration too determine if it supports the Integration Feature.
        ISupportsFeature<IIntegrationFeature> supportsFeature = service as ISupportsFeature<IIntegrationFeature>;

        if(supportsFeature != null)
        {
            integrationFeature = supportsFeature.GetFeature();
        }

        return integrationFeature;
    }

public void TestMethod()
{
    ICustomLogic customLogic = GetIntegrationFeature<ICustomLogic>();
    if (customLogic != null)
    {
        customLogic.DoSomething();
    }
}

我不确定我对这个实现的感受,部分我认为我大大超过了复杂的情况,但我也认为它很容易使用,因为我的许多集成都需要提供自定义逻辑。

另一个问题是,如果集成提供了多个IntegrationFeatures,那么由于它们具有相同的GetFeature名称,您必须显式调用接口函数,这可能会给其他开发人员带来更多混淆。

1 个答案:

答案 0 :(得分:2)

我会从上到下,从你需要的实施开始。

从我看到你需要在运行时访问由某个系统从给定值创建的集成提供的功能。所以你的第一批演员将是

interface IIntegrationFeature {}

以及可以为您提供此功能的内容

interface IIntegratedSystem
{
  T GetFeature<T>(string integrationType) where T : IIntegrationFeature;
}

此设置的客户端将使用这样的演员

IIntegratedSystem system = .... // system implementation

T feature = system.GetFeature<T>("Which integration type?");

if (feature != null)
{
    //the feature exists and I'm using it
}

IIntegratedSystem实施的责任是提供实时选择或创建的现有IIntegrationFeature IChannelIntegration。您考虑通过实施IChannelIntegration通知任何客户ISupportFeature<IIntegrationFeature>实施已实施功能。当集成有大约20个功能时会发生什么?您将拥有一个实现集成接口本身的类和另外20个ISupports接口。你如何添加其他功能?您可以通过添加违反单一责任原则的新ISupports<INewFeature>来修改该类。并且您不需要在编译时知道集成是否满足某个功能,因为客户端可能会也可能不会使用它。基本上IChannelIntegration听起来更像是复合的集成,它应该能够提供IIntegrationFeature,因此IChannelIntegration的定义类似于IIntegratedSystem }

interface IChannelIntegration 
{
    T GetFeature<T>() where T : IIntegrationFeature;
}

构建实现IChannelIntegration的方式取决于您,但我更愿意在应用程序的根目录中创建功能。我会是这样的

class ChannelIntegration : IChannelIntegration
{
    private Dictionary<Type, IIntegrationFeature> features;
    public ChannelIntegration()
    {
        features = new Dictionary<Type, IIntegrationFeature>();
    }
    public void RegisterFeature<T>(IIntegrationFeature feature) where T:IIntegrationFeature
    {
        features.Add(typeof(T), feature);
    }
    public T GetFeature<T>() where T : IIntegrationFeature
    {
        IIntegrationFeature feature = features.TryGetValue(typeof(T), out feature) ? feature : null;
        return (T)feature;
    }
}

ChannelIntegration类维护功能列表。您使用RegisterFeature添加更多功能并确保是一项功能,您可以限制它们实现IIntegrationFeature界面。因此,当您添加新功能时,您无法更改ChannelIntegration课程,您可以使用它。

IIntegratedSystem将根据运行时值从IChannelIntegration访问某个功能。正如您所说,这要求使用抽象工厂。这看起来像

interface IChannelIntegrationFactory 
{
    IChannelIntegration CreateIntegration(string integrationType);
}

IIntegratedSystem将使用此工厂创建IChannelIntegration并实现此目的,我将使用构造函数注入机制。

   class IntegratedSystem : IIntegratedSystem
{
    private IChannelIntegrationFactory integrationFactory;
    public IntegratedSystem(IChannelIntegrationFactory integrationFactory)
    {
        this.integrationFactory = integrationFactory;
    }
    public T GetFeature<T>(string integrationType) where T: IIntegrationFeature
    {
        T integrationFeature = default(T);
        IChannelIntegration integration = integrationFactory.CreateIntegration(integrationType);
        if (integration != null)
        {
            integrationFeature = (T)integration.GetFeature<T>();    
        }
        return integrationFeature;
    }
}

现在IntegratedSystem类正在使用IChannelIntegrationFactory根据运行时值创建IChannelIntegration,然后它将从中检索已实现的IIntegrationFeature(如果有的话)。 / p>

我们现在需要的是实施这个工厂,用IChannelIntegration s

创建IIntegrationFeature s

让我们先创建一个新功能

interface ICustomFeature : IIntegrationFeature {}

class CustomFeature : ICustomFeature
{       
}

基于此,抽象工厂实现就像

class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        // use integrationType to decide witch IChannelIntegration to use
        IChannelIntegration integration = new ChannelIntegration();
        integration.RegisterFeature<ICustomFeature>(new CustomFeature());

        return integration;
    }
}

我们在这里创建了一个ChannelIntegration的单一功能。当然,您可以使用自己的IChannelIntegrations创建不同ICustomFeature的多个路径,并根据integrationType参数检索该路径。

那么你如何消费呢?

    IIntegratedSystem system = new IntegratedSystem(new ChannelIntegrationFactory());
    ICustomFeature customFeature = system.GetFeature<ICustomFeature>("Which Integration?");
    if (customFeature != null)
    {
        //use this custom feature

    }
    else
    {
        // that's OK, will wait until is registered.
    }

您想添加新功能吗?在Abstract Factory实现中注册它。

<强> So would you expect to create a new abstract factory of type ChannelIntegrationFactory for each different type of ChannelIntegration?

没有。工厂从具体实施列表中选择一个。这是一个例子

class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        IChannelIntegration integration = null;
        switch (integrationType)
        {
            case "MobileIntegration":
                integration = new ChannelIntegration();
                integration.Register<ITapGestureTrack>(new TapGestureTrack());
                break;
            case "DesktopIntegration":
                integration = new ChannelIntegration();
                integration.Register<IClickTrack>(new ClickTracker());
                integration.Register<ILargeImagesProvider>(new LargeImagesProvider());
                break;
        }
        return integration;
    }
}

您甚至可以将ChannelIntegration视为摘要并创建专门的集成:

 class MobileIntegration : ChannelIntegration
    {
       public MobileIntegration()
       {
            Register<ITapGestureTrack>(new TapGestureTrack());
       }
    }

    class DesktopIntegration : ChannelIntegration
    {
       public DesktopIntegration()
       {
            Register<IClickTrack>(new ClickTracker());
            Register<ILargeImagesProvider>(new LargeImagesProvider());
       }
    }

抽象工厂成为

class ChannelIntegrationFactory : IChannelIntegrationFactory
    {
        public IChannelIntegration CreateIntegration(string integrationType)
        {
            IChannelIntegration integration = null;
            switch (integrationType)
            {
                case "MobileIntegration":
                    integration = new MobileIntegration();
                    break;
                case "DesktopIntegration":
                    integration = new DesktopIntegration();
                    break;
            }
            return integration;
        }
    }

只需将此类视为系统的引导类。这是唯一一个创建与功能集成的类。顺便说一下,您可以使用首选的IoC轻松启用依赖性倒置。 Fiddle