通过扩展模拟继承 [英] Simulate Inheritance by Extension

查看:71
本文介绍了通过扩展模拟继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类库,描述了不同的连接硬件,例如钉子,螺钉和螺栓,我们将其称为ConnectorLibrary.我正在尝试在该库之上构建一个库,该库将分析该库中每个类的抓取能力,我们将其称为ConnectorGripAnalysisLibrary.

I have a library of classes that describe different pieces of connecting hardware such as nails, screws and bolts that we will call the ConnectorLibrary. I am attempting to build a library on top of that one that will handle analyzing the grip capacity of each class in that library that we will call ConnectorGripAnalysisLibrary.

对于这个问题,我们将使用以下类:ScrewBoltConnector. ScrewBolt都从Connector(这是一个抽象类)继承,它们都在ConnectorLibrary中实现.

For this question we will work with the classes: Screw, Bolt, and Connector. Both Screw and Bolt inherit from Connector (which is an abstract class) and they are both implemented in the ConnectorLibrary.

对于我需要实现的基础库中的每个类,确定握持力的方法不同.因此,对于BoltScrew,我都需要实现一个DoesPassGripTest(Board board)之类的方法. (板只是一个示例参数)

There is a different method for determining grip for each class in the base library that I need to implement. So for both Bolt and Screw I need to Implement a method such as DoesPassGripTest(Board board). (Board being just an example parameter)

如果要在Connectorlibrary库中实现此功能,可以将DoesPassGripTest放入Connector抽象方法中,并在各个派生类中实现不同的公式.

If I were going to implement this in the Connectorlibrary, I would put DoesPassGripTest into Connector an abstract method and implement the different formulas in the respective derived classes.

目标是能够使我的代码在ConnectorGripAnalysisLibrary中像这样工作:

The goal is to be able to have my code work like this from the ConnectorGripAnalysisLibrary:

[Test()]
public static void CheckScrewAndBoltGripTest()
{
    Board board = new Board();

    Bolt b = new Bolt();
    Screw s = new Screw();
    List<Connector> connectors = new List<Connector>()

    connectors.add(b);
    connectors.add(s);

    foreach(var connector in connectors)
    {
        if(!connector.DoesPassGripTest(board));
            throw new Exception("Grip Test Fails");
    }
}

我想在ConnectorGripAnalysisLibrary中保持开放式封闭原理",以便在将新的Connector添加到ConnectorLibary的情况下,除了添加新类之外,无需修改ConnectorGripAnalysisLibrary. 为扩展而开放,为修改而封闭"

I want to maintain the "Open closed principle" in the ConnectorGripAnalysisLibrary, so that in the event a new Connector is added to the ConnectorLibary, no modification of the ConnectorGripAnalysisLibrary is needed other than adding a new class. "Open for Extension, Closed for Modificaiton"

但是我如何才能将此功能内置到在ConnectorLibrary之上构建的GripAnalysisLibrary中.我可以用一种巧妙的方式来做到这一点吗?

But how can I build this functionality into the GripAnalysisLibrary that is built on top of the ConnectorLibrary. Is there a slick way that I can do this?

我不希望ConnectorLibrary包含GripAnalysis代码和功能. ConnectorLibrary将是开源的,而GripAnalysisLibrary将是专有的.

I don't want the ConnectorLibrary to contain the GripAnalysis code and functionality. The ConnectorLibrary is to be opensource while the GripAnalysisLibrary will be proprietary.

推荐答案

要将此作为扩展方法,您需要创建一个类来定义 Connector 的扩展,并在需要的地方包括该类在连接器实例上使用DoesPassGripTest方法.扩展程序的基本概述是:

For doing this as an extension method you need to create a class to define extensions for Connector and include the class wherever you want to use the DoesPassGripTest method on a Connector instance. The basic outline of the extension is:

public static class ConnectorExtensions
{
    public static bool DoesPassGripTest(this Connector connector, Board board)
    {
        // Some logic to determine which connector is being used
    }
} 

除了类型检查之外,我不知道是否有其他方法可以确定要传递哪个连接器,因为您没有提供有关连接器或夹点分析逻辑的任何详细信息.您的扩展程序需要知道如何针对给定的每种连接器类型评估给定板的测试.

I don't know if there is any other method for determining which connector is being passed in other than type checking since you didn't provide any details about Connectors or the grip analysis logic. Your extension would need to know how to evaluate the test for a given board for each Connector type you are given.

基于您对ConnectorGripAnalysisLibrary易于扩展且无需修改的要求,以下是使用反射的方法的伪代码,该方法允许您仅需要为每个新连接器添加一个类.

Based on your desire to have your ConnectorGripAnalysisLibrary be easily extendable and without modification, here is pseudo-code of an approach using reflection that allows you to only need to add a class for each new connector.

创建一个提供信息以运行分析的接口,以及该接口用于哪种类型的连接器:

Create an interface that supplies information to run the analysis and which type of Connector it is for:

public interface IConnectorGripAnalyzer
{
    Type ConnectorType { get; }
    bool DoesPassGripTest(Board board);
}

使用泛型创建基类,以轻松实现具体类:

Create a base class using generics for easy implementations of concrete classes:

public class ConnectorGripAnalyzer<T> : IConnectorGripAnalyzer where T : Connector
{
    public Type ConnectorType 
    { 
        get { return typeof(T); }
    }

    public virtual bool DoesPassGripTest(Board board)
    {
        return true;
    }
}

创建一个存储库,该存储库可用于通过类型使用反射来获取IConnectorGripAnalyzer实例.首次使用时,它会收集所有各种分析仪,并按连接器类型存储它们:

Create a repository that can be used to get an IConnectorGripAnalyzer instance by Type using reflection. On first use it gathers all of the various analyzers and stores them by connector Type:

public static class ConnectorAnalyzerRepository
{
    private Dictionary<Type, IConnectorGripAnalyzer> connectorGripAnalyzers;

    public IConnectorGripAnalyzer GetGripAnalyzer(Connector connector)
    {
        if (connectorGripAnalyzers == null)
        {
            connectorGripAnalyzers = new Dictionary<Type, IConnectorGripAnalyzer>();

            var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(IConnectorGripAnalyzer).IsAssignableFrom(t));
            foreach (var t in types)
            {
                var c = Activator.CreateInstance(t) as IConnectorGripAnalyzer;
                if (c == null)
                    continue;

                connectorGripAnalyzers[c.ConnectorType] = c;
            }
        }

        return connectorGripAnalyzers.ContainsKey(typeof(connector)) ? connectorGripAnalyzers[typeof(connector)] : null;
    }
}

Connector的扩展利用资源库为给定的Connector创建适当的IConnectorGripAnalyzer实例.如果连接器的类型没有实现,则该示例将引发异常,但您也可以返回false或将其记录为配置问题:

The extension for Connector leverages the repository to create an appropriate IConnectorGripAnalyzer instance for the given Connector. In the case that the Type of the Connector has no implementation the example throws an exception, but you could return false or log it as a configuration issue as well:

public static class ConnectorExtensions
{
    public static bool DoesPassGripTest(this Connector connector, Board board)
    {
        var analyzer = ConnectorAnalyzerRepository.GetGripAnalyzer(connector);
        if (analyzer == null)
            throw new ArgumentException("Invalid connector type"); // Do whatever you want with the failure

        return analyzer.DoesPassGripTest(board);
    }
}

现在需要在ConnectorGripAnalysisLibrary中添加对连接器的支持,只需添加一个继承自ConnectorGripAnalyzer且具有具体Connector类型的类即可.所需要做的就是为特定的连接器适当覆盖DoesPassGripTest(Board board):

Adding support for a Connector in the ConnectorGripAnalysisLibrary is now a matter of adding a class that inherits from ConnectorGripAnalyzer with the concrete Connector type. All that is needed is an appropriate override of DoesPassGripTest(Board board) for the specific Connector:

public class NailConnectorGripAnalyzer : ConnectorGripAnalyzer<NailConnector>
{
    public override bool DoesPassGripTest(Board board)
    {
        return true;
    }
}

public class ScrewConnectorGripAnalyzer : ConnectorGripAnalyzer<ScrewConnector>
{
    public override bool DoesPassGripTest(Board board)
    {
        return true;
    }
}

这篇关于通过扩展模拟继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆