避免使用层次结构参数的操作中的静态绑定 [英] Avoid static binding in operations which use hierarchy arguments

查看:146
本文介绍了避免使用层次结构参数的操作中的静态绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的真实类非常扩展,所以我将使用几个玩具类来表达我的问题。

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

  
public class Element1 extends Element {}

public class Element2 extends Element {}

我有一个库存使用不同的元素 c code code $ c
$ b

  
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 可以管理库存

  public StockManager {

股票股票;
public StockManager(股票){
this.stock = stock;
}

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

当然,这段代码不编译,因为库存没有定义一个包含元素作为参数的方法。在这种情况下,我们可以使用不同的方法修复代码。



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

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

此方法可以定义一个用于管理不同具体元素的开关( Element1 Element2 )。不过,这对我来说是不可取的,因为这个开关违反了开放/关闭原则,以及我有很多(很多)具体的元素。



另一个选择,我可以使用像访客模式
我可以将库存对象发送到具体元素。具体要素将使用库存操作。所以,该类可以改为:

  public abstract class Element {
public abstract空白股票(股票);
}

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 {

股票股票;
public StockManager(股票){
this.stock = stock;
}

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

它允许在编译时确定,时间静态类型的混凝土元素。并且动态绑定将收取调用正确的具体元素( Element1 或<$ c $)的 stockOperation C>元素2 )。然而,我在具体的元素中有重复的代码,我将有几个具体的元素。



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

解决方案

您是否将股票操作放在股票对象中。无论是否使用开关,只要有另一种元素类型,您就需要通过向其添加新的重载操作来修改库存。正如你所说,你的股票类应该关闭修改。



所以你必须做任何股票操作对Element对象本身的放弃。这基本上是你的第二个建议,但是你可以在每个不同的元素中实现。

  public abstract class Element {
公共抽象空白股票操作(股票);
}

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

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

您可能需要与股票对象进行沟通真正的操作。通过传递给每个 stockOperation 的股票进行交易,从而使得方法可用于允许元素获取或设置股票对象所需的任何内容,如操作结果



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


I have found an issue about static binding.

My real class are very extended, so I will use several toy class to express my problem.

We suppose that we have the following hierarchy.

public class Element{}

public class Element1 extends Element{}

public class Element2 extends Element{}

I have a Stock class which use the different Element specialization defined by Element hierarchy.

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

Finally, I have a StockManager which allows to manage a 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);
        }
    }
}

Of course, this code does not compile, because Stock does not define a method which includes a Element as argument. In this case we could fix the code using different approaches.

First, I will be able to define a method which will define a Element as input arg, e.g.

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

This method could define a switch for managing the different concrete elements (Element1, Element2). However, this is imposible for me, because the switch violate the Open/Close Principle, and I have a lot (a lot) of concrete elements.

Another alternative, I could use something like the Visitor Pattern. I could send the Stock object to a concrete element. And the concrete element will be charge of using the Stock operations. So, the class could change to:

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

And the 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);
        }
    }
}

It allows determine in compile-time the static type of the concrete elements. And the dynamic binding will be charge of call the stockOperation method of the correct concrete element (Element1 or Element2). HOWEVER!!, I have duplicate code in the concrete elements, and I will have several concrete elements.

So, I would like know if we know any pattern design or any best practice for solve this issue. (Another alternative, it maybe to use reflection, but I would not like use it).

解决方案

The problem is that you place the individual stock operations in the stock object. No matter if you use a switch or not, as soon as you have another Element type, you'll need to modify stock by adding a new overloaded operation to it. And as you said, your Stock class should be closed to modifications.

So you have to do relegate whatever the stock operation is to the Element object itself. This is basically your second suggestion, but you do the implementation in each different 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");
    }
}

You will probably need to communicate with the stock object for the real operations. Do that with the stock that was passed to each stockOperation, making methods available that allow the elements to get or set whatever is needed inside the stock object, like the result of the operation.

This way, if you have a new Element type, you only need to write the new operation in the new Element, and you can keep the same Stock class without changing it. This is extension rather than modification.

这篇关于避免使用层次结构参数的操作中的静态绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆