2012-05-08 4 views
4

У меня сложный класс, и я хочу упростить его, реализовав класс фасада (предположим, что у меня нет контроля над сложным классом). Моя проблема заключается в том, что сложный класс имеет много методов, и я просто упрощу некоторые из них, и оставшаяся часть останется такой, какая есть. То, что я подразумеваю под «упрощением», объясняется ниже.Как упростить класс без написания уже простых методов?

Я хочу найти способ, который, если метод реализован с фасадом, затем вызовите его, если нет, то вызовите метод в сложном классе. Поэтому я хочу это писать меньше кода :) [меньше больше]

Пример:

Facade facade = // initialize 
facade.simplified(); // defined in Facade class so call it 

// not defined in Facade but exists in the complex class 
// so call the one in the complex class 
facade.alreadySimple(); 

Варианты, что приходит на ум ум:

Вариант 1: Напишите класс, содержащий переменную сложного класса и реализуйте сложные, а затем реализуйте простые с прямым делегированием:

class Facade { 
    private PowerfulButComplexClass realWorker = // initialize 
    public void simplified() { 
     // do stuff 
    } 
    public void alreadySimple() { 
     realWorker.alreadySimple(); 
    } 
    // more stuff 
} 

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

Вариант 2: Расширить сложный класс и реализовать упрощенные методы, но тогда будут видны как простые, так и сложные версии этих методов.

В питона можно добиться подобного поведения, как это:

class PowerfulButComplexClass(object): 
    def alreadySimple(self): 
     # really simple 

    # some very complex methods 


class Facade(object): 
    def __init__(self): 
     self.realworker = PowerfulButComplexClass() 
    def simplified(self): 
     # simplified version of complex methods in PowerfulButComplexClass 

    def __getattribute__(self, key): 
    """For rest of the PowerfulButComplexClass' methods use them as they are 
    because they are simple enough. 
    """ 
     try: 
      # return simplified version if we did 
      attr = object.__getattribute__(self, key) 
     except AttributeError: 
      # return PowerfulButComplexClass' version because it is already simple 
      attr = object.__getattribute__(self.data, key) 
     return attr 


obj = Facace() 
obj.simplified() # call the one we have defined 
obj.alreadySimple(# call the one defined in PowerfulButComplexClass 

Так что это путь Java для достижения этой цели?

Edit: Что я имею в виду «упрощение»: комплексный метод может быть либо метод слишком много аргументов

void complex method(arg1, arg2, ..., argn) // n is sufficiently large 

или набор связанных методов, которые почти всегда называют вместе, чтобы достичь одного задача

outArg1 = someMethod(arg1, arg2); 
outArg2 = someOtherMethod(outArg1, arg3); 
actualResult = someAnotherMethod(outArg2); 

поэтому мы хотим иметь что-то вроде этого:

String simplified(arg1, arg2, arg3) { 
    outArg1 = someMethod(arg1, arg2); 
    outArg2 = someOtherMethod(outArg1, arg3); 
    return someAnotherMethod(outArg2); 
} 
+1

Что вы подразумеваете под упрощением? Являются ли ваши более простые методы более быстрой специализацией или просто легче читать или что-то еще? Если это оптимизация специализации, то вариант 2 имеет смысл, и ваш простой метод должен проверить, разрешают ли аргументы простые случаи и вызывают стандартный суперкласс класса по умолчанию. Ваша Java IDE может записать все ваши заглушки для вас. – Julian

+0

Я отредактировал вопрос, чтобы уточнить, что я подразумеваю под упрощением. –

+0

ОК, так что это не тот класс, который вы хотите упростить, его программу, которую вы планируете писать, используя ее. Это имеет больше смысла. Тогда я больше склоняюсь к вашему инкапсуляционному подходу. Это означает, что вы только реализуете API, который вам нужен для вашей программы, и вы знаете, когда читаете свой фасад, что ни одна из «лишних» сложностей корневого класса нигде не используется. Это упростит ваши модульные тесты. – Julian

ответ

3

Это называется Наследие. Рассмотрим следующий код:

class Complex { 
    public function complex() { /* Complex Function */ } 
    public function simple() { /* Already simple function */ } 
} 

class SimplifiedComplex extends Complex { 
    public function complex() { /* Simplify Here */ } 
} 

Метод simple() будет работать на SimplifiedComplex объекта.

+1

таким образом вы все равно можете получить доступ к методу 'Complex.complex()', явно нажав на него: '((Complex) simplifiedComplexInstance) .complex()'. – yair

+2

@ yair фактически нет. DownCasting все еще вызывает метод переопределения. Однако изнутри класса вы можете вызвать 'super.complex()' и, возможно, добавить явный публичный метод для этого. Подробнее см. Здесь: http://stackoverflow.com/questions/1032847/can-java-call-parent-overridden-method-in-other-objects-but-not-subtype –

+0

@GuillaumePolet, вы поняли это правильно. Таким образом, решение Истины завершается, насколько это связано с вопросом. – yair

1

В зависимости от вашего варианта использования вы можете создать фасад перед некоторыми функциональными возможностями сложного класса, делегируя (вариант 1), и вместо предоставления поддержки остальной части функциональности в сложном классе вы предоставляют средства для доступа к сложному классу напрямую (getComplexClass).

Это может сделать дизайн более четким. Рассмотрим, например, сложный класс, обрабатывающий большинство функций банковской системы. Создание класса с именем «Учетная запись», которое имеет доступ к сложному классу, но использует только методы, относящиеся к банковскому счету, помогает проекту. Для удобства класс Account может иметь метод getBankSystemForAccount или что-то подобное.

2

Я думаю, вы уже это назвали. Я бы выбрал вариант 1. Он обеспечивает максимальную гибкость, учитывая жесткость java.

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

Наследование должно использоваться только для моделирования строгих отношений «есть», где подкласс обязательно содержит все свойства и поведение базового класса. Если вы используете наследование для чего-либо еще, вы просите о неприятностях.

Наконец, я не покупаю идею «Меньше больше» (вставьте невероятно краткий, неразборчивый пример perl). Я покупаю принцип «Код должен быть таким простым, каким он должен быть и не проще».

+0

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

1

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