1

我发现了一个关于静态绑定的问题。

我的真实课非常丰富,所以我会用几个玩具课来表达我的问题。

我们假设我们有以下层次结构。

public class Element{}

public class Element1 extends Element{}

public class Element2 extends Element{}

我有一个使用层次结构定义Stock的不同Element专业化的类。Element

public class Stock{

    public void operation(Element1 e1){
        System.out.println("Operation - " + e1.getClass().getName());
    }

    public void operation(Element2 e2){
        System.out.println("Operation - " + e2.getClass().getName());
    }
}

最后,我有一个StockManager允许管理Stock.

public StockManager{

    Stock stock;
    public StockManager(Stock stock){
        this.stock=stock;
    }

    public void manage(List<Element> elements){
        for(Element element: elements){
            stock.operation(element);
        }
    }
}

当然,这段代码不会编译,因为Stock没有定义包含Elementas 参数的方法。在这种情况下,我们可以使用不同的方法修复代码。

首先,我将能够定义一个将 a 定义Element为输入 arg 的方法,例如

public void operation(Element e){
    System.out.println("Operation - " + e.getClass().getName());
}

这个方法可以定义一个开关来管理不同的具体元素(Element1, Element2)。但是,这对我来说是不可能的,因为开关违反了打开/关闭原则,而且我有很多(很多)具体元素。

另一种选择,我可以使用类似Visitor Pattern的东西。我可以将Stock对象发送到具体元素。具体元素将负责使用Stock操作。因此,该类可以更改为:

public abstract class Element{
    public abstract void stockOperation(Stock stock);
}

public class Element1 extends Element{
    public abstract void stockOperation(Stock stock){
        stock.operation(this);
    }
}

public class Element2 extends Element{
    public abstract void stockOperation(Stock stock){
        stock.operation(this);
    }
}

StockManager.

public StockManager{

    Stock stock;
    public StockManager(Stock stock){
        this.stock=stock;
    }

    public void manage(List<Element> elements){
        for(Element element: elements){
            element.stockOperation(stock);
        }
    }
}

它允许在编译时确定具体元素的静态类型。并且动态绑定将负责调用stockOperation正确的具体元素(Element1Element2)的方法。但是!!,我在具体元素中有重复的代码,我将有几个具体的元素。

所以,我想知道我们是否知道任何模式设计或解决这个问题的最佳实践。(另一种选择,它可能使用反射,但我不想使用它)。

4

1 回答 1

2

问题是您将单个库存操作放在库存对象中。无论您是否使用开关,只要您有另一种元素类型,您就需要通过添加新的重载operation来修改库存。正如您所说,您的 Stock 类应该禁止修改。

因此,您必须将库存操作的任何内容委托给 Element 对象本身。这基本上是您的第二个建议,但您在每个不同的元素中执行实现。

public abstract class Element{
    public abstract void stockOperation(Stock stock);
}

public class Element1 extends Element{
    @Override
    public void stockOperation(Stock stock){
        System.out.println("Operation - Element1");
    }
}

public class Element2 extends Element{
    @Override
    public void stockOperation(Stock stock){
        System.out.println("Operation - Element2");
    }
}

您可能需要与 stock 对象进行通信以进行实际操作。使用传递给 each 的 stock 执行此操作stockOperation,使方法可用,允许元素获取或设置 stock 对象中所需的任何内容,例如操作的结果。

这样,如果你有一个新的Element类型,你只需要在新的Element中编写新的操作,就可以保持相同的Stock类而不改变它。这是扩展而不是修改。

于 2014-10-24T18:01:22.487 回答