将包含数据的大对象传递到接口中

时间:2018-08-01 09:18:15

标签: c# design-patterns interface strategy-pattern

上下文

我有一个使用策略模式的抽象类。

public interface IReader
{
    HashSet<DataSheet> Read(string fullFilePath, HashSet<string> sheetNames, ref string errors);
}

public abstract class AbstractReader : IReader
{
    public virtual HashSet<DataSheet> Read(string fullFilePath, Hashset<string> sheetNames, ref string errors)

    protected virtual void InitializeRowColInfo(string filePath, string sheetName)

    //And some other methods
}

该方法读取,读取excel文件并通过其参数获取所需的信息,并输出要进一步处理的信息。

策略

要实现Abstract Reader,我创建了一个新类来覆盖它。例如,

对于遵循我的抽象类格式逻辑的文件,

public class ConcreteReader1 : AbstractStandardReader
{
}

对于不遵循抽象类格式逻辑的文件,

public class ConcreteReader2 : AbstractStandardReader
{
    protected override void InitializeRowColInfo(string filePath, string sheetName)
}

在这里,我将根据文件的格式需求重写该方法,而从抽象类中重用常见的方法。对象的创建方法如下:

public IReader GetReader(string reader){
    if (reader.toUpper().trim().Equals("CONCRETEREADER1"){
        return new ConcreteReader1();
    }
    //Continue else ifs for the other readers
}

问题:参数

但是,由于我为所有方法都包括的参数的严格性质,每当需要一种需要其他参数的文件格式时,我都无法重用我的代码。

要解决此问题,我可以创建一个要传递的对象,例如documentInfo对象:

public class DocumentInfo
{
    public string FullReadFilePath { get; set; }
    public HashSet<string> SheetNames { get; set; }
    public string Errors { get; set; }
}

public interface IReader
{
    HashSet<DataSheet> Read(DocumentInfo documentInfo);
}

这样,可以将所需的任何其他参数添加到该对象中,而不会影响现有的具体阅读器,并且我可以摆脱引用字符串。

但是,

  1. 存在一个冗余问题,因为对DocumentInfo对象的任何新添加的属性将始终未初始化,并且对于不使用它们的读者(也使代码混乱)毫无用处。

  2. 此外,我所有其他方法都将依赖于此对象,因为它包含有关读取的所有信息(fullFilePath,sheetNames等)

是否有更好的方法来解决此问题?

1 个答案:

答案 0 :(得分:1)

我的理解是,您正在尝试进行技术重构,而无需重新考虑对象责任(SOLID原则https://stackify.com/solid-design-principles/的S)。这导致尝试将所有内容合并为一个类。 我看到您可以通过以下方式重组类:

  1. DocumentInfo-描述文档结构的数据对象(如果它是策略的一部分,则可以包括RowColInfo)
  2. IReader-阅读界面
  3. 错误-错误类(可以保留数组或创建单独的类)
  4. InitializeRowColInfo-不确定是否需要通用,这看起来像特定阅读器实现的一部分
  5. AbstractReader-您真的需要它吗?重新考虑将技术方法保留在不同的位置/类别中
  6. 获取特定的阅读器实现超出阅读器范围(如果需要,请保持相同)

总而言之,我想使用以下结构

public class DocumentInfo
{
    public HashSet<string> SheetNames { get; set; }
    // potentially RowColInfo if it's part of your configuration
}

public interface IReader
{
    HashSet<DataSheet> Read(DocumentInfo docuInfo, ref string errors);
}

public class ConcreteReader: IReader
{
    public ConcreteReader(string filePath) {...};
    public HashSet<DataSheet> Read(DocumentInfo docuInfo, ref string errors) {...};
}

实际上就是这样。