zoukankan      html  css  js  c++  java
  • 利用策略模式与退化的建造模式实现减少工作量的方法

    前言

        大家都知道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));
    
        }
    }
  • 相关阅读:
    postgresql获取随机数
    windows环境中Tomcat实现开机自启动
    让Tomcat支持中文路径名和中文文件名
    CentOS 环境变量编辑、保存、立即生效的方法
    eclipse/intellij idea 远程调试hadoop 2.6.0
    利用Spring的@Async异步处理改善web应用中耗时操作的用户体验
    ssh 免密码设置失败原因总结
    hadoop 2.6伪分布安装
    weblogic.nodemanager.common.ConfigException: Native version is enabled but nodemanager native library could not be loaded 解决办法
    velocity模板引擎学习(3)-异常处理
  • 原文地址:https://www.cnblogs.com/dmeck/p/8734136.html
Copyright © 2011-2022 走看看