【问题标题】:Abstract Class, OOP Design Pattern抽象类,OOP 设计模式
【发布时间】:2013-10-10 15:15:09
【问题描述】:

我有一个名为“操作”的抽象类 并且这个类有一个叫做“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!");
    }

}

唯一的问题是一些东西是“操作”( 一些扩展 Operation 的类)需要参数来准备(一些 需要整数,有些需要字符串,有些需要更复杂的数据类型..所以它并不总是整数)

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

我使用什么 OOP 模式来实现这一点 以及如何设置此代码?

编辑:

理想情况下,我想准备和运行这样的操作:

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

假设我使用这个解决方案:

 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 {
       }
    }

那么-我想知道是否可以避免这种情况:

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

【问题讨论】:

  • 将参数传递给Teleportation 构造函数?
  • 你要具体一点,这里可以有n个答案。
  • 我想扩展 Operation 并需要参数来准备的类并不总是需要一个 int ?
  • @Julien - 是的,你是对的 - 只是做了一个编辑来解释要准备的参数并不总是 int 并且应该是复杂的数据类型:-)
  • 在我看来你的抽象类应该是一个接口,但也许是因为我没有看到整个东西^^

标签: java oop


【解决方案1】:

我建议使用额外的构造函数,您可以在其中添加实现所需的必要数据并将其存储在类实现的字段中。

你的例子:

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...
    }
}

这种方法也适用于更复杂的参数。

【讨论】:

  • 如果您想利用多态性,这是最好的方法,因为您可以将 Operation 的任何子类交给一个对象,并且它总是知道它可以调用 prepare() 而不必担心参数。毕竟,构造函数是你准备使用对象的地方——你通常不想使用单独的方法。
  • @MadSeb 我阅读了您的编辑,这种方法也支持它。
  • 是的,确实,我会回答同样的问题,基本上你是通过构造函数(准备)组装对象依赖项,然后调用 run(),但我认为你不会需要prepare()方法……对象已经准备好了,最好使用构造函数将对象置于一致状态,然后防止以后发生突变。来自我的 +1。
  • @RazvanPetruescu 同意 - 你可能不需要 prepare() 方法。
【解决方案2】:

这里要做的第一件事就是覆盖抽象类操作并用你的能力重载。

public class Teleportation extends Operation {

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

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

记住KISSYAGNI 语句,无需在代码中的任何地方使用设计模式,只要它们使事情变得更简单。

【讨论】:

    【解决方案3】:

    您要么需要扩展抽象类以包含两个方法签名,要么将签名更改为采用可变参数 int 参数:

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

    【讨论】:

      【解决方案4】:

      您可以为您的操作类使用泛型类:

      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;
          }
      }
      

      然后对于具体的类,使用适当的参数类型对其进行扩展(您可以为每个操作指定一个特定的类):

      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;
          ....
      }
      

      和:

      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;
          ....
      }
      

      【讨论】:

      • 我在这里看到了一些问题:1)一些实现根本不需要任何参数,所以这将导致必须在这些类的构造函数中调用super(null)。 2) 在某些情况下,您可能需要来自不同类型的更多参数,因此即使有 List&lt;Object&gt; 也会导致具有非常具体的类实现构造函数和/或准备/运行实现。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-14
      • 2010-09-06
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 2012-05-25
      相关资源
      最近更新 更多