【问题标题】:Hierarchy issue on Composite with JavaComposite with Java 的层次结构问题
【发布时间】:2016-02-08 09:15:52
【问题描述】:

我正在尝试在 Java 上使用复合模式来生成报告,但我显然忘记了层次结构和方法重载的工作原理。

假设我有以下模型:

public class Product {

    public String get(){
        return "Product";
    }

}

public class BProduct extends Product {

    public String getB() {
        return "BBBBB";
    }

}

public class CProduct extends Product {

    public String getC() {
        return "CCCCC";
    }

}

以及以下转换器:

import java.util.List;

public class Converter {

    private List<Converter> converters;

    public Converter() {

    }

    public Converter(List<Converter> converters) {
        this.converters = converters;
    }

    public void execute(Product product) {
        for (Converter converter : converters) {
            converter.execute(product);
        }
    }

}

public class BConverter extends Converter {

    @Override
    public void execute(Product product) {
        innerExecute(product);
    }

    public void innerExecute(Product product) {
        System.out.println(product.get() + " done on B normal.");
    }

    public void innerExecute(BProduct b) {
        System.out.println(b.getB() + " done on B special.");
    }

}

public class CConverter extends Converter {

    @Override
    public void execute(Product product) {
        System.out.println(product.get() + " done on C normal.");
    }

    public void execute(CProduct c) {
        System.out.println(c.getC() + " done on C special.");
    }

}

使用以下测试对其进行测试:

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class ProductConverterTest {

    @Test
    public void test() {
        List<Converter> converters = new ArrayList<>();
        converters.add(new BConverter());
        converters.add(new CConverter());
        Converter converter = new Converter(converters);

        List<Product> list = new ArrayList<>();
        list.add(new Product());
        list.add(new BProduct());
        list.add(new CProduct());

        for (Product product : list) {
            converter.execute(product);
        }
    }
}

获取输出:

Product done on B normal.
Product done on C normal.
Product done on B normal.
Product done on C normal.
Product done on B normal.
Product done on C normal.

当我想要的是:

Product done on B normal.
Product done on C normal.
BBBBB done on B special.
Product done on C normal.
Product done on B normal.
CCCCC done on C special.

注意:我想在不使用 instanceof 的情况下执行此操作。我已经知道如何使用它了。我想知道的是,如果没有它是否可以完成。

【问题讨论】:

    标签: java overloading composite class-hierarchy


    【解决方案1】:

    这种行为的原因是#execute 方法被重载。在编译时选择调用哪个重载方法。为了使其按您的意愿工作,您必须使用动态选择,这将导致instanceOf 检查或覆盖product 的方法或传递/检索类并进行比较:

    public class Converter {
    
        private List<Converter> converters;
    
        public Converter() {
    
        }
    
        public Converter(List<Converter> converters) {
            this.converters = converters;
        }
    
        public void execute(Product product) {
            for (Converter converter : converters) {
                converter.execute(product);
            }
        }
    
    }
    
    public class BConverter extends Converter {
    
        @Override
        public void execute(Product product) {
            if (product.getClass() == BProduct.class) {
                innerExecute((BProduct)product);
            } else {
                innerExecute(product);
            }
        }
    
        public void innerExecute(Product product) {
            System.out.println(product.get() + " done on B normal.");
        }
    
        public void innerExecute(BProduct b) {
            System.out.println(b.getB() + " done on B special.");
        }
    
    }
    
    public class CConverter extends Converter {
    
        @Override
        public void execute(Product product) {
            if (product.getClass() == CProduct.class) {
                innerExecute((CProduct)product);
            } else {
                innerExecute(product);
            }
        }
    
        public void innerExecute(Product product) {
            System.out.println(product.get() + " done on C normal.");
        }
    
        public void innerExecute(CProduct b) {
            System.out.println(b.getC() + " done on C special.");
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      子转换器中的执行方法总是调用上级类的内部执行方法。在您的示例中,从子类中删除 innerExecute(Product proeuct) 。

      您还可以尝试覆盖产品中的 toString()-Methode 而不是 get-method。然后使用接口作为执行方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        相关资源
        最近更新 更多