设计模式将不同的操作委托给不同的类

时间:2014-07-24 08:33:18

标签: java design-patterns

我有一个ABC类可以执行操作a(),b()和c()(operation == method),它们都是密切相关的。我也有类似DE和FGH的simimar类。将来,可能会添加新类以及其他操作。类永远不会共享操作(例如,没有类ADF)

我的程序应该能够执行所有这些操作,时间是"有点随机",这意味着我事先没有估计将执行哪些操作/多少次。

我通过创建一个包装类" OperationInvoker"来解决这个问题。我的程序只能访问这个调用程序,并且每个操作都有一个方法。这样做的好处是封装:如果创建了新操作或现有操作或编辑了新操作,则需要编辑包装类。

我的问题是,"巨大"包装器是解决这个问题的最佳模式吗?

我调查了观察者的模式我认为这不是一个合适的案例,因为ABC,DE,FGH这两个课程从来没有任何共同利益。例如,如果需要执行操作A,则所有已注册的类将接收事件A,并且只有1个类(即ABC)实际上对此事件感兴趣。所有其他注册课程将丢弃该活动。这似乎是所有注册和观察的过度/开销。

委托模式也遇到了同样的问题:我没有多个类以不同的方式执行相同的操作,因此没有必要使用灵活的委派系统。

是否有其他更好的模式,或者这只是一个委托包装类的简单案例?

编辑:有人问ABC究竟是做什么的。好吧,我有一个描述SOAP Web服务的WSDL文件。我使用工具将此文件转换为java类。这意味着我无法控制这些类的内容,因为它们是自动生成的。所以我编写了一个WebServiceInvoker类,它充当了这些Web服务的包装器。这个包装类有3个方法:做Web服务A,做Web服务B,做Web服务C.

随着程序的扩展,越来越多的wsdl文件进入图片。当然,没有一个Web服务做同样的事情。它们并非全部捆绑在一个大型wsdl文件中的唯一原因是因为某些Web服务在逻辑上并不属于其他Web服务。所以我结束了以下课程:

  • 一个可以调用Web服务A,B和C
  • 的包装类
  • 一个可以调用Web服务D,E
  • 的包装类
  • 一个可以调用webservice F,G和H
  • 的包装类

将来可能会出现更多wsdl(以及包装类)。之所以在所有其他包装器周围有一个额外的包装器,是因为需要使用"会话ID"来调用每个服务。所以每个包装器都需要知道这些信息。因此,超级包装程序保存此信息,并可以调用所有Web服务。这也非常适合作为api:使用Web服务的程序对服务一无所知,它只通过超级包装器为每个Web服务提供了一种公共方法。该程序当然知道每个Web服务返回的内容(列表,字符串,没有...)。

2 个答案:

答案 0 :(得分:1)

为了便于代码维护,我建议将包装器更改为:

public class Operations {
    private ABC abcInst;
    private DE deInst;
    private FGH fghInst;

    protected Operations(ABC abc, DE de, FGH fgh) {
        this.abcInst = abc;
        this.deInst = de;
        this.fghInst = fgh;
    }

    public ABC getABC() { return abcInst; }
    public DE getDE() { return deInst; }
    public FGH getFGH() { return fghInst; }
}

这种方式不需要麻烦(除非添加了新课程),来自来电者的所有来电只需要额外的.getABC().a()代替.a()等。这强调了这一事实:操作由不同的类执行,但仍允许通过传递Operations - 实例来访问所有功能。

答案 1 :(得分:1)

看起来你有一个明确的架构,你试图不泄漏到其他组件。避免这种泄漏的自然方法是增加一个分离度。

基本上,如果你愿意,你仍然可以保留一个巨大的包装器,但是你需要考虑你想要暴露的东西并且只暴露它。看起来您想要公开的是已知操作的列表,所以如下所示:

// Your setup - trimmed down.
interface ABC {

    public void a();

    public void b();

    public void c();
}

interface DE {

    public void d();

    public void e();
}

interface FGH {

    public void f();

    public void g();

    public void h();
}

// Your current wrapper.
class AllOps {

    public ABC getABC() {
        return null;
    }

    public DE getDE() {
        return null;
    }

    public FGH getFGH() {
        return null;
    }
}

// One further degree of separation.
enum Op {

    A {

                @Override
                void op() {
                    ops.getABC().a();
                }

            },
    B {

                @Override
                void op() {
                    ops.getABC().b();
                }

            },
    C {

                @Override
                void op() {
                    ops.getABC().c();
                }

            },
    D {

                @Override
                void op() {
                    ops.getDE().d();
                }

            },
    E {

                @Override
                void op() {
                    ops.getDE().e();
                }

            },
    F {

                @Override
                void op() {
                    ops.getFGH().f();
                }

            },
    G {

                @Override
                void op() {
                    ops.getFGH().g();
                }

            },
    H {

                @Override
                void op() {
                    ops.getFGH().h();
                }

            };
    // Hide the huge wrapper.
    private static AllOps ops = new AllOps();
    // Only expose the operations.
    abstract void op();
}

public void test() {
    Op.A.op();
    Op.F.op();
}

不确定这是什么模式,但如果你只公开枚举,我认为你已经实现了断开连接。

可以添加其他操作作为以您喜欢的任何方式实现op的新枚举。他们甚至可能不会使用巨大的包装。