利用策略模式与退化的建造模式实现减少工作量的方法

前言

    大家都知道springMVC的使用,我们会少些很多servlet层面的代码,但是随着controller使用多了,就会我们的代码上多出许多RequestMapping注解,

  举个例子

    一个web文件管理的例子,用户需要这个目录的所有文件,请求到了一个RequestMapping方法,这时我们使用一个类来处理这个这个目录下面的所有文件信息,

我们需要返回每个文件的详细信息,这时如果使用RequestMapping方法就显得有些鸡肋了

  • 为什么呢?
  • 例如我们需要使用到很多RequestMapping方法来处理客户端每个请求,你想啊,只是一个类似于ls的命令我们就需要创建一个往客户端返回的json对象,当需要实现的功能很多时,这无疑是曾加了许多无用的劳动力,而且会让我们创建很多json对象

好了问题出来了我们来找一个解决办法,问题是什么呢?

1、需要一个只需要实例化一次的json对象方法,2、尽量少些RequestMapping

 

下面我们先解决第二种问题

如果要少些RequestMapping方法就需要让一个RequestMapping方法来解决客户端的需求,这里就要使用一个策略方法

具体实现方法如何实现呢

嗯,上代码

例如

这个是它的一个接口

public interface CommandExecutorFactory {
    CommandExecutor get(String commName);

}

实现类

@Service("commandExecutorFactory")
public class DefaultCommandExecutorFactory  implements CommandExecutorFactory{


    String _classNamePattern;
    private Map<String,CommandExecutor>_map= new HashMap<String,CommandExecutor>();

    private CommandExecutor _fallbackCommand;
    
    @Override
    public CommandExecutor get(String commName) {
        
          if (_map.containsKey(commName)){
                return _map.get(commName);
            }
          try {
                String className = String.format(_classNamePattern,commName.
                        substring(0,1).toUpperCase()+commName.substring(1));
                return (CommandExecutor) Class.forName(className).newInstance();

            } catch (Exception e) {
                return _fallbackCommand;
            }
    }

    public String get_classNamePattern() {
        return _classNamePattern;
    }

    public void set_classNamePattern(String _classNamePattern) {
        this._classNamePattern = _classNamePattern;
    }

    public Map<String, CommandExecutor> get_map() {
        return _map;
    }

    public void set_map(Map<String, CommandExecutor> _map) {
        this._map = _map;
    }

    public CommandExecutor get_fallbackCommand() {
        return _fallbackCommand;
    }

    public void set_fallbackCommand(CommandExecutor _fallbackCommand) {
        this._fallbackCommand = _fallbackCommand;
    }

}

如何使用呢

public class CommandController{
    private CommandExecutorFactory commandExecutorFactory;

    private FsUserCommandFactory fsUserCommandFactory;
    
    

    public void connector(HttpServletRequest request,
             HttpServletResponse response)throws IOException, ServletException{
     CommandExecutor executor = null;
        
            executor = commandExecutorFactory.get(cmd);
    
        if(executor==null){
            throw new FsException(String.format("咱不不支持此方法: %s", cmd));
        }

。。。。。。。。。。。。。。
    }
}

 

通过配置的类的包路径来通过class.forname转换成对象文件,如果报错的话说明是没有此方法的我们返回到前端

这个是不是有点类似Struts的出来方式呢

第二个小问题解决了,这样我们就只需要一个@requestMapping注解就可以

然后先说说第一个问题,如果仅仅只创建一个json对象很多人立刻想到,单例???

what。你在想什么,也可能是我自己这样想的把

其实springmvc这个在上层代码结构里为我们解决了这个办法,所使用的是建造模式的退化版本,相同于模板方法 ,这个退化版本又和模板方法差异’,

来看下UML

建造模式当退化的时候就变成了下列模样

但是呢,还是推荐你去看原文《java与模式》建造模式一篇中详细的介绍

贴张图片

下面用一个比较简单的方法来解决上面的问题

源码是elfinder'的一个实现

我仿照了两个它的两个版本重新修改了下

地址https://github.com/glide-the/dmeck

先附代码,之后详细介绍

controller

@Controller
@RequestMapping("connector")
public class ConnectorController {

    @Resource(name = "commandExecutorFactory")
    private CommandExecutorFactory commandExecutorFactory;

    @Resource(name ="fsServiceFactory")
    private FsServiceFactory fsServiceFactory;

    @RequestMapping
    public void connector(HttpServletRequest request,
                          final HttpServletResponse response)throws IOException{
        /**
         * 文件上传暂时不做
         */
        String cmd = request.getParameter("cmd");
        CommandExecutor executor = commandExecutorFactory.get(cmd);
        if(executor==null){
            throw new FsException(String.format("unknown command: %s", cmd));
        }

        try {
            final HttpServletRequest finalRequest = request;
                executor.execute(new CommandExectionContext() {
                    /**
                     * 总是返回一个factory
                     * @return
                     */
                    @Override
                    public FsServiceFactory getFsServiceFactory() {
                        return fsServiceFactory;
                    }

                    @Override
                    public HttpServletRequest getRequest() {
                        return finalRequest;
                    }

                    @Override
                    public HttpServletResponse getResponse() {
                        return response;
                    }

                    @Override
                    public ServletContext getServletContext() {
                    return finalRequest.getSession().getServletContext();
                }
                 });
        } catch (Exception e) {
            throw new FsException("unknown error", e);
        }

    }

。。。。。。。。。。

 

三个包装接口

CommandExectionContext
public interface CommandExectionContext
{
    FsServiceFactory getFsServiceFactory();

    HttpServletRequest getRequest();

    HttpServletResponse getResponse();

    ServletContext getServletContext();
}
CommandExecutor
/**
 * 抽象工厂AbstractCommandExecutor的接口
 */
public interface CommandExecutor {
    void execute(CommandExectionContext commandExectionContext) throws  Exception;
}
CommandExecutorFactory
反射接口

public interface CommandExecutorFactory {
    CommandExecutor get (String commandName);
}
AbstractCommandExecutor
/**
 * 抽象工厂
 */
public abstract class AbstractCommandExecutor implements CommandExecutor {


    private static final String CMD_TMB_TARGET = "?cmd=tmb&target=%s";
    private Map<String, Object> map = new HashMap<>();

    @Override
    public void execute(CommandExectionContext ctx) throws Exception {
        FsService fileService = ctx.getFsServiceFactory().getFileService(ctx.getRequest(),ctx.getServletContext());

        execute(fileService,ctx.getRequest(),ctx.getResponse(),ctx.getServletContext());
    }

    public abstract void execute(FsService fileService, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext)throws  Exception;

-------------------------
AbstractorJsonCommandExecutor

/**
 * 抽象工厂装饰类
 */
public abstract class AbstractorJsonCommandExecutor extends AbstractCommandExecutor {
    @Override
    final public void execute(FsService fsService, HttpServletRequest request, HttpServletResponse response,
                              ServletContext servletContext) throws Exception {

        JSONObject json = new JSONObject();

        try {
            execute(fsService, request, servletContext, json);
        } catch (ErrorException e) {
            /**
             * 自定义异常处理
             */
            if (e.getArgs() == null || e.getArgs().length == 0)
            {
                json.put("error", e.getError());
            } else
                {
                JSONArray errors = new JSONArray();
                errors.put(e.getError());
                for (String s : e.getArgs()) {
                    errors.put(s);
                }
                json.put("error", errors);
            }
        } catch (Exception e) {
            json.put("error", e.getMessage());
        } finally {
            response.setContentType("text/html;charset= UTF-8");

            PrintWriter writer = response.getWriter();
            json.write(writer);
            System.out.println(json);
            writer.flush();
            writer.close();
        }

    }

    protected abstract void execute(FsService fsService, HttpServletRequest request,
                                    ServletContext servletContext, JSONObject json) throws Exception;
}
DefaultCommandExecutorFactory
反射实现

public class DefaultCommandExecutorFactory implements CommandExecutorFactory {

    String _classNamePattern;

    private Map<String,CommandExecutor>_map= new HashMap<String,CommandExecutor>();

    private CommandExecutor _fallbackCommand;

    @Override
    public CommandExecutor get(String commandName) {

        if (_map.containsKey(commandName)){
            return _map.get(commandName);
        }

        try {
            String className = String.format(_classNamePattern,commandName.
                    substring(0,1).toUpperCase()+commandName.substring(1));
            return (CommandExecutor) Class.forName(className).newInstance();

        } catch (Exception e) {
            return _fallbackCommand;
        }

    }
OpenCommandExecutor

具体执行器
public class OpenCommandExecutor extends AbstractorJsonCommandExecutor
    implements CommandExecutor{
    @Override
    protected void execute(FsService fsService, HttpServletRequest request,
                           ServletContext servletContext, JSONObject json) throws Exception
    {
        boolean init = request.getParameter(ElFinderConstants.ELFINDER_PARAMETER_INIT) !=null;
        boolean tree = request.getParameter(ElFinderConstants.ELFINDER_PARAMETER_TREE) !=null;
        String target = request.getParameter(ElFinderConstants.ELFINDER_PARAMETER_TARGET);

        Map<String ,TargetEx> files= new LinkedHashMap<String, TargetEx>();
        if (init){
            json.put(ElFinderConstants.ELFINDER_PARAMETER_API,2.1);
            json.put(ElFinderConstants.ELFINDER_PARAMETER_NETDRIVERS,new Object[0]);
        }
        if (tree){
            for (Volume v : fsService.getVolumes()) {
                TargetEx root = new TargetEx(v.getRoot(), fsService);
                files.put(root.getHash(),root);
                addSubFolders(files,root);
            }
        }

        TargetEx cwd = finderCwd(fsService, target);
        files.put(cwd.getHash(),cwd);
        addChildren(files,cwd);

        json.put(ElFinderConstants.ELFINDER_PARAMETER_FILES,buildJsonFilesArray(request,files.values()));
        json.put(ElFinderConstants.ELFINDER_PARAMETER_CWD,getTargetInfo(request,cwd));
        json.put(ElFinderConstants.ELFINDER_PARAMETER_OPTIONS,getOptions(cwd));

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章