Question

We have a case where we need build a Resource which can be one of two types: Logical or Physical. With each resource subtype, we have a Configuration attached which can be a LogicalConfiguration and a PhysicalConfiguration.

This is done because the configuration objects are editable and need to be versioned. Such as a resource can have two configuration versions: active and draft. A method is provided in Resource to Add a configuration addConfiguration(Configuration config)

Now, we are facing a issue, LogicalConfiguration can be wrongly passed to addConfiguration method for a PhysicalResource.

Resource resource = new PhysicalResource()
Configuration config = new LogicalResourceConfiguration();
physicalResource.addConfiguration(config)

This invocation will succeed and a wrong configuration will get added. Following ways can be used to avoid this.

  1. We do the instanceOf check or define a member Type, but this will kill polymorphism.
  2. We create two methods addLogicalConfiguration/addPhysicalConfiguration one of them fails at Runtime.

What will be the most suitable way to approach this problem ? Or is there a specific pattern to address these kind of issues?

No correct solution

OTHER TIPS

You can add a generic type parameter to the Resource class:

class Resource<T extends Configuration> {
    public void addConfiguration(T config) {}
}

Then, you can have:

class PhysicalResource extends Resource<PhysicalConfiguration> {...}

class LogicalResource extends Resource<LogicalConfiguration> {...}

This structure should fulfill your expectations, by giving a compilation error when an attempting to add an incorrect Configuration type to a Resource:

abstract class Configuration  {
}
   class LogicalConfiguration extends Configuration  {
   }
   class PhysicalConfiguration extends Configuration  {
   }
abstract class Resource<C extends Configuration>  {
   private C config;
   public void addConfiguration(C config)  {
      this.config = config;
   }
   public C getConfig()  {
      return  config;
   }
}
   class LogicalResource extends Resource<LogicalConfiguration>  {
   }
   class PhysicalResource extends Resource<PhysicalConfiguration>  {
   }

Use it exactly as you do in your example:

Resource resource = new PhysicalResource()
Configuration config = new LogicalResourceConfiguration();

//COMPILATION ERROR:
physicalResource.addConfiguration(config);                        

Put the classes into their own package and make addConfiguration in Resource protected.

That way, anyone using your package will discover the error at code writing time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top