我有以下数据库表:
id method_id
1 1
1 2
1 3
和2个班级:
EmailController
and Smscontroller
在我的代码中,我需要遍历表并根据method_id(1或2)来调用EmailController或Smscontroller的send方法。
推荐的设计模式是什么?
EDITED
可能有100种方法!我只放了3.这就是为什么我不喜欢if else。
同样,我发送给EmailController发送方法的对象与我发送给SmsController发送方法的对象不同。
在EmailController中我需要发送User对象。 在SmsController中,我需要发送Manager对象
答案 0 :(得分:2)
这个怎么样:
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();
我在我的解决方案中使用Strategy模式和Factory Method模式。
答案 1 :(得分:2)
我无法想到设计模式。但为了获得最大的灵活性,您可以采用与此类似的设计:
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
并让它实例化相应的控制器供您使用。
编辑:Luis建议的基于反射的代码版本。请注意,对于生产用途,您应确保传递的参数有效(非null等),并且还要严格处理异常。
method_id class_name param_class_name
1 "com.foo.SmsController" "com.foo.Manager"
2 "com.foo.EmailController" "com.foo.User"
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);
答案 2 :(得分:1)