java - 如何使用 protected 方法为 Java 类实现装饰器模式

标签 java design-patterns

包外的子类不能访问父类实例上的 protected 成员(只能访问子类本身或其子类的实例)。 JLS链接:http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2

这是一个例子。现有类如下所示:

package package1;
public abstract class BaseImplementation {

    public String getResource1() {
        return processTemplate1(getBaseUrl());
    }

    public String getResource2() {
        return processTemplate2(getBaseUrl());
    }

    // Kind of 'Template Method' pattern.
    protected abstract String getBaseUrl();
}

所以打算像下面这样编写装饰器:

package package2;
public class ImplementationDecorator extends BaseImplementation {
    private BaseImplementation delegate;

    public ImplementationDecorator(BaseImplementation delegate) {
        this.delegate = delegate;
    }

    @Override
    protected String getBaseUrl() {
        return trackServer + "?redirect=" + delegate.getBaseUrl();
    }
}

代码不会编译。 getBaseUrl() 在基类中具有 protected 访问权限,即使是子类也无法在父实例上访问它。

所以问题是如何使用 protected 方法装饰此类实例,而不使用“肮脏”的技巧,例如反射或将子类放入与父类同名的包中。

在 Java 语言本身中也有相同的示例(例如 javax.security.auth.login.ConfigurationSpi),在我发现的 Java 案例中 - 从同一个包访问是用过。

最佳答案

您在这里尝试做的是拦截行为,这种行为在类型 BaseImplementation 与其派生类型之一之间的关系中或多或少是私有(private)的——在这里,您的“delegate"实例,你想在你的 ImplementationDecorator 类中装饰。 BaseImplementation 的作者从未预料到有人想插到中间,并且从 BaseImplementation 派生的类型的作者也没有预料到除 之外的任何调用者BaseImplementation 本身会进入那里。

相反,您正在寻找的模式看起来更像这样,如果您不拥有所涉及的类,恐怕您无法对其进行改造:

public interface URLProvider
{
  String getBase();
}


public final class BaseImplementation
{
  public BaseImplementation(URLProvider provider)
  {
    if (null == provider)
      throw new NullPointerException();
    this.provider = provider;
  }


  public String getResource1()
  {
    return processTemplate1(provider.getBase());
  }


  public String getResource2()
  {
    return processTemplate2(provider.getBase());
  }


  private final URLProvider provider;
}

有了它,如果有人编写了 URLProvider 类型的实现,装饰起来就很容易了,因为现在方法 URLProvider#getBase() 是公开的。

现在,您可能会说,嗯,这不就是将您的 BaseImplementation#getBaseUrl() 方法更改为公共(public)方法而不是 protected 方法吗?不完全的。在这里,设计承认——甚至警告——URLProvider 实例是一种可以在任何地方使用的功能。

关于java - 如何使用 protected 方法为 Java 类实现装饰器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6863117/

相关文章:

java - 用Grails 3处理 token

java - 我可以让 jar 执行 python 脚本吗?

java - 这段代码是某种命令模式吗?

C#生产者/消费者

java - Spring - 使用@Configurable 和@Value 注释用新运算符创建对象

java - 在单个模型 Hibernate Spring 中将两个表连接到第三个表

Java - 如何创建 Class<Map<Object,List<Object>>> 对象

design-patterns - 设计模式 - 服务层

Java、FTP 和多个消费者

objective-c - 两个对象可以是彼此的代表吗......?