Abstract Class, OOP Design Pattern

2019-09-07 08:15发布

问题:

I have an abstract class called "Operation" and this class has an abstract method called "Prepare".

public abstract class Operation {
    public abstract void prepare() throws Exception;
    public abstract void run() throws Exception;
    // other stuff here that's not abstract
    public void printHelloWorld() { 
         System.out.println("Hello World!");
    }

}

The only issue is that some things that are "Operation" ( some classes that extends Operation ) need arguments to prepare ( some need ints, some need String, some need more complex data types..so it's not always an int )

public class Teleportation extends Operation {
   @Override
   public void prepare(int capacityRequired ) throws Exception {
        // do stuff
   }
   @Override
   public void run() throws Exception {
   }
}

What OOP pattern do I use to achieve this and how do I set up this code ?

EDIT :

Ideally, I want to prepare and run operations like this :

for (Operation operation : operations ) {
  operation.prepare();
  operation.run(); 
}

Assuming I use this solution :

 public class Teleportation extends Operation {
       private int cReq;
       public void setCapacityRequired(int cReq) {
         this.cReq = cReq;
       }
       @Override
       public void prepare() throws Exception {
                // I can do the preparation stuff
                // since I have access to cReq here
       }
       @Override
       public void run() throws Exception {
       }
    }

Then - I wonder if it's possible to avoid this :

 for (Operation operation : operations ) {
      if (operation.getClass().isInstanceOf(Teleporation.class)) {
               ((Teleporation)operation).setCapacityRequired( 5 );
      }
      operation.prepare();
      operation.run(); 
    }

回答1:

I would recommend having an additional constructor where you can add the necessary data that the implementation requires and store it in fields for the class implementation.

For your example:

public class Teleportation extends Operation {
    private final int capacityRequired;
    public Teleportation(int capacityRequired) {
        this.capacityRequired = capacityRequired;
    }
    public void prepare() throws Exception {
    // do stuff using the capacityRequired field...
    }
}

This approach applies for more complex parameters as well.



回答2:

The very first thing to do here is to override the abstract class operation and overload with your capacity.

public class Teleportation extends Operation {

    public void prepare() throws Exception {
        prepare(0);
    }

    public void prepare(int capacityRequired) throws Exception {
        //do stuff
    }
}

And remember the KISS and YAGNI statements, there is no need to use design patterns anywhere in your code, just where they makes things simpler.



回答3:

You either need to expand the abstract class to include two method signatures or change the signature to take a varargs int parameter:

public abstract class Operation {
    public abstract void prepare(int... args) throws Exception;
}


回答4:

You can use generic class for your operation class:

public abstract class Operation<T>
{
    private T operationModel;

    public Operation(T operationModel)
    {
        super();
        this.operationModel = operationModel;
    }

    public abstract void prepare() throws Exception;

    public abstract void run() throws Exception;

    public T getOperationModel()
    {
        return operationModel;
    }
}

Then for concrete classes, extend it with proper parameter-type (You can have a specific class for each operation):

public class TeleOperation extends Operation<TeleOperationModel>
{
    public TeleOperation(TeleOperationModel operationModel)
    {
        super(operationModel);
    }

    @Override
    public void prepare() throws Exception
    {
        TeleOperationModel teleOperationModel = getOperationModel();
        //...

    }

    @Override
    public void run() throws Exception
    {

    }
}

public class TeleOperationModel
{
    private int capacity;
    ....
}

and:

public class MicroOperation extends Operation<MicroOperationModel>
{
    public MicroOperation(MicroOperationModel operationModel)
    {
        super(operationModel);
    }

    @Override
    public void prepare() throws Exception
    {
        MicroOperationModel  microOperationModel = getOperationModel();
        //...
    }

    @Override
    public void run() throws Exception
    {

    }
}

public class MicroOperationModel
{
    private int x;
    private int y;
    private int z;
    ....
}


标签: java oop