Java 装饰一个混凝土课堂,糟糕的做法?

Java 装饰一个混凝土课堂,糟糕的做法?,java,decorator,Java,Decorator,装饰设计模式的典型uml图如下所示: 它们显示装饰者正在界面周围 问题是,它是一个接口还是一个具体类真的很重要吗 首先,装饰者不应该挑剔包装对象的行为,它只是一个功能层。所以我不认为这比使用接口更危险 通常我会(想)这样装饰: class-Foo{ 公共无效doSmth(){ } } 类LoggedFoo扩展了Foo{ 私人的福·拉佩德福; 公共LoggedFoo(Foo-Foo){wrappedFoo=Foo;} @凌驾 公共无效doSmth(){ System.out.println(“do

装饰设计模式的典型uml图如下所示:

它们显示装饰者正在界面周围

问题是,它是一个接口还是一个具体类真的很重要吗

首先,装饰者不应该挑剔包装对象的行为,它只是一个功能层。所以我不认为这比使用接口更危险

通常我会(想)这样装饰:

class-Foo{
公共无效doSmth(){
}
}
类LoggedFoo扩展了Foo{
私人的福·拉佩德福;
公共LoggedFoo(Foo-Foo){wrappedFoo=Foo;}
@凌驾
公共无效doSmth(){
System.out.println(“doSmth start”);
wrappedFoo.doSmth();
系统输出打印项次(“doSmth end”);
}
}
我认为我们不应该一眼就看到具体的类继承,因为“它很危险”。
那么,接口还是具体类,在这里有关系吗?

你应该使用接口,因为这是更好的实践。它们更易于测试和更改实现。如果您想在生产中使用不同类型的记录器(数据库、文件、控制台等),该怎么办?

您应该使用接口,因为这是更好的做法。它们更易于测试和更改实现。如果您想在生产环境中使用不同类型的记录器(数据库、文件、控制台等),该怎么办?

这很重要,因为
装饰器的整个思想是添加功能,而不必遵循实现继承路线。如果您同意实现继承并冒着更改对象现有行为的风险,那么根本不需要装饰器


整个想法是在不破坏实现继承所做的现有行为的情况下扩展功能

这很重要,因为
Decorators
的整个思想是添加功能,而无需遵循实现继承路线。如果您同意实现继承并冒着更改对象现有行为的风险,那么根本不需要装饰器


整个想法是在不破坏实现继承所做的现有行为的情况下扩展功能

扩展类可能会产生意外的副作用

如果Foo已经有了一个(或多个)构造函数,那么您也必须实现它们并调用超类

此外,如果Foo在构造函数中具有私有状态或副作用,那么这些副作用现在将执行两次。一次用于传入构造函数的Foo,一次用于LoggedFoo,它也是一个Foo


它可能会变得混乱,导致bug和资源消耗增加,但这完全取决于类。如果类的行为类似于接口(默认构造函数,没有副作用,没有状态),那么它可能不会直接成为问题。但在这一点上,它只是一个调用其他实例的子类,这可能是一个方便的构造,但我不会使用decorator模式调用它。

扩展类可能会产生意外的副作用

如果Foo已经有了一个(或多个)构造函数,那么您也必须实现它们并调用超类

此外,如果Foo在构造函数中具有私有状态或副作用,那么这些副作用现在将执行两次。一次用于传入构造函数的Foo,一次用于LoggedFoo,它也是一个Foo


它可能会变得混乱,导致bug和资源消耗增加,但这完全取决于类。如果类的行为类似于接口(默认构造函数,没有副作用,没有状态),那么它可能不会直接成为问题。但在这一点上,它将只是一个调用其他实例的子类,这可能是一个方便的构造,但我不会使用decorator模式调用它。

这永远都不重要——问题是,一如既往,实现接口通常更干净,避免被锁定到一个具体的类。接口允许一个类实现多个接口,但具体的类不会,装饰器只会扩展一个classIt“要紧”,因为这不是装饰器模式。Michael,你这么说是因为我忽略了“抽象装饰器”吗Foo和LoggedFoo之间的元素?这一点都不重要——问题是,与往常一样,实现接口通常更干净,避免被锁定到一个具体类。接口允许一个类实现多个接口,但具体类并不重要,装饰器只会扩展一个classIt“重要”从某种意义上说,这不是装饰器模式。Michael,你是说因为我省略了Foo和LoggedFoo之间的“抽象装饰器”元素吗?对于不同的伐木者,我会用相同的方式装饰,LoggedFoo的一个实例可以与另一个装饰器轻松装饰。对于不同的伐木者,我会用同样的方式来装饰,LoggedFoo的一个实例可以与另一个装饰者轻松地装饰。这是一个有趣的例子aspect@Sheed这个类现在包装了一个Foo,我们称之为foo1,它本身就是一个Foo:foo2。所以当你使用这个类时,至少有两个Foo存在。装饰接口没有这种效果。是的,我在意识到私有成员仍然存在并且可以在不调用构造函数的情况下初始化之后删除了我的注释。这是一个有趣的问题aspect@Sheed这个类现在包装了一个Foo,我们称之为foo1,它本身就是一个Foo:foo2。所以当你使用这个类时,至少有两个Foo存在。装饰接口没有这种效果。是的,我在意识到私有成员仍然存在并且可以在不调用构造函数的情况下进行初始化后删除了我的注释。类的契约是在继承层次结构的最高级别编写的,无论顶层是