Как удалить дублирующийся код для всех классов, реализующих интерфейс, не наследуя от конкретного класса? - PullRequest
2 голосов
/ 14 декабря 2009

У меня вопрос по шаблону. У меня есть платформа для нашего приложения для смарт-клиентов, похожая на CAB (блок составного приложения), и мы называем его widget-framework. Где мы можем определить модули нашего приложения как «Виджет», и есть файл конфигурации, в котором перечислены все виджеты. Виджет - это любой класс, который реализует интерфейс IWidget. Все виджеты имеют код для загрузки подвиджетов, и этот код идентичен. Как поделиться этим кодом среди всех этих виджетов, не заставляя виджет наследоваться от конкретного класса? Какова лучшая практика в этом случае? Есть ли шаблон дизайна для этого случая?

Спасибо

Ответы [ 8 ]

2 голосов
/ 14 декабря 2009

вы можете использовать составной метод, создать объект с именем SubWidgetLoader или что-то подобное, а затем сделать так, чтобы все экземпляры IWidget содержали экземпляр класса загрузчика.

1 голос
/ 14 декабря 2009

Похоже, шаблон Decorator можно использовать для добавления метода «загрузки подвиджетов» в каждый класс. Этот шаблон позволяет изменять метод «загрузки подвиджетов» для разных классов, не полагаясь на наследование.

0 голосов
/ 09 мая 2011

На других языках это может быть достигнуто с помощью миксинов. В C # вы можете получить что-то близкое, определив методы расширения в интерфейсе ...

interface IWidget
{
    ICollection<IWidget> SubWidgets { get; set }
}

static class WidgetExtensions
{
    static public void LoadSubWidgets(this IWidget widget)
    {
        widget.SubWidgets.Add(GetSomeWidgetDependency());
    }
}
0 голосов
/ 14 декабря 2009

Почему бы не получить их все из общего базового класса? Это может быть абстрактный базовый класс, поскольку вы обеспокоены тем, что они не наследуются от конкретного базового класса. Абстрактный базовый класс может предоставлять функции «загрузки подвиджетов», которыми они все обладают.

Но если вы склонны избегать наследования, то шаблон Builder кажется подходящим для повторного использования кода построения деревьев подвиджетов без введения базового класса.

http://en.wikipedia.org/wiki/Builder_pattern

0 голосов
/ 14 декабря 2009

Почему вы не наследуете от базового класса?

Ваша ситуация кажется подходящей для шаблона метода . Я думаю, что наследование является лучшим решением, если нет веских причин не делать этого. В вашем конкретном случае наследование от BaseWidget также кажется логичным шагом.

Примечание: Я знаю, что вы конкретно спрашиваете, как НЕ использовать наследование, но вы не говорите нам, почему. Я думаю, что если кто-то специально просит что-то, что противоречит моим обычным тенденциям в разработке программного обеспечения, он должен объяснить не только что, но и почему, если он не отказывается просто дать ответ (если я знаю это), если я думаю, что просто «дизайн» не так.

0 голосов
/ 14 декабря 2009

Если вы не хотите расширять суперкласс с помощью общего кода, вы можете попытаться использовать делегирование и обернуть общие функции, давайте назовем его SubWidgetLoader. То есть создайте класс, который реализует общую функциональность, и ваши объекты IWidget содержат SubWidgetLoader. Таким образом, для каждого отдельного виджета не нужно повторять код, а нужно вызывать класс SubWidgetLoader для выполнения задания.

0 голосов
/ 14 декабря 2009

Я бы сделал это по совокупности. Создайте класс WidgetLoader и используйте его для реализации своих функций загрузки подвиджетов.

Это позволяет отделить загрузочную функциональность от основного намерения вашего класса Widget, избежать наследования и может быть слабосвязанным, если создается на фабрике.

0 голосов
/ 14 декабря 2009

Звучит как прекрасная возможность использовать абстрактный класс, который наследуется от интерфейса. Но, похоже, есть причина не делать этого.

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

...