vendredi 21 septembre 2018

Electricity Billing System for Home in OOPS

I recently appeared for interview for code-pairing round and I was asked following question: Electricity Billing System for home“. The corresponding power usage of home appliances(Fan, AC, Fridge, Light) was given:

Appliance | Per hour unit consumption
Fan 4
Light 2
AC 10
Fridge 8

The slab chart was given as:

Slab 1 - 0 to 1000 unit: INR Rs 20 per unit
Slab 2 - 1001 to 3000 unit: INR Rs 30 per unit
Slab 1 - 3001 to 6000 unit: INR Rs 40 per unit
Slab 1 - 6001 and above unit: INR Rs 50 per unit

Input:

Appliance | CountOfAppliance | TotalUasgePerDayInHours
Fan 2 4
Light 1 4
AC 1 12
Fridge 1 5

Output:

200000 INR
Units Per Day : (2*4*4 + 1*4*2 +1*12*10 + 1*5*8) = 200
unitsPerMonth = 6000
totalBill = 1000*20 + 2000*30 + 3000*30 + 3000*50 = 200000

I had modeled the code using "Factory Design Pattern" for appliance. But my Code for Price Slab was something the interviewer was not happy with the hardcoding. Though I modified it by using Constants file for slabs but the interviewer was still expecting something better. Kindly let me know how it can be improved.

My Code:

IElectricComponent

public interface IElectricComponent {
    public enum Unit{
           FAN(4), LIGHT(2), AC(10) , FRIDGE(8);
           private int value;
           private Unit(int value) {
                this.value = value;
           }
           public int getValue(){
            return value;
           }
       }
    public int claculateUnitForSingleDay();
}

Fan

public class Fan implements IElectricComponent{

    private int noOfComponents;
    private int perDayUsage;
    public Fan(int noOfComponents, int perDayUsage){
        this.noOfComponents=noOfComponents;
        this.perDayUsage=perDayUsage;               
    }

    public int claculateUnitForSingleDay(){
        return noOfComponents*perDayUsage*Unit.FAN.getValue();      
    }   
}

The same way for Fridge,Light and Ac

Factory : ApplianceFactory

public class ApplianceFactory {

        public static IElectricComponent getInstance(String appliance, int countOfAppliance ,int perDayUsage ){

            switch(appliance){

                case ApplianceConstants.FAN:
                    return new Fan(countOfAppliance,perDayUsage);

                case ApplianceConstants.LIGHT:
                    return new Light(countOfAppliance,perDayUsage);

                case ApplianceConstants.AC:
                    return new AC(countOfAppliance,perDayUsage);

                case ApplianceConstants.FRIDGE:
                    return new Fridge(countOfAppliance,perDayUsage) ;

                default :
                    return new IElectricComponent() {

                        @Override
                        public int claculateUnitForSingleDay() {
                            // TODO Auto-generated method stub
                            return countOfAppliance*perDayUsage;
                        }
                    };
            }

        }
    }

Constants:

public interface ApplianceConstants {

    public String FAN = "Fan";
    public String LIGHT = "Light";
    public String AC = "AC";
    public String FRIDGE = "Fridge";

    public int Slab1 = 20;
    public int Slab2 = 30;
    public int Slab3 = 40;
    public int Slab4 = 50;
}

PriceSlab:

public class PriceSlab {

    HashMap<String,Integer> slabs = new HashMap<>();

    public int calculateBill(int units){

        slabs.put("A", ApplianceConstants.Slab1);
        slabs.put("B", ApplianceConstants.Slab2);
        slabs.put("C", ApplianceConstants.Slab3);
        slabs.put("D", ApplianceConstants.Slab4);

        return calculateBillTotal(units);
    }

    private int calculateBillTotal(int units) {

        int total = 0;
        if(units <= 1000){
            total = units*slabs.get("A") ;
        }
        else if (units <= 3000){
            total = 1000*slabs.get("A") + (units-1000)*slabs.get("B");
        }
        else if (units <= 6000){
            total = 1000*slabs.get("A") + 2000*slabs.get("B") +(units-3000)*slabs.get("C");
        }
        else{
            total = 1000*slabs.get("A") + 2000*slabs.get("B") + 3000*slabs.get("D")
                +(units-6000)*slabs.get("C");
        }
        return total;
    }
}

Main class:

public class BillGenerator {

    public static void main(String[] args) {

        Scanner scn = new Scanner(System.in);
        ApplianceFactory factory = new ApplianceFactory();
        int inputOfAppliance = scn.nextInt();
        String appliance="";
        int countOfAppliance;
        int perDayUsage;
        int unitsPerDay=0;
        for(int t=0 ; t<inputOfAppliance ;t ++){
            appliance = scn.next();
            countOfAppliance = scn.nextInt();
            perDayUsage = scn.nextInt();
            IElectricComponent electricComponent = factory.getInstance(appliance, countOfAppliance, perDayUsage);
            unitsPerDay += electricComponent.claculateUnitForSingleDay();
        }
        System.out.println("unitsPerDay = "+unitsPerDay);
        int unitsPerMonth = unitsPerDay * 30;
        System.out.println("unitsPerMonth = "+unitsPerMonth);

        PriceSlab slab= new PriceSlab();
        int totalBill = slab.calculateBill(unitsPerMonth);
        System.out.println("totalBill = "+totalBill);
    }

}

I thought a lot about how to remove hardcoding from price-slab function but couldn't think of anything better. Please let me know how it can be improved or if any other design pattern could be used for it.

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire