丑陋的类接口定义

时间:2010-03-04 08:30:52

标签: c# class-design

班级的功能:

  1. 接收一系列图像帧,序列为 无限
  2. 检测帧中是否有动作。
  3. 根据特定算法对运动帧进行分组。
  4. 到目前为止,设计(非常愚蠢):

    class MotionDetector
    { 
          //detect motion in the frame, return true if the group is captured. 
          //frameToDispose is the frame that need be dispose, or for further process.
          public bool ProcessFrame(Frame in, out frameToDispose); 
        }
    

    消费者(摘录):

    public void Foo()
    {
         bool groupCaptured = motionDetector.ProcessFrame(nextFrame, out lastFrame);
    
        if (IsStaticFrame(lastFrame)) { lastFrame.Dispose(); }
        else { imagesArray.Add(lastFrame); }
    
        if(groupCaptured) { processImageGroup(imagesArray);  }
    }
    

    我对MotionDetector的设计感到不安:

    1. 获取图像组的方法。
    2. 处理不动框架的方法。
    3. 通知客户端捕获的群组的方式。
    4. 您能否就课程的界面设计提出一些建议,以便客户使用此课程更容易,更优雅?

3 个答案:

答案 0 :(得分:3)

消费者类正在做MotionDetector应该做的工作。也许MotionDetector构造函数(或类中的某个方法)应该采用帧流,这项工作应该在内部完成。该算法运行后,该类应仅显示必需的图像数组。

答案 1 :(得分:1)

如果我理解你的问题,你不喜欢你班级的客户必须使用你提供的方法......左右 如何使框架处理类的属性而不是out参数?

class MotionDetector{ 

  public bool PreProcessFrame(Frame in); 

  public Frame frameToDispose{
    get;        
  }      
}

然后你就可以使用它:

bool groupCaptured = motionDetector.ProcessFrame(nextFrame);
if (IsStaticFrame(motionDetector.frameToDispose)){
  // ...
}

否则(如果你的应用程序有意义)你可能会这样做:

class MotionDetector{       
  // returns frame to dispose if sucessful, null otherwise
  public Frame PreProcessFrame(Frame in); 
}

编辑关于让消费者知道所捕获的群组,使用评论中建议的事件:

class GroupCapturedEventArgs : EventArgs{
  // put relevant information here...
}
class MotionDetector{
  public event EventHandler<GroupCapturedEventArgs> GroupCaptured;
  // then somewhere in your code:
  private vois SomeMethod() {
    // a group captured
    if (GroupCaptured != null) {
      GroupCaptured (this,new GroupCapturedEventArgs(/*whatever*/));
    }
  }      
}

答案 2 :(得分:1)

我可能会这样做:

public class MotionDetector
{
    private IFrameGroupListener m_listener;

    public MotionDetector(IFrameGroupListener listener)
    {
        m_listener = listener;
    }

    public void NewFrame(Frame f)
    {
        if(DetectMotion(f))
        {
            var group = GetCaptureGroup();
            m_listener.ReceiveFrameList(group);
        }
    }
}

public interface IFrameGroupListener
{
    void ReceiveFrameList(IList<Frame> captureGroup);
}

public class FramePump
{
    private MotionDetector m_detector;

    public FramePump(MotionDetector detector)
    {
        m_detector = detector;
    }

    public void DoFrame()
    {
        Frame f = GetFrameSomehow();
        m_detector.NewFrame(f);
    }

}

我假设DetectMotion()存储了框架,否则你必须将它保留在待处理列表中,直到它摆脱它为止。无论如何,FramePump从实际设备/文件中获取单独的帧。这是它的工作。 MotionDetector负责检测运动,并将带有运动的帧组传递给FrameGroupListener,然后FrameGroupListener执行它需要做的任何事情。

通过这种方式,类很好地与责任分开,而且很少以有状态的方式完成 - 所有状态都本地化到各个类。由于调用都是无效的,如果需要,可以将它们分派到任意线程。

FramePump可能会在某种定时器循环上被触发。

我可能会考虑将分组算法分解为一个单独的类 - 让运动检测器类向每个帧吐出一个bool,指示是否检测到运动,然后MotionGrouper类将单独采用这些类,根据所需的算法吐出帧列表。 “检测运动”和“确定如何对帧进行分组”显然是两个责任。但是,应该清楚如何在这种一般的管道设计中进行重构。