过滤器/组件模式而不是笨拙的继承?

发布于 2024-10-25 18:32:42 字数 952 浏览 1 评论 0原文

我有一个:

class ServiceObject {

    ServiceClass svcClass;

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

}

然后我有一个要在同步中添加的子类:

class SynchronizedServiceObject extends ServiceObject {

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

}

我还有一个子类来添加日志记录上下文

class LogContextServiceObject extends ServiceObject {

    void execute(String operation, Map arguments, ...) {
        MDC.set("context", myCtx);
        super.execute(operation, arguments, ...);
        MDC.remove("context");
    }

}

但是,如果我想使用这两个功能,我需要编写另一个具有这两个功能的子类。您可以想象,如果有更多附加功能(日志记录、请求重写等),我将不得不为我需要的每种组合编写大量类。

相反,我想放弃子类并在创建 ServiceObject 时传递某种过滤器或组件对象。推荐的模式是什么(在 Java 中,或一般情况下)。

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.execute(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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情丝乱 2024-11-01 18:32:42

就 GoF 的著名书籍: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);
        }
    }
}

毕竟,您可以根据需要组合它们:

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

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()
                            )
                    );
沉默的熊 2024-11-01 18:32:42

最简单的解决方案是创建一个工厂类和枚举器:

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

用法:

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

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);
一影成城 2024-11-01 18:32:42

这听起来很像责任链模式。这通常被描述为传播请求直到某些处理程序可以承担责任,但它也用于传播请求直到某些处理程序“消耗”它。在您的情况下,您希望无条件传播到所有处理程序。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文