English 中文(简体)
Fine-grained decorator pattern
原标题:

I understand the Decorator pattern, in it s simplest terms. The idea being that one class wraps another, where a decorator method wishes to run some other code before and/or after calling the same method on the decorated object.

However, I have run into the situation where I cannot simply call the decorated method, as it has some undesired side-effects. However I do want much of that decorated method to run.

So I believe that I need to split the decorated method into multiple methods, then in the decorator I can call some of them, run my decorating code, then call some others - missing out the side-effect I don t want.

However in order to maintain polymorphism, that would mean adding those methods to the interface that the decorated and decorator objects implement. This is undesirable; they should not be public, and it effectively means the decorated class has knowledge of how it will be decorated.

I believe that the Template pattern is possibly more appropriate, where an abstract base class calls each of the smaller methods in turn, where the "decorator" simply supplies an alternative implementation for the ones it cares about. However this isn t exactly "composition over inheritance", so what do you recommend?

最佳回答

It sounds like your API violates Command-Query Separation so your best option would be to redesign the API.

However, in case I m mistaken or redesign is not possible, perhaps you could split the method of the decorated class into two methods without changing the interface.

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);
    }
}

Notice that MyDecorator decorates MyClass instead of IMyInterface.

问题回答

Sounds like Template suits your scenario best. I wouldn t force composition when not needed ... this conversation said it best, "...exceptions to this rule: when you should use inheritance i.e. if you need to model substitutability."





相关问题
Choosing the right subclass to instantiate programmatically

Ok, the context is some serialization / deserialization code that will parse a byte stream into an object representation that s easier to work with (and vice-versa). Here s a simplified example ...

Design pattern for managing queues and stacks?

Is there a design pattern for managing a queue or a stack? For example, we are looking to manage a list of tasks. These tasks will be added to a group queue, users will then be able to pull off the ...

Organizing classes using the repository design pattern

I have started upgrading one of our internal software applications, written in ASP.NET Web Forms, and moving to ASP.NET MVC. I am trying to leverage the Repository design pattern for my classes, ...

Misuse of Observer Pattern?

I have a Car object which contains a latitude field and a longitude field. I use the observer pattern so that any time either of these fields change in my application, my car object is notified. I ...

How are Models (in MVC) and DAOs supposed to interact?

How are models and DAOs supposed to interact? I m in the process of putting together a simple login module and I m unsure where to put the "business logic." If I put the logic with the data in the ...

热门标签