我发现了一个关于静态绑定的问题。
我的真实课堂非常扩展,所以我会用几个玩具课堂来表达我的问题。
我们假设我们有以下层次结构。
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
没有定义一个包含Element
作为参数的方法。在这种情况下,我们可以使用不同的方法修复代码。
首先,我将能够定义一种方法,将Element
定义为输入arg,例如
public void operation(Element e){
System.out.println("Operation - " + e.getClass().getName());
}
该方法可以定义用于管理不同具体元素(Element1
、Element2
)的开关。然而,这对我来说是不可能的,因为开关违反了打开/关闭原则,而且我有很多(很多)具体的元素。
另一种选择,我可以使用类似访问者模式的东西。我可以将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);
}
}
以及CCD_ 13。
public StockManager{
Stock stock;
public StockManager(Stock stock){
this.stock=stock;
}
public void manage(List<Element> elements){
for(Element element: elements){
element.stockOperation(stock);
}
}
}
它允许在编译时确定具体元素的静态类型。并且动态绑定将负责调用正确的具体元素(Element1
或Element2
)的stockOperation
方法。然而!!,我在具体元素中有重复的代码,我将有几个具体元素。
所以,我想知道我们是否知道解决这个问题的任何模式设计或最佳实践。(另一种选择,可能是使用反射,但我不想使用它)。
问题是将单个股票操作放置在股票对象中。无论你是否使用开关,只要你有了另一个Element类型,你就需要通过向它添加一个新的重载operation
来修改stock。正如你所说,你的stock类应该对修改关闭。
因此,您必须将股票操作降级到Element对象本身。这基本上是您的第二个建议,但您在每个不同的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对象进行通信。对传递给每个stockOperation
的stock执行此操作,使方法可用,允许元素获取或设置stock对象内部所需的任何内容,如操作的结果。
这样,如果你有一个新的Element类型,你只需要在新的Element中写新的操作,就可以保持同一个Stock类而不更改它。这是扩展而不是修改。