Pregunta

There is a class named "Bill". Bill can be either "Electricity" , "Food" or "Customer" which are all POJO. So it contains three objects:

    public class Bill{
      private Electricity el1;
      private Food el2;
      private Customer el3;
      //setters and getters
      public setElectricity(...)
      ...
    }

List of Bills are populated using some DTOs. And each time, I need to check all elements to be sure what type of bill am I having.

My goal is to refactor this design.

I could also have one object and set the content regarding to the type, but is it having any standard pattern?

Is there any pattern for classes who can be a class based on the type that is requested? I mean Bill will be either electricity, food or customer regarding to the populating time.

Note: My application favored composition over inheritance It is also a “design by contract” based application.

Edit: Bill is not an abstract of it's objects. Lets assume, food is just specification of food like color and receipt! A bill can be one and only one of the object at a point of time.

¿Fue útil?

Solución 2

If ElectricityBill, FoodBill, GasBill has some common functionality, then create Bill as abstract class and extend other classes from bill.

If they have altogether different behaviour and state (which i doubt)then create Bill as interface and let other concrete class implement them.

i usually call it simple factory pattern(dont confuse it with factory method/abstract factory pattern)

public class BillFactory
{
    Bill createBill(String type)
    {
         if(type.equals("Electricity"))
           {
            bill=new ElectricityBill();
       }
        ........


    }
}

Otros consejos

Bill is an abstract entity hence it should be an abstract class. All other type of bills should extend from it such as : ElectricityBill, FoodBill, GasBill etc

As you have a big object with many parameters out of which some can be optional.

You can use Builder Pattern for creating the instance of your Bill class.

Unlike the abstract factory pattern and the factory method pattern whose intention is to enable polymorphism, the intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.

Suppose you are building a house:

public House getHouse() {
    return this.houseBuilder.getHouse();
  }

  public void constructHouse() {
    this.houseBuilder.buildBasement();
    this.houseBuilder.buildStructure();
    this.houseBuilder.bulidRoof();
    this.houseBuilder.buildInterior();
  }

Example from Java Papers

If Bill only can contain one instace, why dont u use a interface?

    public interface Billable {

        double getPrize();
    }

    public class Electricity implements Billable {

        @Override
        public double getPrize() {
            return 20.0;
        }
    }

    public class Bill {

        /**
         * Billable to bill.
         */
        Billable billable;
        /*
         * Discount percent applied to bill.
         */
        @Min(0)
        @Max(100)
        double discount;
        /**
         * VAT percent applied to bill.
         */
        @Min(0)
        @Max(100)
        double vat;

        public Bill(@NotNull Billable billable) {
            this.billable = billable;
            discount = 10.0;
            vat = 21.0;
        }


        public double getFinalPrize() {
            double discountFactor = 1 - discount / 100;
            double vatFactor = 1 + vat / 100;
            return billable.getPrize() * discountFactor * vatFactor;
        }

        public static void main(String[] args) {
            Electricity electricity = new Electricity();
            Bill electricityBill = new Bill(electricity);
            System.out.println(electricityBill.getFinalPrize());

        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top