代码之家  ›  专栏  ›  技术社区  ›  Jonathon Reinhart

接口C布局的正确方法#

  •  1
  • Jonathon Reinhart  · 技术社区  · 17 年前

    我在设计程序的一部分时遇到了问题(一次也不写!)如果不写小说,这很难解释,所以我会尽量简短。

    基本上,我有一个从硬件读取/写入参数的程序。目前,它是通过串行方式实现的,但最终,我希望它通过USB来实现,使用ftdi芯片的.NET包装器。 http://www.ftdichip.com/Projects/CodeExamples/CSharp.htm

    我想我的问题是,我知道我需要几个抽象层,但我似乎不知道在哪里画线。首先,我不想要我的 ReadParam() , WriteParam() SendCommand() 函数将在我的主窗体类中。这似乎是胡说八道。所以很明显,它们应该在其他类中,我将实例化。让我们称之为 Comm 现在。

    第一种选择是,我可以做一个接口,比如说 IComm 我的串行和USB风格都实现了这一点。问题是,大部分代码都会以两种风格复制,因为我有 ReadReplyData() 以及其他功能,它们在将串行数据返回到GUI之前对其进行预处理。

    所以下一个选项是让comm成为一个中介类,它定义了一个接口 ICommDriver . 康姆 将实现一个私有 Read RealDyDATA() 格式化函数,以及公共 读参数() , 写参数() SDENTCOMD() 函数,而 ICM驱动程序 只会指定更简单的 Read Write 功能。

    这一切似乎微不足道,除了两个曲折。首先,我希望这个是多线程的,很明显,这样图形用户界面就不会挂起。所以我想 康姆 将使用 BackgroundWorker 做所有的读/写。此外,还需要告诉串行风格(从GUI下拉列表中)要打开哪个COM端口,而USB风格不需要。那么,我是否要将其作为接口的一部分呢?

    感谢大家的帮助,我已经写/删除代码好几天了,试图找出正确的方法来做到这一点!

    乔纳森

    3 回复  |  直到 17 年前
        1
  •  7
  •   Rex M    17 年前

    我知道我想要几层 抽象,但我似乎不知道 在哪里画线

    这就是你的问题所在。这是一种根本上有缺陷的发展方法,正是它导致了这种瘫痪。发展若干 混凝土 首先实现风格。让他们使用Kludgy在应用程序中工作 if type1 else type2 逻辑。 然后 返回并重构它们,以共享一个共同的契约、共同的基础、你拥有什么。它将是 非常明显 需要去哪里。

    更多详情请参见评论:

    如果您在实现之间共享了代码,那么应该使用抽象类。根据我的经验,最好的做法是保持公共方法的最终性,并从公共方法中调用受保护的抽象方法,例如:

    public interface IComm
    {
        void WriteParam(...);
    }
    
    public abstract class CommStandardBase : IComm
    {
        public void WriteParam(...)
        {
            DoWriteParam(...);
        }
    
        private void DoWriteParam(...)
        {
            CommonWrite1(...);
            HandleWriteParam(...);
            CommonWrite2(...);
        }
    
        protected abstract void HandleWriteParam(...);
    
        private void CommonWrite1(...)
        {
            ...
        }
    
        private void CommonWrite2(...)
        {
            ...
        }
    }
    

    使每个类独立。它应该是单实例、单线程的,并且可以在工人和记者之间传递。

        2
  •  1
  •   jrista    17 年前

    至于您究竟需要哪种接口,这最终取决于您和任何知道此应用程序如何在如此低的级别上工作的人。我想回答关于在UI中使用您的实现的部分,以及关于使用后台工作人员进行通信的注释。我建议你把它倒过来。BackgroundWorker实际上是一个UI级组件……但是comm更像是一个“中心”组件(就像企业应用程序中的业务对象)。您的UI应该创建一个backgroundworker,然后创建comm实例来执行所需的工作,并协调comm中的任何事件来更新UI。如果您需要UI和BackgroundWorker在较长的时间内进行通信,我建议您创建某种数据传输对象,您的UI可以创建、放入队列,并使用ManualReseteEvent或AutoResetEvent线程句柄在UI线程和BackgroundWorker之间进行通信。这将为您提供一个更松散耦合的产品,允许您独立地开发可能显示它的任何类型的UI(可能允许您拥有windforms、wpf、命令行,甚至PowerShell客户机)。

        3
  •  1
  •   Saif Khan    17 年前

    我现在有点像vb.net模式,所以这里……

    
    Interface IComm
    
        Function ReadParam()
        Function WriteParam()
        Function SendCommand()
    
    End Interface
    
    
    
    >
    
    
    MustInherit Class CommBase
    
    .... Load this up with the overideable
    
    End Class
    
    
    
    

    然后只需实现接口并在需要时继承基。我也同意Rex M的观点。不要把它推得太远而导致松耦合。