【问题标题】:Decorator pattern - how to decorate two types at once装饰器模式 - 如何一次装饰两种类型
【发布时间】:2012-02-29 11:47:33
【问题描述】:

我在 Java 中工作

我为图边创建了一个很好的装饰器结构。我有两个顶点的基础边,然后我有一个加权装饰器,它为边添加权重,然后我有一个定向装饰器,为边添加方向。装饰器是使用接口和委托方法实现的(不是通过继承)。

现在我想添加另一个装饰器——一个流装饰器,对应一个流边。流边有方向和权重(容量),加上流。我如何在Java中实现这样的东西?我需要类似的东西

public class FlowEdge implements IEdge, IWeightedEdge, IOrientedEdge, IFlowEdge
{
    private IEdge, IWeightedEdge, IOrientedEdge decorated;
    private int flow;

    //constructors, delegate methods...

但这显然是不可能的。

也许装饰器不是最好的使用模式。我想实现关注点的分离(所以我可以有正常、加权、定向边缘的任意组合),但还需要一个类中可能有多个装饰器的功能。这有可能吗?还是我过度设计了这个?

【问题讨论】:

  • 为什么这“显然不可能”?你只能extend一个类,但你可以implement任意数量的接口。
  • 我的意思是线私有的IEdge,IWeightedEdge,IOOrientedEdge修饰;为了保留所有类型,我需要实现委托方法。

标签: java design-patterns decorator


【解决方案1】:

我放弃了整个装饰器的想法,并像普通继承一样实现了边缘。

Edge --> WeightedEdge --> OrientedEdge --> FlowEdge

它可能不如使用装饰那么优雅,我现在不能拥有未加权的边缘,但它简单明了。

【讨论】:

    【解决方案2】:

    声明装饰器实现的装饰类型似乎是错误的。装饰者确切地知道它在装饰什么似乎也是错误的。您可以实现一个“复合装饰器”,它依赖于其他装饰器类来添加特定行为,以及它本身提供的新行为。也许是这样的:

    public class FlowEdge implements IEdge // or IFlowEdge
    {
        private IEdge decorated;
        private int flow;
    
        public FlowEdge(IEdge decorated) {
            this.decorated = new WeightedEdge(new OrientedEdge(decorated));
            . . .
        }
    }
    

    【讨论】:

    • 一个有趣的想法,但是我必须有任意的权重和方向值,因为它们不能在构造函数中传递(除了检查类型然后转换为适当的类型)。
    • @JakubZaverka - 为什么不能在构造函数中传递相关属性?根据您的描述,FlowEdge 属性包括WeightedEdgeOrientedEdge 的所有属性。然后可以将这些传递给FlowEdge 构造函数中的相关构造函数。 (也许我误解了一些东西;我不明白你为什么需要在这里进行任何类型检查和强制转换。)
    • FlowEdge(WeightedEdge wedge, OrientedEdge oedge) 我在这条路上走了一段时间,但它看起来并不干净,你可以通过两个不同的实例。我必须检查if(wedge != oedge),然后抛出某种异常。那已经在运行时,我想在编译时检查它。
    【解决方案3】:

    您的设计听起来有缺陷。装饰器通常会“包装”他们想要装饰的类,并将其传递给它们的构造函数。您的代码应该使这样的事情成为可能:

    Graph myGraph = new BaseGraph();
    Graph decoratedGraph = new FlowedGraph(new WeightedGraph(new OrientedGraph(myGraph)));
    

    【讨论】:

    • 谢谢...是的,这就是我学到的装饰师。但是 FlowedGraph 必须同时具有方向和权重,在这种情况下我不能保证“decoree”将两者兼而有之。我只能让它加权或定向。
    【解决方案4】:

    装饰器是使用接口和委托方法实现的(不是 通过继承)。

    我认为这可能是您撞墙的原因。装饰器模式通过使用继承和多态在 Java 中很好地产生了自己。这是“用一种语言编程与用一种语言编程”的一个很好的例子。

    【讨论】:

    • 我如何用两个装饰器装饰一个类?我不能从 Java 中的两个类继承。
    • 这并不是装饰器在 Java 中的工作方式。你没有继承那么多......在运行时装饰。例如:new BufferedReader(new FileReader("readme.txt")).
    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 2011-12-28
    • 2022-08-15
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多