使用布尔属性检查类型?

时间:2018-01-22 14:09:28

标签: c# design-patterns

我非常清楚类型检查,但发现自己处于一种独特的境地,我开始质疑我是否在最佳实践中。希望经验丰富的评论会给我一些方向和值得深入思考的事情。并且,说实话,并不是我所拥有的不会起作用,但是当我做出其他改变时,我想知道陷阱可能是什么以及我是否应该改变策略。在那里看起来并不多(实际上我没有看到任何基本类型检查占据了大部分搜索结果)。

我的情况是我正在开发物料清单接口系统。在此系统中,以下类图适用:

enter image description here 一般来说,这里的重点是,只有三种具体类型值得关注。因为在对象的构造函数中设置属性值很容易,所以我已经定义了(当然一般再说一遍)IMaterial接口:

public interface IMaterial
{
    bool IsCommodity { get; }

    bool IsAssembly { get; }

    bool IsUnclassified { get; }

    ...
}

最初的想法是,对象图几乎没有改变的余地,通过预设的布尔值提高了性能,我不必担心通过类型检查具体类型来打破其他各种原则。 / p>

例如,我可以这样做......

bool hasCommodities = materialCollection.Any(item => item.IsCommodity);
bool hasAssemblies = materialCollection.Any(item => item.IsAssembly);
bool hasDescriptionOnly = materialCollection.Any(item => item.IsUnclassified);

或者这......

if (bomMaterial.IsAssembly)
{
    symbol = new BomAssemblySymbol();
}
else
{
    symbol = new BomItemSymbol();
}

而不是......

bool hasCommodities = materialCollection.Any(item => item is ClassifiedItem);
bool hasAssemblies = materialCollection.Any(item => item is Assembly);
bool hasDescriptionOnly = materialCollection.Any(item => item is UnclassifiedItem);

或者这......

if (bomMaterial is Assembly)
{
    symbol = new BomAssemblySymbol();
}
else
{
    symbol = new BomItemSymbol();
}

因此,就我而言,接口对属性的使用意味着对实现细节中具体类型的依赖性较小。但话又说回来,它引出了一个问题,如果出现另一种类型会怎么样?这里最好的答案是什么?是否有一种模式,我可能会忽视,应该考虑这个?如果有人想知道为什么消费代码会关心,那是因为在CAD系统中,用户与之交互的单个命令反过来利用这些对象。由于单行代码差异,我无法为它们创建单独的命令。 的更新 这是一个更完整的例子,展示了CAD方面如何瓶颈过程。 TryGetMaterialInformation()方法提示CAD系统中的用户输入特定输入。 SymbolUtility.InsertSymbol()方法只包含一组常用的用户提示,用于插入任何符号,然后插入它。

public override void Execute()
{
    IMaterial bomMaterial = null;
    bool multipleByReference = false;
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

    if (!TryGetMaterialInformation(out bomMaterial, out multipleByReference))
    {
        ed.WriteMessage("\nExiting command.\n");
        return;
    }

    IBlockSymbol symbol;
    if (bomMaterial.IsAssembly)
    {
        symbol = new BomAssemblySymbol();
    }
    else
    {
        symbol = new BomItemSymbol();
    }

    if (multipleByReference)
    {
        SymbolUtility.InsertMultipleByReferenceSymbol(symbol, bomMaterial);
    }
    else
    {
        SymbolUtility.InsertSymbol(symbol, bomMaterial);
    }
}

来自SymbolUtility

    internal static void InsertSymbol(IBlockSymbol symbol, IMaterial material)
    {
        ICADDocumentDTO document = new CADDocumentDTO();
        Editor ed = document.ActiveDocument.Editor;

        //Get the insert point
        Point3d insertPoint = Point3d.Origin;
        if (!CommandUtility.TryGetPoint("Select insert point: ", out insertPoint))
        {
            ed.WriteMessage("\nExiting command.\n");
            return;
        }

        //Insert the object    
        using (ISystemDocumentLock documentLock = document.Lock())
        {
            CreateSymbolDefinition(symbol, document);

            symbol.Insert(insertPoint, material, document);
        }
    }

1 个答案:

答案 0 :(得分:1)

如果您拥有IsClassifiedIMaterialIMaterial等属性,则应描述某种可归因于实例的逻辑属性。他们应该告诉消费者具体类型是什么。

原因是<form method="POST" data-request="Component_2::onSubmit" data-request-flash> 的消费者既不知道也不需要知道实现AJAX handler 'Component_2::onSubmit' was not found. 的任何具体类型。

如果这些属性实际上指示了具体类型,那么所有这些属性都是类型检查,它们将导致将对象转换回其具体类型,从而破坏了创建抽象的目的(界面。)

它看起来像我,因为你正在考虑将属性作为类型检查的直接替代方法。

替代方案是,消费者只是告诉类做什么(调用方法)而不是消费者查看类属性并决定对类做什么或不做什么,而类本身的实现决定了如何实现这一目标。

相关问题