How to consolidate many classes and avoid instances?

The program that I am helping to develop should output several dynamically generated questions for the user's response. Questions are of different types and have the corresponding Constraint class, which is populated with user data. My question is how to create consistent behavior for different constraints.

  ---->Constraint<-------------------- | | | FConstraint PConstraint TConstraint | | UConstraint AConstraint 

The base class of Constraint empty, as is TConstraint.

UConstraint , PConstraint and AConstraint share three variables. However, UConstraint and AConstraint have one additional variable that PConstraint does not have.

It seems to me that I'm trying to hammer a brick wall with some ticks. My thought is to provide an abstract Constraint method with a signature:

 // All answers are of type string. abstract void setValue(string variable, string answer); 

which are implemented by each subclass of Constraint . However, passing a string to determine which variable to set seems error-prone, and the same bad code smell.

The second option was to move three similar variables to Constraint, but that still leaves UConstraint, AConstraint with this extra bit of information that I might need to set. This does not help TConstraint not need any of them.

My current brute force is β€œTurn this project on.” the solution is instanceof soup, in which I check and fill in the missing information related to restrictions.

 Object constraint = item.getConstraint(); if (constraint instanceof AConstraint) { AConstraint constraint = (AConstraint) constraint; if (constraint.getValue() == null) { constraint.setValue(string); } else if (constraint.getKey() == null) { constraint.setKey(string); } // More of the same. } else if (constraint instanceof PConstraint) { // As the above if() group. } // etc. 

Is there a better solution for this design than an abstract function?

+4
source share
5 answers

In your question there is not enough information about the actual work that you need to do in each case, but usually this code:

 Object constraint = item.getConstraint(); if (constraint instanceof AConstraint) { // Work } else if (constraint instanceof PConstraint) { // Work } // etc. 

- a strong odor for using polymorphism and refactoring into something like this:

 Constraint constraint = item.getConstraint(); constraint.doWork(...); 

where specific classes will look something like this:

 public class AConstraint { public ... doWork(...) { if (getValue() == null) { setValue(string); } else if (getKey() == null) { setKey(string); } // More of the same. } } 
+3
source

Use this principle

A program in interfaces and an encapsulation of behavior that continues to change in an abstract class or interfaces.

for example: for your example above

Interface - restriction

Abstract class - FConstraint

Concrete class - PConstraint, TConstraint, UConstraint, AConstraint

+3
source

You can do something like this:

 public interface Constraint{} public abstract class VariableConstraint implements Constraint { /* hold 3 shared variables here */ } public class UConstraint extends VariableConstraint{} public class PConstraint extends VariableConstraint{} public class AConstraint extends VariableConstraint{} public abstract class EmptyConstraint implements Constraint {} public class TConstraint extends EmptyConstraint {} 
+2
source

Define general functionality in Constraint : any operation that you want to perform on a Constraint object (which may actually be an object of one of the subtypes), you have a method for this function in Constraint that you override in subclasses.

You may have a trivial (for example, empty) implementation for parent classes, where this functionality does not make sense.

This way, you don’t have to care about a particular class of the object, just use the facility provided by the superclass

+1
source

Have Constraint as an interface. Define an abstract class that extends this Constraint , and this should have shared variables. UConstraint , AConstraint should extend this abstract class, which has common variables. Other classes can directly implement the Constraint interface. The code instance must be changed as

 Constraint constraint = item.getConstraint(); constraint.doWork(..); 

Always the best design - write code with an interface

+1
source

Source: https://habr.com/ru/post/1414001/


All Articles