装饰混凝土class,不好的做法?
Decorating a concrete class, bad practice?
装饰器设计模式的典型 uml 图如下:https://www.dofactory.com/net/decorator-design-pattern
它们显示装饰器围绕着一个界面。
问题是,它是界面还是具体class真的重要吗?
首先,装饰器不应该挑剔包装对象的行为,它只是一层功能。所以我看不出这比使用界面有什么风险。
通常我会(喜欢)这样装饰:
class Foo{
public void doSmth(){
}
}
class LoggedFoo extends Foo{
private Foo wrappedFoo;
public LoggedFoo(Foo foo){wrappedFoo = foo;}
@override
public void doSmth(){
System.out.println("doSmth start");
wrappedFoo.doSmth();
System.out.println("doSmth end");
}
}
我认为我们不应该只看到具体的 class 继承,因为 "it's dangerous"。
所以,界面还是具体 class,这里 重要吗?
您应该使用接口,因为这是更好的做法。它们更容易测试和更改实现。如果您想在生产中使用不同类型的记录器(数据库、文件、控制台等)怎么办?
这很重要,因为 Decorators
的整个想法是在不采用实现继承路线的情况下添加功能。如果您接受实现继承并冒着改变对象现有行为的风险,那么根本不需要装饰器。
整个想法是在不破坏实现继承所做的现有行为的情况下扩展功能。
扩展 class 可能会产生意想不到的副作用。
如果 Foo 已经有一个(或多个)构造函数,您也必须实现它们并调用超级 class。
此外,如果 Foo 在构造函数中有私有状态或副作用,现在会执行 两次 。一次用于在构造函数中传递的 Foo,一次用于 LoggedFoo,它也是一个 Foo。
它可能会变得混乱并导致错误和资源消耗增加,但这完全取决于 class。如果 class 表现得像一个接口(默认构造函数,无副作用,无状态),它可能不会直接成为问题。但在这一点上,它只是一个 subclass 调用另一个实例,这可能是一个方便的构造,但我不会使用装饰器模式调用它。
装饰器设计模式的典型 uml 图如下:https://www.dofactory.com/net/decorator-design-pattern
它们显示装饰器围绕着一个界面。
问题是,它是界面还是具体class真的重要吗?
首先,装饰器不应该挑剔包装对象的行为,它只是一层功能。所以我看不出这比使用界面有什么风险。
通常我会(喜欢)这样装饰:
class Foo{
public void doSmth(){
}
}
class LoggedFoo extends Foo{
private Foo wrappedFoo;
public LoggedFoo(Foo foo){wrappedFoo = foo;}
@override
public void doSmth(){
System.out.println("doSmth start");
wrappedFoo.doSmth();
System.out.println("doSmth end");
}
}
我认为我们不应该只看到具体的 class 继承,因为 "it's dangerous"。 所以,界面还是具体 class,这里 重要吗?
您应该使用接口,因为这是更好的做法。它们更容易测试和更改实现。如果您想在生产中使用不同类型的记录器(数据库、文件、控制台等)怎么办?
这很重要,因为 Decorators
的整个想法是在不采用实现继承路线的情况下添加功能。如果您接受实现继承并冒着改变对象现有行为的风险,那么根本不需要装饰器。
整个想法是在不破坏实现继承所做的现有行为的情况下扩展功能。
扩展 class 可能会产生意想不到的副作用。
如果 Foo 已经有一个(或多个)构造函数,您也必须实现它们并调用超级 class。
此外,如果 Foo 在构造函数中有私有状态或副作用,现在会执行 两次 。一次用于在构造函数中传递的 Foo,一次用于 LoggedFoo,它也是一个 Foo。
它可能会变得混乱并导致错误和资源消耗增加,但这完全取决于 class。如果 class 表现得像一个接口(默认构造函数,无副作用,无状态),它可能不会直接成为问题。但在这一点上,它只是一个 subclass 调用另一个实例,这可能是一个方便的构造,但我不会使用装饰器模式调用它。