装饰模式中的困惑

时间:2014-02-10 10:20:00

标签: java design-patterns

我正在阅读Gof的装饰设计模式。我对以下几点感到困惑

  1. 它说模式的重要方面是让装饰者     出现在使用组件的任何地方。客户不能     通常说明装饰组件之间的区别     未装饰的组件?例如,如果我认为,我是一个客户,和     基本组件与电子邮件有关,但我也希望它安全。     有人向我提供功能。

     Email email = new SecuredEmail(new TextEmail());
    
    问:这只是非常假设的。作为客户,我不会知道 那,这封文字邮件是装饰的吗?我只是困惑,可以有人 澄清这个疑问?

  2. 装饰器及其组件不相同。装饰师充当 透明的外壳。但从对象身份的角度来看, 装饰组件与组件本身不同。 因此,在使用装饰器时,不应该依赖对象标识。 这是什么意思?

  3. 有人可以解释这两部分。

3 个答案:

答案 0 :(得分:2)

假设Email是Java接口。任何实现Email的类都可用于初始化变量email,包括任何装饰器,因为装饰器实现接口或扩展抽象类(实现接口)。当然,客户端可以知道什么是类实例,但他们通常不需要这样做。只需使用email.getClass()

另一方面,装饰器与装饰物不是同一个物体。它包裹装饰物体。因此TextEmailSecuredEmail不是同一个对象。如果代码如下:

TextEmail txtEmail = new TextEmail();
SecuredEmail securedEmail = new SecuredEmail(txtEmail);

然后检查他们的身份会得到下一个结果:

System.out.println("identical: " + (txtEmail == securedEmail));

identical: false

equals(Object)可以写成,因此它可以给出不同的结果,例如

System.out.println("equal: " + txtEmail.equals(securedEmail));

输出:

equal: true

答案 1 :(得分:1)

你不是客户。使用电子邮件的代码是客户端,它只知道对象是电子邮件。它不会知道它是用SecuredEmail装饰的TextEmail。

至于依赖于对象标识,这意味着无论是传递TextEmail还是包含在SecuredEmail中的TextEmail,一段代码都应该相同。从技术意义上讲,您不应该依赖email1 == email2,因为email2可能是使用SecureEmail修饰的email1。

答案 2 :(得分:1)

Ad.1作为客户端,装饰类的用户无法确定您使用的实现。

我们需要假设Email是一个接口,以免创建两个方法。

方法1

 public Email getMail() {
   reutrn TextEmai();
 }

方法2

 public Email getMail() {
   reutrn SecureEmail();
 }

作为API的用户,您将知道存在具有方法Email getMail()的类,您无法通过它描述将要解析的类。它可能是方法1或方法2.但作为一种使用,你不能确定。

第二点,指对象平等。对于此示例,TextEmail对象不等于SecureEmail。正如鲍里斯在他的回答和评论中所解释的那样。装饰者可以但不必以相同的方式实现equals方法。因此,在使用装饰器模式时,您永远不应该信任或依赖于相等。