Как сократить шаблон кода в составной / украсить шаблон - PullRequest
2 голосов
/ 13 мая 2019

В составном / декорированном паттерне внешний контейнер переопределяет некоторые методы, чтобы изменить поведение, но для остальных методов приходится делегировать субкомпоненту.

Пример: класс A имеет 10 методов, класс B содержит A, но переопределяет только 2 метода, тогда B должен переопределить 8 методов, просто чтобы делегировать экземпляру A внутри.Как вырезать эти шаблонные коды в Java и Python?

РЕДАКТИРОВАТЬ: я стараюсь не расширять B, потому что я пытаюсь быть более сложным, чем наследование.

Ответы [ 3 ]

0 голосов
/ 24 мая 2019

Хотя в самом языке Java нет функции, которая спасает вас, вы можете взглянуть на @Delegate аннотацию Lombok здесь , чтобы узнать меньше шаблонов (это то, что делает проект lombok).Для вашего примера в вашем вопросе это может выглядеть так:

interface A {

    void method1();

    void method2();

    // ... 8 more methods
}

public class B implements A {

    private interface AOverride {

        void method1();
    }

    @Delegate(types = A.class, excludes = AOverride.class)
    private final A delegate;

    public B(final A delegate) {
        this.delegate = delegate;
    }

    @Override
    public void method1() {

    }
}

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

0 голосов
/ 24 мая 2019

Lombok имеет экспериментальную @Delegate функцию, которую вы можете попробовать:

public class DelegationExample {

  private interface SimpleCollection {
    boolean add(String item);
    boolean remove(Object item);
  }

  @Delegate(types=SimpleCollection.class)
  private final Collection<String> collection = new ArrayList<String>();
}
0 голосов
/ 24 мая 2019

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

class A implements Decorator{    
    @Override
    public void decorate(){
      System.out.print("Decorate A");
    }

    @Override
    public void help(){
      System.out.print("Help");
    }

}

class B implements Decorator{    
    private Decorator member;

    public B(Decorator decorator){
      this.member = decorator;
    }

    @Override
    public void decorate(){
      member.decorate();
      System.out.print("Decorate B");
    }

    @Override 
    public void help(){
      //***you need the behaviour of A here
      member.help();
    }
}

Decorator d = new B(new A());
b.help();

Так что в строке // **, если вы хотите поведениетам просто сделайте B extends A вместо расширения / реализации абстрактного класса / интерфейса.Тогда вам не нужно делегировать.Это поведение будет унаследовано.

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

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

public class RemovalCountingList<E> implements List<E> {
    @Delegate(excludes = ExcludedListMethods.class)
    private final List<E> delegate;
    private final AtomicInteger removalCount = new AtomicInteger();
    public RemovalCountingList(List<E> delegate) {
        this.delegate = delegate;
    }
    @Override
    public E remove(int index) {
        System.out.println("Removal count: " + removalCount.incrementAndGet());
        return delegate.remove(index);
    }
    @Override
    public boolean remove(Object o) {
        boolean isRemoved = delegate.remove(o);
        if (isRemoved) {
            System.out.println("Removal count: " + removalCount.incrementAndGet());
        }
        return isRemoved;
    }
    /**
     * Excluded methods that Lombok will not implement, we will implement/override these methods.
     */
        private abstract class ExcludedListMethods {
            public abstract E remove(int index);
            public abstract boolean remove(Object o);
        }
    }

public class ClientMain {
    public static void main(String[] args) {
        RemovalCountingList<String> cities = new RemovalCountingList<>(new ArrayList<>());
        cities.add("London");
        cities.add("Paris");
        cities.add("Istanbul");
        cities.add("Tokyo");
        String removedCity = cities.remove(0);
        System.out.println("Removed city: " + removedCity);
        boolean isRemoved = cities.remove("Istanbul");
        System.out.println("Is removed?: " + isRemoved);
    }
}

Это поможет вамчтобы удалить ваши стандартные коды.

...