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

前言html

    你们都知道springMVC的使用,咱们会少些不少servlet层面的代码,可是随着controller使用多了,就会咱们的代码上多出许多RequestMapping注解,前端

  举个例子java

    一个web文件管理的例子,用户须要这个目录的全部文件,请求到了一个RequestMapping方法,这时咱们使用一个类来处理这个这个目录下面的全部文件信息,git

咱们须要返回每一个文件的详细信息,这时若是使用RequestMapping方法就显得有些鸡肋了github

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

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

一、须要一个只须要实例化一次的json对象方法,二、尽可能少些RequestMappingspring

 

下面咱们先解决第二种问题json

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

具体实现方法如何实现呢app

嗯,上代码

例如

这个是它的一个接口

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));

    }
}
相关文章
相关标签/搜索