В какой степени вы можете предотвратить изменение существующего кода при использовании шаблонов проектирования?

В школе я посещаю уроки по шаблонам проектирования и прочитал несколько глав книги Head First Design Patterns. Я хотел бы выяснить, в какой степени шаблоны проектирования могут предотвратить переписывание существующего кода.

Возьмем, к примеру, Duck классы и FlyBehavior классы. У меня есть в public static void main(String[] args) следующий код:

Duck mallard = new MallardDuck(new FlyWithWings());

Правильно ли я говорю, что вам неизбежно придется изменить свой main() метод, когда вы захотите добавить новую стратегию? Таким образом, вы изменяете существующий код, верно? Я конкретно имею в виду ту часть, где упоминается конкретный класс стратегии: new FlyWithWings().

Если вы внедрили шаблон фабричного метода в свой код, вы могли бы вообще запретить упоминание конкретного класса (FlyWithWings):

public FlyBehavior returnBehavior(FlyBehaviorFactory factory, String behaviorType) {
    return factory.getFlyBehavior(behaviorType);
}

И, таким образом, иметь следующую строку кода:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings"));

Таким образом, определенная часть вашей программы не должна знать, какую FlyBehaviorFactory использовать. Тем не менее, вашему методу main() все равно придется указывать определенные параметры в методе returnBehavior, чтобы знать, какая фабрика какую стратегию создаст. Таким образом, прав ли я, говоря, что вам все равно придется модифицировать main(), если я добавлю новый класс FlyBehavior и захочу добавить его в качестве параметра в returnBehavior()?

Можно ли еще улучшить эту ситуацию?


person Synchro    schedule 26.04.2015    source источник
comment
Вам следует взглянуть на внедрение зависимостей и различные фреймворки для Это.   -  person Seelenvirtuose    schedule 26.04.2015
comment
@Synchro Пожалуйста, прочитайте: Что мне делать, когда кто-то ответит на мой вопрос   -  person CKing    schedule 30.05.2015


Ответы (2)


В текущем примере вы жестко кодируете параметры, передаваемые вашей фабрике, и, таким образом, определяете поведение в compile time.

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings"));

Это можно изменить, чтобы добавить определенное поведение в runtime вместо compile time :

Duck mallard = new MallardDuck(returnBehavior(flyFactory, args[0]));

С указанным выше изменением вам никогда не придется менять свой метод main. Ваша фабрика может быть написана таким образом, что она throws и exception когда поведение, полученное во время выполнения, недоступно:

if(behaviorType.equals("wings") {
   //...create FlyWithWings
} else{
  //throw an appropriate exception indicating that the behavior does not exist
}

При этом изменение кода неизбежно, если вводится новое поведение. Хотя это изменение будет в одном месте и как можно дальше в вашем приложении, то есть в вашем factory, в котором, в первую очередь, заключается весь смысл factory. Кроме того, когда вы создаете новый FlyBehavior, вы делаете это, расширяя существующий класс. Это встроено в open-closed principle

person CKing    schedule 26.04.2015

Здесь вы делаете внедрение зависимостей, вы внедряете FlyBehaviour в Duck. Иногда при использовании такой инъекции зависимостей у вас может быть цепочка инъекций. Например, если вы хотите внедрить стратегию скорости в FlyBehaviour, у вас может быть что-то вроде этого.

Duck mallard = new MallardDuck(new FlyWithWings(new FastSpeed()));

Было бы нехорошо, если бы основной и любой другой класс, использующий Duck, должен был знать обо всех этих классах и каждый раз менять их. Лучшим решением было бы использование контейнера внедрения зависимостей, который отвечает за создание каждого из этих классов. Тогда в основном вы можете просто вызвать что-то вроде этого

Duck mallard = (Duck) Container.get('Duck');

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

person user2802557    schedule 13.07.2016