C# DataInterface的体系结构设计-移除接通类型

C# DataInterface的体系结构设计-移除接通类型,c#,architecture,switch-statement,oop,C#,Architecture,Switch Statement,Oop,我正在开发一个项目,计算组件配置的各种因素。 配置由用户在运行时设置/更改。我有一个组件基类,所有配置项都是从它派生的 当需要时,从数据存储器中检索每个组件的信息。 为了使存储介质可以更改,我编写了一个DataInterface类作为中介 目前,存储介质是Access数据库。因此,DataInterface类打开数据库并创建查询字符串以提取相关数据。每个组件的查询字符串将不同 我遇到的问题是设计如何在组件类和DataInterface类之间调用GetData。我的解决方案演变如下: 1) Dat

我正在开发一个项目,计算组件配置的各种因素。 配置由用户在运行时设置/更改。我有一个组件基类,所有配置项都是从它派生的

当需要时,从数据存储器中检索每个组件的信息。 为了使存储介质可以更改,我编写了一个DataInterface类作为中介

目前,存储介质是Access数据库。因此,DataInterface类打开数据库并创建查询字符串以提取相关数据。每个组件的查询字符串将不同

我遇到的问题是设计如何在组件类和DataInterface类之间调用GetData。我的解决方案演变如下:

1) DataInterface对于每个组件类型都有一个公共方法getxxdata()。(其中XXX为组件类型)

2) DataInterface有一个公共方法GetData(componentType),并在组件类型内部进行切换

Sensor sensor = new Sensor();
sensor.Data = DataInterface.GetSensorData();
Sensor sensor = new Sensor();
sensor.Data = DataInterface.GetData(ComponentType.Sensor);
3) 抽象组件基类具有虚拟方法GetData(),每个派生类都会覆盖该方法。GetData()使用DataInterface类提取数据

Sensor sensor = new Sensor();
sensor.GetData(); 
//populates Data field internally. Could be called in constructor
对我来说,解决方案3似乎是最好的做事方式。然而,我仍然存在的问题是,DataInterface仍然需要打开调用方的类型,以确定要使用哪个查询字符串

我可以将这些信息放在每个组件对象中,但这样会将组件耦合到所选的存储介质。不好的。此外,组件不应关心数据的存储方式。它应该只调用其GetData方法并获取数据

希望这是有道理的。我所寻找的是一种实现上述功能的方法,它不依赖于使用开关类型

我仍在学习如何设计架构,欢迎对改进提出意见


TIA

首先,我同意每个组件对象的想法,因为它的构造函数负责请求其配置。事实上,这可能被推到了基类构造函数中。我们最终的结局是

DataInterface.GetData( getMyType() );
有点像电话

然后,您要问的主要问题是,我们如何实现GetData(类型)

实际上,您需要从类型到查询字符串的映射,并且不希望在添加新组件时更改代码。那么,提供一些数据驱动的方法怎么样。一个简单的外部配置来证明映射。然后只需更改配置以添加更多组件。

实际上,解决方案3是最糟糕的,因为它赋予了
传感器类人工责任。另外两个解决方案更好,因为它们将数据访问职责封装到不同的类中

我建议使用以下接口和类

interface IComponentDataReader 
{
    object GetData();
}

abstract class AbstractComponent
{
    private IComponentDataReader dataReader;

    public AbstractComponent(IComponentDataReader dataReader)
    {
        this.dataReader = dataReader;
    }

    protected object GetData()
    {
        return dataReader.GetData();
    }
}

class Sensor : AbstractComponent
{
    public Sensor(IComponentDataReader dataReader)
        : base(dataReader)
    {
    }

    public void DoSomethingThatRequiresData()
    {
        object data = GetData();

        // do something
    }
}

class SensorDataReader : IComponentDataReader
{
    public object GetData()
    {
        // read your data

        return data;
    }
}

class MyApplication
{
    public static void Main(string[] args)
    {
        Sensor sensor = new Sensor(new SensorDataReader());
        sensor.DoSomethingThatRequiresData();
    }
}

我希望这是有道理的。基本上,对于良好的OOD,如果你能让你的类只做一件事(单一责任原则),并且只知道它本身,你就会很好。您一定在问,如果传感器组件只知道自身,为什么会有一个
IComponentDataReader
传递给
SensorComponent
。在这种情况下,考虑这是提供给<代码> Syror组件< /C>(依赖注入),而不是请求它(它将在它自己的职责之外寻找)。

< P>如果我理解你的话,使它有点太复杂:

  • 使用getData()方法定义一个iterface(和一些connect、disconnect方法,也许还有一些异常也是个好主意)
  • 基于该接口为每个数据提供程序/不同存储类型派生一个单独的类,如“AcdcessStorage”、“MySQLStorage”、“WhateverStroage”
  • 现在,您可以快速地交换一个数据存储实现和另一个数据存储实现,每个实现有不同的连接方法/查询字符串,您可以同时使用多个存储,并通过静态接口方法对它们进行迭代,hass可以访问所有存储并将它们保存在列表中

  • 不需要任何开关。

    所以,如果我正确理解了你的答案;如果我添加一个新组件,比如电阻器,那么我还需要添加一个名为ResistorDataReader的类?是的。这是正确的。如果您喜欢声明式编程,甚至可以使用某种自动依赖项注入,根据组件需要实例化
    IComponentReader
    的正确实现。就个人而言,我更喜欢控制传递的信息。毕竟,作为开发人员,您知道解决方案是如何工作的,不同的类是如何协作的,因此最终您要负责进行正确的连接。要清除任何误解,您不需要组件和datareader之间的一对一映射。您可能有一个组件与另一个组件依赖相同的数据。在这种情况下,您将向两个组件传递相同的datareader。我想您已经知道可以有一个
    MSAccessSensorDataReader
    和一个
    SQLSensorDataReader
    ,它们都实现了
    IComponentDataReader
    。谢谢jeyoung。这似乎还可以。但是,我发现了一个问题,即如果我更改从Access数据库提取数据的方式,我将不得不更改每种不同类型的MSAccessXXXXXDataReader。这也意味着我将在多个对象(DataReaders)之间传播数据库代码,我希望将其全部保存在一个类中以帮助维护。如果不中断封装或创建紧密耦合,这似乎是不可能的。在
    MSAccessXYZDataReader
    类后面,您可以自由地将所有SQL代码放在一个大类中。重要的是,
    IComponentDataReader
    不再需要no-no-switch语句,并负责从组件类中获取数据。