Java API设计创建自己的API时遇到的问题

时间:2014-05-07 08:13:28

标签: java api design-patterns api-design

我正在开发一个项目,包括在主从模式下通过串口在计算机应用程序和嵌入式设备之间进行通信。

该应用程序将作为多个嵌入式设备的主服务器。

通信部分几乎完成。但现在,我将其重构为API。 因此,它可以用于多个项目,也可以用于配置非常少的许多开发人员。

我在API设计方面不是很好,即使是第一次,我正在创建一个API。

现在,我坚持以下问题: 请考虑以下情况:

/*
 * API Part
 */
public abstract class AbstractSlave {

  // Some fields, constructor and other methods.

  final void handle(Request request, Response response) {
    // Some operations before starting worker thread.

    SlaveWorker worker = new SlaveWorker(request, response);
    worker.start();
  }

}

public class SlaveWorker extends Thread {

  // Constructor

  @Override
  public final void run() {
    work(request, response);
  }

  public void work(Request request, Response response) {

  }

}

AbstractSlave类启动一个工作线程来处理请求和响应,这样长时间运行的操作不会导致从服务器即将发生的响应丢失。

现在,这是" API使用部分":

/*
 * API Usage Part
 */
public class Slave extends AbstractSlave {

  // Constructor

}

public class MyWorker extends SlaveWorker {

  // Constructor

  @Override
  public void work(Request request, Response response) {
    super.work(request, response);

    // My work to be done upon request and response.
  }

}

但正如我们所看到的,AbstractSlave创建了SlaveWorker个实例。 因此,将调用SlaveWorker work()方法,而不是MyWorker

如何让AbstractSlave班级来调用MyWorker work()方法?

注:

  • 由于它是一个API设计,AbstractSlave不知道,有一个MyWorker类。因此,无法直接创建MyWorker实例来代替SlaveWorker
  • handle() AbstractSlave方法可以/意味着不会被覆盖,因为有一些操作需要在启动工作线程之前执行。

2 个答案:

答案 0 :(得分:0)

我认为关键点是让API的客户端创建SlaveWorker(或任何子类)的实例,以便他可以自定义work()方法。

IMO你应该在你的API中提供一个Worker接口(接口比抽象类更少限制):

public interface Worker {
    public void work(Request request, Response response);
}

并且AbstractSlave的方法应该是:

public abstract class AbstractSlave {

    private final Worker worker;

    public AbstractSlave(Worker worker) {
        this.worker = worker;
    }

    final void handle(final Request request, final Response response)
        // Some operations before starting worker thread.

        Thread t = new Thread() {
            public void run() {
                worker.work(request, response);
            }
        };
        t.start();
    }

}

答案 1 :(得分:0)

有不同的方法可以执行此操作,但一种方法是向configureJob添加AbstractSlave方法,并使用此方法告诉AbstractSlave课程MyWorker

public class SlaveManager {
   private Class workerClass = SlaveWorker.class;

   public void configureJob(Class clazz){
      workerClass = clazz;
   }

   final void handle(Request request, Response response) {
      // Some operations before starting worker thread.

      Worker worker = workerClass.newInstance();
      worker.start(request, response);
   }
}

public interface Worker {
   public void work(Request request, Response response);
}

main方法中,只需在致电SlaveManager::configureJob(MyWorker.class)之前致电SlaveManager::handle()

现在,我通过使用Object.newInstance()创建Worker来保持简单,但这不是推荐的一般做法。习惯使用WorkerFactory代替,但我不想在你不熟悉Factory Pattern的情况下引入新的类和新的设计模式。

相关问题