#java #c #oop #design-patterns
#java #c #ооп #шаблоны проектирования
Вопрос:
У меня есть абстрактный метод, который устанавливает метку графического элемента. Существуют различные типы элементов, все из которых наследуются от абстрактного базового класса, который имеет метод «setLabel ()».
Разные элементы выполняют разные действия, когда они устанавливают метку, но в конце все они должны делать одно и то же, что представляет собой серию действий по ведению домашнего хозяйства. Я знаю, что могу создать метод в базовом классе для выполнения этих задач, а затем вызывать его в каждой из реализаций, но это плохо, потому что, помимо прочего, если я забуду вызвать его из одной из реализаций, это создаст ошибку.
Каков хороший способ структурировать это?
Вот пример кода (как я делаю это сейчас на Java):
final public void _setLabel( String s ){
if( s.trim().equals( "null" ) ) return;
StringBuffer sbError = new StringBuffer();
if( ! _setConstantValue( s, sbError ) ){
Error.vShowError( "failed to set value: " sbError );
return;
}
sLabel = s;
_update();
_updateProperties();
if( _isGroupMember() ) this.nodeGroup._update();
}
В базовом классе есть абстрактный метод «_setLabel», поэтому все мои подклассы ДОЛЖНЫ реализовывать этот метод. Последние три строки в методе всегда одинаковы:
_update();
_updateProperties();
if( _isGroupMember() ) this.nodeGroup._update();
Прямо сейчас я просто копирую и вставляю эти строки в каждую реализацию, но я бы предпочел, чтобы они каким-то образом выполнялись в базовом классе, поэтому я могу гарантировать, что они всегда встречаются. Они должны вызываться после всего остального.
РЕШЕНИЕ:
Основываясь на приведенном ниже ответе (благодаря user3736255), решение заключается в использовании невиртуального интерфейса на C или шаблонного метода на Java (что эквивалентно). Итак, новый код базового класса:
final public void _setLabel( String s ){
__setLabel( s );
_update();
_updateProperties();
if( _isGroupMember() ) this.nodeGroup._update();
}
abstract protected void __setLabel( String s );
Каждый подкласс реализует __setLabel
метод, который вызывается шаблонным методом _setLabel
в базовом классе.
Комментарии:
1. Рассматривали ли вы возможность использования интерфейса ?
2. @CanadianDavid это было бы излишним, я просто пытаюсь установить здесь метку.
3. По-настоящему универсального способа добиться этого не существует. Каждый язык будет иметь свой собственный набор ограничений наследования, которые изменяют способ достижения этой цели, если это вообще возможно.
4. Почему вы пометили его C , если хотели, чтобы все ответы были на Java?
5. @CanadianDavid Потому что я думал, что у него может быть один и тот же ответ на обоих языках.
Ответ №1:
Похоже, вы ищете шаблон невиртуального интерфейса: http://en.wikibooks.org/wiki/More_C++_Idioms/Non-Virtual_Interface
Комментарии:
1. Это было бы решением, но как мне это сделать на Java?
2. В Java используйте шаблон шаблона метода так же, как NVI: en.wikipedia.org/wiki/Template_method_pattern
Ответ №2:
Может быть:
class Base() {
public:
void setLabel();
protected:
virtual void doSetLabel();
private:
houseKeepingBefore();
houseKeepingAfter();
}
void Base::setLabel() {
houseKeepingBefore();
doSetLabel();
houseKeepingAfter();
}
Но это не решит вашу проблему, если у вас есть houseKeepingInbetween
.
Комментарии:
1. Мне нужно только заняться домашним хозяйством после. Как мне это сделать на Java?
Ответ №3:
Вы хотите создать декоратор, который расширяет базу и создается с помощью соответствующего экземпляра графического элемента. Ответственность за выполнение действий по ведению домашнего хозяйства лежит на декораторе. Все клиенты вызывают декоратор вместо фактического графического элемента. Примечание: я предполагаю, что все вызовы графического элемента выполняются через определенные / объявленные методы в базе.
Возможно, вы могли бы также использовать аспекты: http://en.wikipedia.org/wiki/Aspect-oriented_programming
Комментарии:
1. Не уверен, решит ли это проблему OP, поскольку им все равно придется не забывать украшать каждый метод, который нуждается в обслуживании во всех подклассах.
2. Не уверен, что это было бы так, если декоратор является прокси для всех подклассов.