Need help \ hint.
Abstracting, give an analogy. If you want to read further - be sure to eat.

Have обед (Our object). It consists of three different things. Первое, второе и третье (these are different objects). You need to create an object that has a different set of these things. Those. lunch can consist of the first and third, and there is no second. Or only from the first. Or only from the third, or from all at once. Lunch should consist of no more than these three objects (the first, second and third).
Reason dictates that there should be a pattern that will help me. I would like to know in which direction to dig, what to look for? For it is somehow unwise to override the constructor.

    3 answers 3

    One answer has already been given to you, I will try to provide some logical alternative.

    First, the "First", "Second" or "Third" is too weak a sign to use for this inheritance (otherwise any addition of the "Dessert" or the abstract "Fourth" dish) will result in the need to create a new basic object . Thus, it is a property of a particular object .

    Further, the program design is built as follows (in general, speaking, the name of the product can also be made a property and avoid inheritance in general, but here, probably, the example will look better with inheritance than without it):

     public abstract class Portion { // Технические детали можете додумать самостоятельно :) public PortionType getType() { ... } } // Реализуем так, что тип данной порции = "Первое" public class Cheesburger : public Portion { ... } // Реализуем так, что тип данной порции = "Десерт" public class CocaCola : public Portion { ... } 

    Now let's think about how we imagine lunch. "Lunch" is a collection of servings, organized as follows, so that the specified conditions are fulfilled (in your case, it consists of exactly three dishes of known types) .

     public class Meal { public List<Portion> getPortions() { ... } } 

    The question is how to allow the creation of those and only those meals that satisfy the conditions you set out. The solution is also easy - we prohibit the construction of the Meal object through its constructor, and we introduce for this purpose some abstract factory.

    A possible interface might look like this:

     public class MealFactory { // Построим, например, по методу 'first fit'. public Meal buildFirstFitMealFromAvailablePortions(List<Portion> availablePortions) throws ImpossibleToBuildMealException { ... } // А здесь передадим как параметр некоторое правило построения обедов. public Meal buildMealFromAvailablePortions(List<Portion> availablePortion, MealBuildingRule buildingRule) throws ImpossibleToBuildMealException { ... } } 

    Here, too, there are options - you can bind strategies directly to the builder or even use some method of dependency injection.


    By the way, as an alternative to the factory, it is possible to consider the Pattern Builder , which is well discussed in the book Effective Java.

      Somehow you made it all difficult for yourself. We have ОБЕД (1 object), we have 3 БЛЮДА (3 different objects), it remains to create a МЕНЮ list, which will contain a set of these dishes and a class that will follow the logic (list formation).

      • Probably, the analogy I got was not the best. These three dishes have nothing to do with each other (except for the fact that an object consists of them). - Viacheslav

      The task can be solved in this way:

        class Meal { public enum Type { FIRST , SECOND , DESERT }; private final HashMap < Type, Portion > portions = new HashMap < Type, Portion > (); public Portion getPortion ( final Meal.Type type ) { return portions.get ( type ); } public List < Portion > getPortions () { return new ArrayList < Portion > ( portions.values () ); } public boolean setPortion ( final Portion p ) { if ( ( null == p ) || ( null == p.getType () ) ) { return false; } // check if exist if ( portions.containsKey ( p.getType () ) ) { // uncomment if you don't need replace existing portions // return false; } // store portion by type // (override if it already exist) portions.put ( p.getType (), p ); return true; } } class Portion { private final Meal.Type type = null; public Meal.Type getType () { return type; } } 

      As for the patterns, if you have any difficulties, I would advise you not to try to master everything at once, better in turn.
      The fact is that some patterns are complex and include several others. It happens that the code samples for several patterns are the same or very similar. which greatly complicates perception :)