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