开发者

Filter/Compontent pattern instead of clumsy inheritance?

I have a:

class ServiceObject {

    ServiceClass svcClass;

    void execute(String operation, Map arguments, ...) {
        svcClass.execute(this, operation, arguments, ...);
    }

}

Then I have a subclass of that to add in synchronization:

class SynchronizedServiceObject extends ServiceObject {

    void execute(String operation, Map arguments, ...) {
        synchronized(lock) {
            super.execute(operation, arguments, ...);
        }
    }

}

I also have a subclass to add a logging context

class LogContextServiceObject extends ServiceObject {

    void execute(String operation, Map arguments, ...) {
        MDC.set("context", myCtx);
        super.execut开发者_如何学编程e(operation, arguments, ...);
        MDC.remove("context");
    }

}

However, if I want to use both features, I would need to write another subclass which has them both. You can imagine that with more added features (logging, request rewriting, etc.) I would have to write a lot of classes for every combination I need.

Instead, I'd like to ditch the subclasses and pass some sort of filter or component objects at the creation of ServiceObject. What's a recommended pattern for this (In Java, or in general).


In terms of famous GoF book: Decorator.

public class LoggingDecorator implements ServiceObject {

    private final ServiceObject decoratee;

    public LoggingDecorator(ServiceObject decoratee) {
        this.decoratee = decoratee;
    }


    @Override
    public void execute(String operation, Map<?, ?> arguments) {
        MDC.set("context", myCtx);
        try {
            decoratee.execute(operation, arguments);
        } finally {
            MDC.remove("context");
        }
    }
}

public class SynchronizedDecorator implements ServiceObject {

    private final ServiceObject decoratee;

    private final Object lock = new Object();

    public SynchronizedDecorator(ServiceObject decoratee) {
        this.decoratee = decoratee;
    }

    @Override
    public void execute(String operation, Map<?, ?> arguments) {
        synchronized (lock) {
            decoratee.execute(operation, arguments);
        }
    }
}

After all you can combine them as you like:

ServiceObject serviceObject =
                    new LoggingDecorator(
                            new SynchronizedDecorator(
                                    new ServiceObjectImpl()
                            )
                    );


Easiest solution is to create a factory class and enumerator:

enum ServiceObjectType { SynchronizedServiceObject ,LogContextServiceObject ,ServiceObject }
static class ServiceObjectFactory {
    ServiceObject NewService(ServiceObjectType  type) {
        switch(type) {
           case ServiceObjectType.SynchronizedServiceObject: return new SynchronizedServiceObject();
           case ServiceObjectType.LogContextServiceObject : return new LogContextServiceObject ();
           case ServiceObjectType.ServiceObject : return new ServiceObject (); 
        }
    }
}

Usage:

ServiceObject blah1 = ServiceObjectFactory.NewService(ServiceObjectType.SynchronizedServiceObject);
ServiceObject blah2 = ServiceObjectFactory.NewService(ServiceObjectType.LogContextServiceObject);


It sounds very much like the Chain of Responsibility pattern. This is often described as propagating a request until some handler can take responsibility, but it is also used to propagate a request until some handler "consumes" it. In your case, you want to unconditionally propagate to all handlers.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜