5

我一直在使用委托模式将工厂创建的对象包装在 3rd 方库中。最近,该库在基类中添加了一个受保护的方法,我的包装类不再起作用。有没有人在不诉诸反思的情况下有一个好的解决方案?

这是在 3rd 方库和他们的包中,

public class Base {
    public void foo();

    protected void bar(); // Newly added
}

这是在我自己的包裹里,

public class MyWrapper extends Base {
    private Base delegate;

    public MyWrapper(Base delegate) {
        this.delegate = delegate;
    }

    public void foo() {
        delegate.foo()
    }

    protected void bar() {
        // Don't know what to do
    }
}

编辑:我原来的帖子不清楚。这两个类在不同的包中。

回答为什么我需要授权的问题。这是委托/包装模式的一个典型用例,我不能在这里用几行代码来展示它。该库公开了 Base 类,但其工厂的实际对象是 Base 的派生类。实际的类会根据配置而变化。所以我不知道代表是什么。因此直接继承模式在这里不起作用。

4

5 回答 5

4
Access Levels
Modifier    Class   Package Subclass    World
public      Y          Y        Y         Y
protected   Y          Y        Y         N
no modifier Y          Y        N         N
private     Y          N        N         N

protectedpackage可以访问,您是否看到任何具体问题:

class Base {
        public void foo(){};

        protected void bar(){}; // Newly added
    }

    class MyWrapper  {
        private Base delegate;

        public MyWrapper(Base delegate) {
            this.delegate = delegate;
        }

        public void foo() {
            delegate.foo();
        }

        protected void bar() {
            // Don't know what to do
            delegate.bar(); //since its in same package, it can be referenced, do you expect compile time error?
        }
    }

此外,在使用委托模式为什么包装类扩展Base类时,我没有看到具体的需求,因为您已经有一个Base. 对我来说,它似乎更像是一个装饰者。

于 2013-04-26T11:49:20.150 回答
1

您不需要(或不应该?)委托该 bar 方法。

如果库定义了受保护的方法。它不希望用户(当然在不同的包中)调用该方法,除非创建该类型的子类。你试图打破规则。

如果你想这样做,有办法,你创建一个子类型Base,比如说SubBase,你创建对象SubBase而不是Base,然后传递subBase给你的包装器。那么你可以在你的包装器bar()方法中delegate.bar()这样写,SubBase实际上是委托,或者说你的包装器不是SubBase委托Base

我想你知道我的意思,所以我只是不输入示例代码,我想只有这一行就足够了:

//Wrapper

 private SubBase delegate;

您会看到包装器不再需要,如果您有SubBase. 您甚至可以public void pubBar()在您的, 中定义 a SubBase,然后调用this.bar(). 这样,SubBase 的所有对象都可以访问受保护的方法 ( via pubBar()),无论来自哪个包

于 2013-04-26T12:07:08.213 回答
1

我的印象是这个Base类要么是一个接口,要么是一个抽象类。如果是这样,您必须实现该bar()方法,例如使用下面列出的三种方法中的任何一种。

旁注,如果Base是普通类,则您无需执行任何操作(对 的实例的MyWrapper.bar()调用实际上会导致对Base.bar().


委托给父对象

bar()如果该方法用作第 3 方 API 中的回调,这通常是一个好主意:

@Override
protected void bar() {
    delegate.bar();
}

没做什么

只是添加了一个空方法以避免编译错误:

@Override
protected void bar() {
    // silently ignored
}

抛出异常

暴力阻止对新方法的任何使用:

@Override
protected void bar() {
    throw new UnsupportedOperationException("not implemented");
}

作为旁注,更健壮的结构是更喜欢组合而不是继承,以将您的实现与第 3 方实现分离,例如

public class MyWrapper {    // does not extend Base
    private Base delegate;

    public MyWrapper(Base delegate) {
        this.delegate = delegate;
    }

    public void foo() {
        delegate.foo()
    }

    // does not have to implement bar()
}
于 2013-04-26T13:33:23.980 回答
0

如果您不需要委托人成为基类的实际实例,则可以简单地删除该关系:

public class MyWrapper {
    private Base delegate;

    public MyWrapper(Base delegate) {
        this.delegate = delegate;
    }

    public void foo() {
        delegate.foo()
    }

}

这是否适合您在很大程度上取决于您的其他代码,而且您的需求现在对我来说并不完全清楚。

如果库定义了提供由抽象基类实现的公共方法的接口,您可以明智地实现该接口,而无需从抽象基类继承,这也可能满足您的需求。

于 2013-04-27T14:07:33.627 回答
0

我正在使用 Spring 在 Wrapper 中注入来自另一个模块的“基本委托”并获取委托,我正在使用 pojo 工厂。

<bean id="interfaceDelegate" factory-bean="DelegatePojoFactory"
    factory-method="getMyDelegateInstance">
    <constructor-arg index="0">
        <value>OnLine</value>
    </constructor-arg>
</bean>

<bean id="wrapper" class="path.Wrapper">
      <property name="delegate" ref="interfaceDelegate"></property>
</bean>
于 2013-04-26T13:43:48.580 回答