рекомендуемый шаблон проектирования Java динамический вызов - PullRequest
1 голос
/ 22 января 2012

У меня есть следующая таблица БД:

id method_id
1   1
1   2
1   3

и 2 класса:

EmailController and Smscontroller

в моем коде мне нужно перебрать таблицу и в соответствии с method_id (1 или 2) вызвать метод send EmailController или Smscontroller.

Какой шаблон дизайна рекомендуется для этого?

EDITED

Там может быть 100 методов! Я ставлю только 3. Вот почему я не предпочитаю if else.

Кроме того, объект, который я отправляю в метод отправки EmailController, отличается от того, который я отправляю в метод отправки SmsController.

В EmailController мне нужно отправить объект User. В SmsController мне нужно отправить объект диспетчера

Ответы [ 3 ]

2 голосов
/ 22 января 2012

Как насчет этого:

abstract class Controller {
    public static Controller getInstance(int methodId) {
        switch (methodId) {
            case 1:
                return new EmailController();
            case 2:
                return new SmsController();
            default:
                return null;
        }
    }
    public abstract void send();
}

class EmailController extends Controller {
    @Override
    public void send() {
        System.out.println("sending email");
    }
}

class SmsController extends Controller {
    @Override
    public void send() {
        System.out.println("sending sms");
    }
}

И используйте это так:

Controller.getInstance(methodId).send();

Я использую шаблон Стратегия и шаблон Factory Method в моем решении.

2 голосов
/ 22 января 2012

Я не могу придумать шаблон дизайна.Но для максимальной гибкости у вас может быть дизайн, подобный следующему:

public interface Sendable /* or Sender, SendingManager, etc. */ {
  public int getId();
  public void send();
}

public class EmailController implements Sendable {
}

public class SmsController implements Sendable {
}

public class Sendables {

 private Map<Integer, Sendable> sendables = new HashMap<Integer, Sendable>();

 public void addSendable(Sendable s) {
   this.sendables.put(s.getId(), s);
 }

 public void sendById(Integer id) {
   this.sendables.get(id).send();
 }

}

Тогда вы можете использовать его так:

Sendables sendables = new Sendables();
sendables.add(new EmailController());
sendables.add(new SmsController());
sendables.add(new ChatController());
// etc.


Row row = table.getRow(...); // let's assume this gets a row from your table
sendables.send(row.getId());

Другим решением может быть дополнительная таблица, подобная этой:

TABLE: CLASS_NAMES
method_id class_name
1         "com.foo.SmsController"
2         "com.foo.EmailController"

А затем передайте class_name в Class.forName и дайте ему возможность создать экземпляр соответствующего контроллера для использования.

РЕДАКТИРОВАТЬ: На основе отраженияверсия кода, предложенная Луисом.Обратите внимание, что для производственного использования вы должны убедиться, что переданные параметры действительны (не нулевые и т. Д.), А также обрабатывать исключения со строгостью.

TABLE: CLASS_NAMES

method_id class_name                 param_class_name
1         "com.foo.SmsController"    "com.foo.Manager"
2         "com.foo.EmailController"  "com.foo.User"

SendManager

public class SendManager {

    private static final String SEND_METHOD_NAME = "send";

    /* DAO for the CLASS_NAMES tables */
    private ClassNameDAO classNameDao;

    /**
     * Gets the row corresponding to methodId, for example
     * (1, "com.foo.SmsController", "com.foo.Manager") then using reflection
     * instantiates an instance of SmsController and invokes its send method
     * with <code>param</code> passed to it.
     */
    public void send(int methodId, Object param) throws Exception {
        ClassNameRow classNameRow = classNameDao.findByMethodId(methodId);

        String senderParameterClassName = className.senderParameterClassName();
        Class paramClass = Class.forName(senderParameterClassName);

        if (!paramClass.isInstance(param)) {
            throw new IllegalArgumentException("methodId and param are not compatible");
        }

        String senderClassName = classNameRow.getSenderClassName();
        Class senderClass = Class.forName(senderClassName);     

        /* Your sender classes must be JavaBeans and have no-arg constructors */
        Object sender = senderClass.newInstance();

        Class paramClass = Class.forName(senderParameterClassName);

        Method send = senderClass.getMethod(SEND_METHOD_NAME, paramClass);

        send.invoke(sender, param);
    }

}

Пример использования

SendManager sendManager = new SendManager();

Manager m = ...;
sendManager.send(1, m);

User u = ...;
sendManager.send(2, u);
1 голос
/ 22 января 2012
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...