Переопределение внутреннего метода с помощью шаблона Designrator Design - PullRequest
1 голос
/ 14 июня 2019

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

Вот псевдокод того, чего я пытаюсь достичь:

interface I{
  complex();
  step1();
  step2();
}
class C implements I{
  complex(){
    ...
    this.step1();
    ...
    this.step2();
  }
  step1(){
    ...
  }
  step2(){
    ...
  }
}
abstract class Decorator implements I{
  I wrapped;
  constructor(I obj){
    this.wrapped = obj;
  }
  complex(){
    this.wrapped.complex();
  }
  step1(){
    this.wrapped.step1();
  }
  step2(){
    this.wrapped.step2();
  }
}
class ConcreteDecorator extends Decorator{
  constructor(I obj){
    super(obj);
  }
  step2(){
    ... // customizing step2()
  }
}

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

Теперь, если я попытаюсь создать объект декорированного класса:

x = new C();
y = new ConcreteDecorator(x);
y.complex();

Я ожидаю, что метод complex() будет выполнен из обернутого основного объекта при использовании переопределенного метода step2() из декоратора. Но он не работает таким образом, поскольку метод complex () в абстрактном декораторе напрямую вызывает метод на базовом объекте, который действительно пропускает переопределенный step2() в декораторе.

Моя общая цель - разрешить декораторам переопределять только один или несколько методов stepx(), которые будут вызываться методом complex(), который уже реализован в базовом объекте и вызывает все шаги.

Может ли эта функция быть реализована с использованием шаблона проектирования Decorator? Если да, то как, а если нет, то каков соответствующий шаблон проектирования для решения этой проблемы.

Спасибо.

Ответы [ 2 ]

1 голос
/ 14 июня 2019

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

interface IStrategy {
  step1(IData data);
  step2(IData data);
}

interface I {
  complex();
}

class C implements I {
  IData data

  constructor(IStrategy strategy) {}

  complex() {
    ...
    this.strategy.step1(this.data);
    ...
    this.strategy.step2(this.data);
  }
}

class S1 implements IStrategy {
  constructor(IStrategy strategy)

  step1(IData data) {
  }

  step2(IData data) {
  }
}

strategy1 = new S1();
c = new C(strategy1)
1 голос
/ 14 июня 2019

Проблема, с которой вы сталкиваетесь, заключается в том, что в вашем приложении шаблона проектирования Decorator, поскольку вы не декорируете complex(), вызов complex() для объекта декоратора будет делегирован декорированному объекту, который имеет "нормальный""версия step2.

Я думаю, что более подходящим шаблоном дизайна для решения вашей проблемы будет Шаблонный метод шаблон проектирования.

В вашем случае complex()будет играть роль шаблонного метода , шаги которого могут настраиваться подклассами.Вместо использования композиции вы используете наследование, а остальное остается более или менее одинаковым.

Вот пример приложения шаблона проектирования Template Template для вашего контекста:

public interface I {
    void complex();
    void step1(); // Better to remove from the interface if possible
    void step2(); // Better to remove from the interface if possible
}

// Does not need to be abstract, but can be
class DefaultBehavior implements I {

    // Note how this is final to avoid having subclass
    // change the algorithm.
    public final void complex() {
        this.step1();
        this.step2();
    }

    public void step1() { // Default step 1
        System.out.println("Default step 1");
    }

    public void step2() { // Default step 2
        System.out.println("Default step 1");
    }
}

class CustomizedStep2 extends DefaultBehavior {

    public void step2() { // Customized step 2
        System.out.println("Customized step 2");
    }
}
...