Мелкозернистый узор декоратора - PullRequest
3 голосов
/ 18 января 2010

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

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

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

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

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

Ответы [ 2 ]

2 голосов
/ 18 января 2010

Звучит так, как шаблон лучше всего подходит для вашего сценария. Я бы не стал форсировать композицию, когда она не нужна ... этот разговор сказал лучше всего: "... исключения из этого правила: когда вам следует использовать наследование, т.е. если вам нужно смоделировать заменяемость".

1 голос
/ 18 января 2010

Похоже, ваш API нарушает Разделение команд-запросов , поэтому лучшим вариантом будет перепроектировать API.

Однако, если я ошибаюсь или перепроектирование невозможно, возможно, вы могли бы разделить метод оформленного класса на два метода без изменения интерфейса.

public interface IMyInterface
{
    Foo GetFoo(Bar bar);
}

public class MyClass : IMyInterface
{
    public Foo GetFoo(Bar bar)
    {
        this.DoSomethingWithSideEffects(bar);
        return this.DoSomethingToGetFoo(bar);
    }

    public Foo DoSomethingToGetFoo(Bar bar)
    {
        // ...
    }

    public void DoSomethingWithSideEffects(Bar bar)
    {
        // ...
    }
}

public class MyDecorator : IMyInterface
{
    private readonly MyClass mc;

    public MyDecorator(MyClass mc)
    {
        // put Null Guard here...
        this.mc = mc;
    }

    public Foo GetFoo(Bar bar)
    {
        return this.mc.DoSomethingToGetFoo(bar);
    }
}

Обратите внимание, что MyDecorator украшает MyClass вместо IMyInterface.

...