1

I am writing an application for different geometrical types of fuel tanks.

I have a design problem that only at runtime I will receive the exact type of tank from the end user; and I don't know how to create/handle a dynamic object on the server side.

For example, a tank can have 3 geometrical types of head: conical, dished, and flat. Each type of head needs to be validated differently.

I have created a parent class named Head that has all common parameters to all geometrical types of head (diameter, thickness etc.). Each child class (Conical, Dished and Flat) extends Head and has its own instance variables.

The end user will choose, for example, a tank with conical heads and input all the required parameters and send it to the server for validation.

At this stage I am stuck. I don't know how to handle the dynamic data. I got a suggestion to use Factory design pattern; but because every class has different variables, I don't think that is the right direction.

code without constructor and get/set methods

public class Head {
    private float headThickness=0;
    private float headThicknessTolerance=0;

    private ShapeOfHead headShape;
    private float knuckleRadius=0;
    private int numberOfHeadPieces=4;
    private HeadSide headSide;

    private Figure8_1WeldingDetails headLongitudinalWeld;
    private Figure9_1WeldingDetails headCircumferentialWeld;

    private Bracing headBracing;
}

public class DishedHead extends Head {
    private float dishedHeadDepth;  
}

public class ConicalHead extends Head {
    private float conicalHeadHeight;
}
2
  • 1
    So with the Factory design pattern you wouldn't know how to instantiate an object? What about having a type field within the data typed in. You use it to differentiate the Child classes for Head. Once you have the new object, you can forward all input data. The object will know how to use the input data, because it's dedicated data for that particular class. But this seems too simple. Maybe I'm overlooking something.
    – DarkTrick
    Commented Apr 24, 2020 at 22:33
  • It's unclear what the problem is exactly, so it's hard to answer the question - can you elaborate a bit more? What are you stuck on, specifically? What step, where do you see the problem? Do you have some idea how to go about it at this point, or are you completely at loss? The Factory pattern can help you in this sort of situation when you want to impose a certain dependency structure on the code, but it doesn't seem you're quite there yet. Once the user-provided data is collected, you should be able to use it to determine the concrete type; just pass it on to the appropriate constructor. Commented Apr 24, 2020 at 23:28

2 Answers 2

3

I prefer to validate in the constructor. The idea behind that is then you know that the object state is valid because the object exists.

Now maybe you can’t validate at the client for some reason. Fine. Create a different type to hold this non-validated data. Some call it a request model. Some call it a DTO. Heck it can be a key value hash table. Whatever you call this data structure it’s what the server takes and passes into the factory to build the validated Head object.

The factory can then return a ConicalHead or a DishedHead.

Alternatively you could just model a dished head with a negative head height. Saves you from creating a FlatHead type.

The serious thing to think about isn’t the data. It’s how these types will be used. This data should be private. Encapsulated. But there should still be useful things you can tell Head to do.

Look at the using code before you settle on a design for this Head. Or you’ll just end up giving up and giving it a bunch of public getters.

0

I got a suggestion to use Factory design pattern; but because every class has different variables, I don't think that is the right direction.

Is the confusion fundamentally about polymorphism? That is, doing the same thing but differently. This is about methods, not properties.

Here's what it looks like (warning: probable invalid Java syntax)

Head dishTank  = TankFactory.Create( headType.Dish );
Head flatTank  = TankFactory.Create( headType.Flat );

dishTank.Validate(); // dish-specific validation
flatTank.Validate(); // flat-specific validation

Here is the "code behind" for the above:

public enum headType { Dish, Conical, Flat }

public class TankFactory {
    public Head Create( headType thisKind ) {
        Head tanked;

        switch( thisKind ) {
           case headType.Dish : {
              tanked = new DishedHead( thisKind ) ;
              break;
           }

           case headType.Flat: {
              tanked = new FlatHead( thisKind )
              break;
           }

        } // switch

        return tanked;
    }
}

public class Head {
    public headType whatAmI;

    // ignore other properties 

    public Head( headType thisKind ) {
       whatAmI = thisKind;
    }

    public bool Validate() { ... } // this will be over-ridden
}


public class DishedHead extends Head {
  private float dishedHeadDepth;  

  public DishedHead(headType thisKind) {
    super( thisKind );
  }

  // class properties are in scope. Parameters not needed.
  public bool Validate() { dished specific code }
}


  public class FlatHead extends Head {
    private float flatHeadHeight;

    public FlatHead( headType thisKind ) {
       super( thisKind );
    }

    // class properties are in scope. Parameters not needed.
    public bool Validate() { flat head specific validation }
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.