在使用层次结构参数的操作中避免静态绑定

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

我真正的课程非常扩展,所以我会用几个玩具类来表达我的问题。

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

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()); } } 

最后,我有一个允许管理StockStockManager

 public StockManager{ Stock stock; public StockManager(Stock stock){ this.stock=stock; } public void manage(List elements){ for(Element element: elements){ stock.operation(element); } } } 

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

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

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

该方法可以定义用于管理不同具体元素( Element1Element2 )的开关。 然而,这对我来说是不可能的,因为开关违反了开/关原则 ,而且我有很多(很多)具体元素。

另一种选择,我可以使用像访客模式这样的东西。 我可以将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 elements){ for(Element element: elements){ element.stockOperation(stock); } } } 

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

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

问题是您将单个库存操作放在库存对象中。 无论您是否使用开关,只要您有另一个元素类型,您就需要通过向其添加新的重载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"); } } 

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

这样,如果您有一个新的Element类型,您只需要在新元素中编写新操作,并且您可以保留相同的Stock类而不更改它。 这是扩展而不是修改。