简体   繁体   English

Java - 动态创建接口的具体类型?

[英]Java - Dynamically creating concrete type of an Interface?

In my java class below I create a product and calculate the shipping as follows:在下面的 java 类中,我创建了一个产品并按如下方式计算运费:

public static void main(String[] args) {
    
    // create product 
    Product product = new Product();
    
    // calculate shipping
    ShippingCalculator usaShippingCalculator = new USAShippingCalculator();
    usaShippingCalculator.calculatePrice(product);

   // todo - how to replace above with dynamic logic around what calculator to use?
    
    }

Note that I have 2 different shipping calculators:请注意,我有 2 个不同的运费计算器:

USAShippingCalculator
RestofWorldShippingCalculator

Both implement the ShippingCalculator interface, shown below:两者都实现了ShippingCalculator接口,如下所示:

public interface ShippingCalculator {

    void calculatePrice(Product product);
}

Note that I have hardcoded above to use the USAShippingCalculator , however what I want to do is dynamically use the calculator that corresponds to the products country of origin - this will be a field in the Product object: String countryOfOrigin.请注意,我在上面进行了硬编码以使用USAShippingCalculator ,但是我想要做的是动态使用与产品原产国相对应的计算器 - 这将是产品对象中的一个字段: String countryOfOrigin.

How can I do so?我该怎么做?

You can create a enum Calculator type with two instances USA and REST_OF_THE_WORLD.您可以创建一个具有两个实例 USA 和 REST_OF_THE_WORLD 的枚举计算器类型。 You can then implement ShippingCalculator to your enum overriding the calculatePrice with the corresponding shipping calculator.然后,您可以为您的枚举实现 ShippingCalculator,使用相应的运费计算器覆盖 calculatePrice。

class Test {

    enum Origins {
        USA, REST_OF_THE_WORLD
    }
    public static void main(String[] args) {

        // Product country of origin.
        Product product = new Product(Origins.USA.toString());

        // Get the country of origin from Product.
        String countryOfOrigin = product.countryOfOrigin;

        // Iterate through each instance. Example. USA, REST_OF_THE_WORLD, etc.
        for(Calculator c : Calculator.values()) {

            // Find the calculator that corresponds to the product origin.
            if (c.name().equals(countryOfOrigin)) {

                // Calculate the price using the corresponding calculator.
                // In this case it would be USA.
                c.calculatePrice(product);

            }
        }
    }
}

enum Calculator implements ShippingCalculator {

    REST_OF_THE_WORLD {
        @Override
        public void calculatePrice(Product product) {
            RestofWorldShippingCalculator world = new RestofWorldShippingCalculator();
            world.calculatePrice(product);
            System.out.println("WORLD PRICE " + world.value);
        }
    },
    USA {
        @Override
        public void calculatePrice(Product product) {
            USAShippingCalculator usa = new USAShippingCalculator();
            usa.calculatePrice(product);
            System.out.println("USA PRICE " + usa.value);
        }
    }
}


interface ShippingCalculator {
    void calculatePrice(Product product);
}

class RestofWorldShippingCalculator  implements ShippingCalculator{

    double value;

    @Override
    public void calculatePrice(Product product) {
        value = product.i * 1.05;
    }
}

class USAShippingCalculator implements ShippingCalculator{

    double value;

    @Override
    public void calculatePrice(Product product) {
        value = product.i * 1.10;
    }
}

class Product {
    String countryOfOrigin;
    int i = 5;

    Product(String countryOfOrigin) {
        this.countryOfOrigin = countryOfOrigin;
    }
}

If you are unlikely to need these calculators anywhere else in your code, you could use anonymous inner classes.如果您不太可能在代码的其他任何地方需要这些计算器,则可以使用匿名内部类。

public static void main(String[] args) {
    
    // create product 
    Product product = new Product();
    
    ShippingCalculator shippingCalculator;
    // calculate shipping
    if(product.countryOfOrigin.equals("USA"))
       shippingCalculator = new ShippingCalculator(){
         void calculatePrice(Product product){
             //do usa calculation
         }
       }
    else
       shippingCalculator = new ShippingCalculator() {
         void calculatePrice(Product product){
             //do non-usa calculation
         }
       }
    
    shippingCalculator.calculatePrice(product);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM