Home > Net >  Java - Dynamically creating concrete type of an Interface?
Java - Dynamically creating concrete type of an Interface?

Time:12-21

In my java class below I create a product and calculate the shipping as follows:

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:

USAShippingCalculator
RestofWorldShippingCalculator

Both implement the ShippingCalculator interface, shown below:

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.

How can I do so?

CodePudding user response:

You can create a enum Calculator type with two instances USA and REST_OF_THE_WORLD. You can then implement ShippingCalculator to your enum overriding the calculatePrice with the corresponding shipping calculator.

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

CodePudding user response:

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

}
  • Related