Объектно-ориентированный метод Параметры дизайна - PullRequest
1 голос
/ 03 февраля 2009

Я хочу разработать метод process (). Метод принимает некоторые данные в виде класса данных и обрабатывает их. Классы данных похожи, но немного отличаются.

Например, у нас есть следующие классы данных processDataObject_A, processDataObject_B и processDataObject_C.

Лучше ли перегрузить метод:

void process(processDataObject_A data)
{
//Process processDataObject_A here
}

void process(processDataObject_B data)
{
//Process processDataObject_B here
}

void process(processDataObject_C data)
{
//Process processDataObject_C here
}

ИЛИ пусть конкретные классы данных расширяют некоторый абстрактный класс данных и передают его в метод процесса, а затем заставляют метод проверять тип и действуют соответственно:

void process(AbstractProcessDataObject data)
{
//Check for type here and do something  
}

ИЛИ есть какой-то лучший способ решить эту проблему? Изменился бы подход, если бы это был веб-метод?

Заранее спасибо

Ответы [ 5 ]

8 голосов
/ 03 февраля 2009

Я бы пошел с:

process (data) {
   data.doProcessing();
}
1 голос
/ 03 февраля 2009

Я второй дизайн Марко. Представьте, что вам нужно добавить другой тип структуры данных и логику процесса, скажем, processDataObject_D. С вашим первым предложенным решением (перегрузка метода) вам придется изменить класс, добавив другой метод. Со вторым предложенным решением вам нужно будет добавить еще одно условие в оператор проверки типов и выполнения. Оба требуют, чтобы вы изменили существующий код. Решение Марко состоит в том, чтобы избежать изменения существующего кода, используя полиморфизм . Вам не нужно кодировать проверку типа if-else. Он позволяет добавлять новую структуру данных и логику процесса без изменения существующего кода , если новый класс наследует тот же суперкласс.

Изучение Паттерна стратегии паттернов дизайна даст вам полное теоретическое понимание проблемы, с которой вы столкнулись. Книга "Head First Design Pattern" от O'Reilly - лучшее из знакомых мне знакомых.

1 голос
/ 03 февраля 2009

Тот факт, что ваши методы возвращаются недействительными, заставляет меня поверить, что ваши обязанности могут быть изменены. Я думаю, что может быть лучше подумать об этом, так как каждый из ваших классов реализует интерфейс IProcessable, который определяет метод Process. Тогда каждый класс будет знать, как манипулировать своими собственными данными. Это, я думаю, менее связано, чем наличие класса, который манипулирует данными внутри каждого объекта. Предполагая, что все эти классы происходят от одного базового класса, вы можете поместить части алгоритма обработки, которые совместно используются в базовом классе.

Это немного отличается от случая, когда у вас может быть несколько алгоритмов, которые работают с идентичными данными. Если вам нужна такая функциональность, вам все же может потребоваться реализовать интерфейс, но метод Process должен принимать параметр типа стратегии и использовать фабрику для создания соответствующей стратегии на основе ее типа. Таким образом, у вас будет класс стратегии для каждого поддерживаемого алгоритма и пары классов данных, но вы сможете сохранить код изолированным. Я бы, вероятно, сделал бы это, только если бы алгоритмы были достаточно сложными, чтобы разделение кода делало его более читабельным. Если это всего лишь несколько строк, которые могут отличаться, вероятно, будет достаточно использовать оператор switch для типа стратегии.

Что касается веб-методов, я думаю, у меня будет другая подпись для класса. Правильное получение данных по сети будет намного проще, если методы будут принимать конкретные классы отдельных типов, чтобы он знал, как правильно сериализовать / десериализовать их. Конечно, на заднем плане веб-методы могут использовать подход, описанный выше.

public interface IProcessable
{
    public void Process() {....}
}

public abstract class ProcessableBase : IProcessable
{
    public virtual void Process()
    {
        ... standard processing code...
    }
}

public class FooProcessable : ProcessableBase
{
    public override void Process()
    {
        base.Process();
        ... specific processing code
    }
}

...

IProcessable foo = new FooProcessable();
foo.Process();

Реализация механизма, основанного на стратегии, немного сложнее.

Веб-интерфейс с использованием объектов доступа к данным

[WebService]
public class ProcessingWebService
{
    public void ProcessFoo( FooDataObject foo )
    {
        // you'd need a constructor to convert the DAO
        // to a Processable object.
        IProcessable fooProc = new FooProcessable( foo );
        fooProc.Process();
    }

}
0 голосов
/ 03 февраля 2009

Я верю, что Стратегия поможет вам.

0 голосов
/ 03 февраля 2009

Как насчет полиморфизма на AbstractProcessDataObject - то есть виртуального метода? Если это не подходит (разделение проблем и т. Д.), То перегрузка может показаться предпочтительной.

Re веб-методы; очень разные: ни полиморфизм, ни перегрузка не очень хорошо поддерживаются (по крайней мере, не в базовом профиле). Опция обнаружения «Проверьте здесь и сделайте что-нибудь» может быть лучшим маршрутом. Или иметь разные именованные методы для каждого типа.


за запрос:

abstract class SomeBase { // think: AbstractProcessDataObject
    public abstract void Process();
}
class Foo : SomeBase {
    public override void Process() { /* do A */ }
}
class Bar : SomeBase {
    public override void Process() { /* do B */ }
}
SomeBase obj = new Foo();
obj.Process();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...