我正在阅读Gof的装饰设计模式。我对以下几点感到困惑
它说模式的重要方面是让装饰者 出现在使用组件的任何地方。客户不能 通常说明装饰组件之间的区别 未装饰的组件?例如,如果我认为,我是一个客户,和 基本组件与电子邮件有关,但我也希望它安全。 有人向我提供功能。
Email email = new SecuredEmail(new TextEmail());
问:这只是非常假设的。作为客户,我不会知道
那,这封文字邮件是装饰的吗?我只是困惑,可以有人
澄清这个疑问? 装饰器及其组件不相同。装饰师充当 透明的外壳。但从对象身份的角度来看, 装饰组件与组件本身不同。 因此,在使用装饰器时,不应该依赖对象标识。 这是什么意思?
有人可以解释这两部分。
本
答案 0 :(得分:2)
假设Email
是Java接口。任何实现Email
的类都可用于初始化变量email
,包括任何装饰器,因为装饰器实现接口或扩展抽象类(实现接口)。当然,客户端可以知道什么是类实例,但他们通常不需要这样做。只需使用email.getClass()
。
另一方面,装饰器与装饰物不是同一个物体。它包裹装饰物体。因此TextEmail
和SecuredEmail
不是同一个对象。如果代码如下:
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方法。因此,在使用装饰器模式时,您永远不应该信任或依赖于相等。