vendredi 30 décembre 2016

How to prevent inheritance from breaking all dependencies in OOP manner without instanceof or typecasting?

We are billing all seats in an airplane. Initially we had a discount per seat. Assume we had a class Discount, and a seat-billing and audit code depended on it.

class Discount {

    private int discountId; // unique key stored in database

    public int getDiscountId() {
        return discountId;
    }

    public List<Seat> getListOfSeatsWithDiscount() {

    }

    public int getDiscountPercentPerSeat() { return 10; }

}

class SeatBill {
    public void billPerSeat() {
        for (each seat object) {
            // fetch discountObject from database.
            Discount d;
            // get list of seats with discounts, and for each of such seats
            seatObject.totalCost = seatObject.totalCost * (100 - d.getDiscountPercentPerSeat())/100;
        }
    }
}

Then we have an audit class which cares about discounted seats.

class Audit {

    public void audit(Discount id) {
        // fetch discount object from database given discount id.
        for (seat in d.getListOfSeatsWithDiscount()) {
            // log all the seats.
        }
    }
}

Now airplane management decides to add another discount -> monthly discount for holiday season. Thus we created an abstract class Discount and created DiscountPerSeat and DiscountPerMonth.

abstract class Discount {
    private int discountId; // unique key stored in database

    public int getDiscountId() {
        return discountId;
    }
}

class DiscountPerSeat extends Discount {


    public List<Seat> getListOfSeatsWithDiscount() {

    }

    // returns 10% discount on each seat reserved.
    public int getDiscountPercentPerSeat() { return 10; }

}

class DiscountPerMonth extends Discount {

    public boolean checkIfMonthIsValid(int month) {
        return month == 12;
    }

    // returns 10% discount on monthly bill
    public int getDiscountPercentPerMonth() { return 10; } 
}

The monthly bill code will now change.

class MonthlyBill {

    public int monthlyBillPerPersonOrCompany(int id) {
        int totalCostPerEntity = gettotalCost(id);
        // fetch discount object from database
        // apply discount if 'current month' is december'
        totalCostPerEntity = totalCostPerEntity * (100 - (disCountPerMonth.getDiscountPercentPerMonth()))/100
    }
}

Now my question is:

  1. Audit class is broken because getListOfSeatsWithDiscount is moved into its subclasss of abstract method discount. How to fix it without typecaseting/instanceof ?

  2. SeatBill class is broken, since abstract class Discount does not support getDiscountPercentPerSeat. How to fix this without typecasting / instanceof ?

  3. MonthlyBill will fetch discount object from database. Once again how to resolve this issue in an OOP way without relying on instance of ?

Basically a whole lot of dependencies are broken in code base because code relies on specific methods of subclasses such as getListOfSeats or getValidMonth etc which cannot be abstracted to the base class.

Please let me know a common solution / design pattern to such refactoring.

Aucun commentaire:

Enregistrer un commentaire