2010-03-04 3 views
1

Функция класса:Гадкого определение интерфейса класса

  1. Получит последовательность кадров изображения, последовательность является бесконечной .
  2. Определите, есть ли движение в кадрах.
  3. Группа кадров движения в соответствии с определенным алгоритмом.

До сих пор дизайн (довольно глупо):

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. Способ уведомления клиента о том, что группа захвачена.

Можете ли вы дать несколько советов по дизайну интерфейса класса, так что для потребителя этот класс проще и элегантнее?

+0

Что именно вы чувствуете неудобно? – AxelEckenberger

+0

@ Obalix, отредактированный, чтобы добавить то, что мне не удобно. – Benny

ответ

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, который затем делает все, что ему нужно.

Таким образом, классы прекрасно разделены с обязанностями, и очень мало сделано с учётом состояния - все состояния локализованы для отдельных классов. Поскольку вызовы все недействительны, они могут быть отправлены на произвольные потоки, если вам нужно.

Возможно, FramePump активируется по таймерному циклу.

Я бы, вероятно, подумал о том, чтобы разбить алгоритм группировки на отдельный класс - пусть класс motiondetector выплескивает каждый кадр вместе с bool, указав, было ли обнаружено движение, а затем класс MotionGrouper будет брать их отдельно, и выплескивать списки кадров в соответствии с любым алгоритмом. «Обнаружение движения» и «определение того, как группировать фреймы», довольно четко соответствуют двум обязанностям. Но должно быть ясно, как вы будете делать этот рефакторинг в этом общем виде проектирования трубопроводов.

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); 
} 

EDIT о разрешении потребителя знайте захваченную группу, используя событие, как это предложено в комментариях:

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*/)); 
    } 
    }  
} 
+0

Хороший момент, как насчет того, как сообщить потребителю, что группа захвачена и как получить группу? – Benny

+0

Третий пример - самый чистый, ИМО. Люди получают зависание при возврате логических значений иногда, когда простой нулевой тест работает одинаково и намного удобнее обслуживать. – Chris

+0

Что касается вопроса о том, чтобы сообщить потребителю, что группа захвачена, почему бы не использовать событие? – Chris

3

Потребительский класс выполняет работу, которую должен выполнять MotionDetector. Возможно, конструктор MotionDetector (или некоторый метод в классе) должен взять поток кадров, и эта работа должна быть выполнена внутренне. Класс должен выставлять только необходимый массив изображений после запуска алгоритма.

+0

Извините, последовательность кадров бесконечна. – Benny

+0

В этом случае он все еще может использовать поток, но выставлять неизменный IList . –

Смежные вопросы