如何使用设计模式代替开关盒
How to use design Pattern in place of switch case
我有枚举class
public enum TaskName {
LOGIN,REGISTER,MESSAGE
}
我将此枚举与 switch-case 一起使用
public class TaskController {
private UserDao userDaoJpaImpl;
private FriendDao friendDaoJpaImpl;
private GroupDao groupDaoJpaImpl;
private MessageDao messageDaoJpaImpl;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
userDaoJpaImpl = new UserDaoJpaImpl(emfactory);
friendDaoJpaImpl = new FriendDaoJpaImpl(emfactory);
groupDaoJpaImpl = new GroupDaoJpaImpl(emfactory);
messageDaoJpaImpl = new MessageDaoJpaImpl(emfactory);
}
public void doIt(String taskName)
{
switch (taskName) {
case LOGIN:
userDaoJpaImpl.create(/*Something*/);
//Implementation
break;
case REGISTER:
//Implementation
break;
case MESSAGE:
messageDaoJpaImpl.create(/*Something*/);
//Implementation
break;
}
}
}
我将 TaskController 对象创建为
static TaskController controller=new TaskController()
这样对象只创建一次
现在我打算用命令模式代替 switch-case
但我不知道如何在命令 classess
中使用我的 UserDaoJpaImpl、FriendDaoJpaImpl、GroupDaoJpaImpl、MessageDaoJpaImpl
编辑
命令Class
public interface Command {
void setSession(Session session); //Session is websocket connection session not HttpSession
void setConnectedUser(Map<String, UserDTO> connectedUser);
void setData(String data);
JSONObject execute();
}
我想将整个逻辑从 TaskController.doIt() 移动到将实现命令接口的其他命令 class。
我正在使用 Websocket。我不想用 spring 来解决这个问题
提前致谢
你正在寻找我解决这个问题的方法。
本质上,
public enum TaskName {
LOGIN {
@Override
public void doIt(TaskController taskController) {
taskController.getUserDao().create(/*something*/);
//...
}
},
REGISTER {
@Override
public void doIt(TaskController taskController) {
//Implementation
}
},
MESSAGE {
@Override
public void doIt(TaskController taskController) {
taskController.getMessageDao().create(/*something*/);
//...
}
};
private TaskName() {
}
public abstract void doIt(TaskController taskController);
public static TaskName getByTaskName(String taskName) {
for(TaskName taskEnum : TaskName.values()) {
if(taskEnum.name().equalsIgnoreCase(taskName)) {
return taskEnum;
}
}
throw new IllegalArgumentException("The Task Name [" + taskName + "] is not a valid task name!");
}
}
public class TaskController {
private UserDao userDaoJpaImpl;
private FriendDao friendDaoJpaImpl;
private GroupDao groupDaoJpaImpl;
private MessageDao messageDaoJpaImpl;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
userDaoJpaImpl = new UserDaoJpaImpl(emfactory);
friendDaoJpaImpl = new FriendDaoJpaImpl(emfactory);
groupDaoJpaImpl = new GroupDaoJpaImpl(emfactory);
messageDaoJpaImpl = new MessageDaoJpaImpl(emfactory);
}
public void doIt(String taskName) {
TaskName.getByTaskName(taskName).doIt(this);
}
}
除非我完全误解了你的问题,因为你从来没有真正展示过你的 Command
类。
您还应该考虑针对这个特定问题使用框架,例如 Spring 框架.
让问题有点模糊和主观,让我们可以自由想象 :)。这是我对结构的看法。
public interface Command {
public void doIt(EntityManagerFactory emFactory);
}
class LoginCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
UserDaoJpaImpl userDaoJpaImpl = new UserDaoJpaImpl(emFactory);
// Do something
}
}
class RegisterCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
}
}
class MessageCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
}
}
enum TaskName {
LOGIN(new LoginCommand()), REGISTER(new RegisterCommand()), MESSAGE(new MessageCommand());
private Command command;
TaskName(Command command) {
this.command = command;
}
public void doIt(EntityManagerFactory emFactory) {
command.doIt(emFactory);
}
}
public class TaskController {
private EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
public void doIt(String taskName) {
TaskName task = TaskName.valueOf(taskName);
task.doIt(emFactory);
}
}
所有的方法都被称为doIt
,当然它们会发生变化。
与@epicPandaForce 相同的想法,但在 java 8 中可以稍微不同地处理。通过将 lambda 传递给构造函数。
public enum TaskName {
LOGIN((taskController) -> {
taskController.getUserDao().create(/*something*/);
//...
}),
REGISTER((taskController) -> {
//Implementation
}),
MESSAGE((taskController) -> {
//...
});
private final Consumer<TaskController> doIt;
private TaskName(Consumer<TaskController> doIt) {
this.doIt = doIt;
}
public final void service(...) {
doIt(...);
}
public interface Command {
public void Execute();
}
public class Invoker {
private Map<TaskName,Command> commandMap = new EnumMap<TaskName,Command>(TaskName.class);
public void AddCommand(TaskName task,Command command){
commandMap.put(task, command);
}
public void HandleCommand(TaskName task){
Command command=commandMap.get(task);
command.Execute();
}
}
public class ConcreteMessageCommand implements Command {
private MessageDao messageDaoJpaImpl;
public ConcreteMessageCommand(MessageDao md){
messageDaoJpaImpl=md;
}
@Override
public void Execute() {
// TODO Auto-generated method stub
messageDaoJpaImpl.create();
}
}
public class ConcreteUserCommand implements Command {
private UserDao userDaoJpaImpl;
public ConcreteUserCommand(UserDao ud){
userDaoJpaImpl=ud;
}
@Override
public void Execute() {
userDaoJpaImpl.create();
}
}
public class TaskController {
Invoker invoker;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
invoker=new Invoker();
ConcreteUserCommand cuc=new ConcreteUserCommand(new UserDaoJpaImpl(emfactory));
invoker.AddCommand(TaskName.LOGIN, cuc);
ConcreteMessageCommand cmc=new ConcreteMessageCommand(new MessageDaoJpaImpl(emfactory));
invoker.AddCommand(TaskName.MESSAGE, cmc);
}
public void doIt(TaskName taskName)
{
invoker.HandleCommand(taskName);
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
TaskController task=new TaskController();
task.doIt(TaskName.LOGIN);
}
}
你可以像这样使用命令模式来消除 switch-case,GroupDaoJpaImpl- MessageDaoJpaImpl 可以被认为是接收器 objects.You 可以更改创建对象的位置以优化代码。
我有枚举class
public enum TaskName {
LOGIN,REGISTER,MESSAGE
}
我将此枚举与 switch-case 一起使用
public class TaskController {
private UserDao userDaoJpaImpl;
private FriendDao friendDaoJpaImpl;
private GroupDao groupDaoJpaImpl;
private MessageDao messageDaoJpaImpl;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
userDaoJpaImpl = new UserDaoJpaImpl(emfactory);
friendDaoJpaImpl = new FriendDaoJpaImpl(emfactory);
groupDaoJpaImpl = new GroupDaoJpaImpl(emfactory);
messageDaoJpaImpl = new MessageDaoJpaImpl(emfactory);
}
public void doIt(String taskName)
{
switch (taskName) {
case LOGIN:
userDaoJpaImpl.create(/*Something*/);
//Implementation
break;
case REGISTER:
//Implementation
break;
case MESSAGE:
messageDaoJpaImpl.create(/*Something*/);
//Implementation
break;
}
}
}
我将 TaskController 对象创建为 static TaskController controller=new TaskController()
这样对象只创建一次
现在我打算用命令模式代替 switch-case
但我不知道如何在命令 classess
中使用我的 UserDaoJpaImpl、FriendDaoJpaImpl、GroupDaoJpaImpl、MessageDaoJpaImpl编辑
命令Class
public interface Command {
void setSession(Session session); //Session is websocket connection session not HttpSession
void setConnectedUser(Map<String, UserDTO> connectedUser);
void setData(String data);
JSONObject execute();
}
我想将整个逻辑从 TaskController.doIt() 移动到将实现命令接口的其他命令 class。
我正在使用 Websocket。我不想用 spring 来解决这个问题
提前致谢
你正在寻找我解决这个问题的方法
本质上,
public enum TaskName {
LOGIN {
@Override
public void doIt(TaskController taskController) {
taskController.getUserDao().create(/*something*/);
//...
}
},
REGISTER {
@Override
public void doIt(TaskController taskController) {
//Implementation
}
},
MESSAGE {
@Override
public void doIt(TaskController taskController) {
taskController.getMessageDao().create(/*something*/);
//...
}
};
private TaskName() {
}
public abstract void doIt(TaskController taskController);
public static TaskName getByTaskName(String taskName) {
for(TaskName taskEnum : TaskName.values()) {
if(taskEnum.name().equalsIgnoreCase(taskName)) {
return taskEnum;
}
}
throw new IllegalArgumentException("The Task Name [" + taskName + "] is not a valid task name!");
}
}
public class TaskController {
private UserDao userDaoJpaImpl;
private FriendDao friendDaoJpaImpl;
private GroupDao groupDaoJpaImpl;
private MessageDao messageDaoJpaImpl;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
userDaoJpaImpl = new UserDaoJpaImpl(emfactory);
friendDaoJpaImpl = new FriendDaoJpaImpl(emfactory);
groupDaoJpaImpl = new GroupDaoJpaImpl(emfactory);
messageDaoJpaImpl = new MessageDaoJpaImpl(emfactory);
}
public void doIt(String taskName) {
TaskName.getByTaskName(taskName).doIt(this);
}
}
除非我完全误解了你的问题,因为你从来没有真正展示过你的 Command
类。
您还应该考虑针对这个特定问题使用框架,例如 Spring 框架.
让问题有点模糊和主观,让我们可以自由想象 :)。这是我对结构的看法。
public interface Command {
public void doIt(EntityManagerFactory emFactory);
}
class LoginCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
UserDaoJpaImpl userDaoJpaImpl = new UserDaoJpaImpl(emFactory);
// Do something
}
}
class RegisterCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
}
}
class MessageCommand implements Command {
@Override public void doIt(EntityManagerFactory emFactory) {
}
}
enum TaskName {
LOGIN(new LoginCommand()), REGISTER(new RegisterCommand()), MESSAGE(new MessageCommand());
private Command command;
TaskName(Command command) {
this.command = command;
}
public void doIt(EntityManagerFactory emFactory) {
command.doIt(emFactory);
}
}
public class TaskController {
private EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
public void doIt(String taskName) {
TaskName task = TaskName.valueOf(taskName);
task.doIt(emFactory);
}
}
所有的方法都被称为doIt
,当然它们会发生变化。
与@epicPandaForce 相同的想法,但在 java 8 中可以稍微不同地处理。通过将 lambda 传递给构造函数。
public enum TaskName {
LOGIN((taskController) -> {
taskController.getUserDao().create(/*something*/);
//...
}),
REGISTER((taskController) -> {
//Implementation
}),
MESSAGE((taskController) -> {
//...
});
private final Consumer<TaskController> doIt;
private TaskName(Consumer<TaskController> doIt) {
this.doIt = doIt;
}
public final void service(...) {
doIt(...);
}
public interface Command {
public void Execute();
}
public class Invoker {
private Map<TaskName,Command> commandMap = new EnumMap<TaskName,Command>(TaskName.class);
public void AddCommand(TaskName task,Command command){
commandMap.put(task, command);
}
public void HandleCommand(TaskName task){
Command command=commandMap.get(task);
command.Execute();
}
}
public class ConcreteMessageCommand implements Command {
private MessageDao messageDaoJpaImpl;
public ConcreteMessageCommand(MessageDao md){
messageDaoJpaImpl=md;
}
@Override
public void Execute() {
// TODO Auto-generated method stub
messageDaoJpaImpl.create();
}
}
public class ConcreteUserCommand implements Command {
private UserDao userDaoJpaImpl;
public ConcreteUserCommand(UserDao ud){
userDaoJpaImpl=ud;
}
@Override
public void Execute() {
userDaoJpaImpl.create();
}
}
public class TaskController {
Invoker invoker;
public TaskController() {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("Eclipselink_JPA");
invoker=new Invoker();
ConcreteUserCommand cuc=new ConcreteUserCommand(new UserDaoJpaImpl(emfactory));
invoker.AddCommand(TaskName.LOGIN, cuc);
ConcreteMessageCommand cmc=new ConcreteMessageCommand(new MessageDaoJpaImpl(emfactory));
invoker.AddCommand(TaskName.MESSAGE, cmc);
}
public void doIt(TaskName taskName)
{
invoker.HandleCommand(taskName);
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
TaskController task=new TaskController();
task.doIt(TaskName.LOGIN);
}
}
你可以像这样使用命令模式来消除 switch-case,GroupDaoJpaImpl- MessageDaoJpaImpl 可以被认为是接收器 objects.You 可以更改创建对象的位置以优化代码。