CDI:与经典装饰模式相比,@ Decorator在实际项目中是否有用

时间:2015-10-21 16:36:11

标签: java java-ee design-patterns cdi decorator

Env:
   Wildfly 9.0.1
   Weld 2.2.14

我目前正在研究在合理的遗留代码库中使用CDI @Decorator的可能性。

查看规范和java ee 7示例,CDI @Decorators似乎是

  • 在编译时定义。好吧,至少是他们的清单
  • 对象无法像运行时的​​Decorator那样在运行时进行修饰 图案

引用经典的Pizza和Toppings示例,可以在运行时创建任何深度的充值披萨。例如:新奶酪(新火腿(新辣椒(新的LargePizza())))

CDI @Decorator可以实现吗?如果没有,那么@Decorator的实际用途是什么,你必须在编译时声明对象,即使用@Decorator和@Delegate(以及beans.xml中的列表)?可能是我在这里遗漏了一些东西。

提前致谢,

勒凯什

2 个答案:

答案 0 :(得分:3)

你问过CDI给你的东西与经典的手写装饰图案相比。不多。只有:

  • 保证注入的bean已经自动“装饰”
  • 让您跳过覆盖装饰界面中的每个方法
顺便说一句,有些澄清,你说:

  

使用CDI(...)对象无法像运行时的​​Decorator模式一样在运行时进行修饰

错误,对象在运行时进行修饰。但是中装饰的是什么,在编译时被声明 如果你自己实现装饰模式(经典方法),那么你将获得提到的灵活性 - 但你真的需要这个吗?有时是,有时没有。

更新:CDI @Decorator确实无法阻止类爆炸问题。这是一个很大的缺点。

但我可以想象CDI @Decorator的有效用例 - 例如假设你想为EntityManager添加一些行为。在这种情况下,您不能继承,因为JPA实现在编译时是未知的。如果您想亲自实施装饰器,那么您将需要编写许多方法,请参阅:

public class CraftedEntityManager implements EntityManager {

    private final EntityManager delegator;

    public CraftedEntityManager(EntityManager em) {
        this.delegator = em;
    }

    @Override
    public void persist(Object entity) {
        delegator.persist(entity);
    }

    @Override
    public <T> T merge(T entity) {
        return delegator.merge(entity);
    }

    @Override
    public void remove(Object entity) {
        delegator.remove(entity);
    }

    // ...
    // here goes almost 50 other methods of the EntityManager

}

所以它似乎是一个很好的用例。

答案 1 :(得分:1)

装饰器和替代品是解决类似但不完全相同问题的两种方法。在替代方案中,您希望在不执行原始bean的任何行为的同时满足现有bean的签名。把它想象成嘲弄。

装饰者和拦截者可能更密切相关。装饰器旨在在调用原始bean的代码之前/之后执行某些操作。这类似于拦截器,除了拦截器期望应用于所有方法调用的相同拦截逻辑。装饰者没有那种期望。