zoukankan      html  css  js  c++  java
  • 《设计模式之禅》--MVC框架

    需求:设计一个MVC框架

    (以下可能摘要不全,后期整理)

    架构图:

    * 核心控制器:MVC框架入口,负责接收和反馈HTTP请求

    * 过滤器:Servlet容器内的过滤器,实现对数据的过滤处理

    * 拦截器:对进出模型的数据进行过滤,不依赖系统容器,只过滤MVC框架内的业务数据

    * 模型管理器:提供一个模型框架,内部所有业务操作应该无状态,不关心容器对象

    * 视图管理器:管理所有的视图

    * 辅助工具:比如文件管理、对象管理

    【核心控制器】

    public class FilterDispatcher implements Filter {
        //定义一个值栈辅助类
        private ValueStackHelper valueStackHelper = new ValueStackHelper();
        //应用IActionDispatcher
        IActionDispather actionDispatcher = new ActionDispatcher();
    
        //servlet销毁时要做的事情
        public void destroy() {
        }
    
        //过滤器必须实现的方法
        public void doFilter(ServletRequest request, ServletResponse response,
                             FilterChain chain) throws IOException, ServletException {
            //转换为HttpServletRequest
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            //传递到其他过滤器处理
            chain.doFilter(req, res);
            //获得从HTTP请求的ACTION名称
            String actionName = getActionNameFromURI(req);
            //对ViewManager的应用
            ViewManager viewManager = new ViewManager(actionName);
            //所有参数放入值栈
            ValueStack valueStack = valueStackHelper.putIntoStack(req);
            //把所有的请求传递给ActionDispatcher处理
            String result = actionDispatcher.actionInvoke(actionName);
            String viewPath = viewManager.getViewPath(result);
            //直接转向
            RequestDispatcher rd = req.getRequestDispatcher(viewPath);
            rd.forward(req, res);
        }
    
        public void init(FilterConfig arg0) throws ServletException {
        /*
        * 1、检查XML配置文件是否正确
        * 2、启动监控程序,观察配置文件是否正确
        */
        }
    
        //通过url获得actionName
        private String getActionNameFromURI(HttpServletRequest req) {
            String path = (String) req.getRequestURI();
            String actionName = path.substring(path.lastIndexOf("/") + 1,
                    path.lastIndexOf("."));
            return actionName;
        }
    }

    核心控制器的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app>
      <filter>
        <display-name>FilterDispatcher</display-name>
        <filter-name>FilterDispatcher</filter-name>
        <filter-class>{包名}.FilterDispatcher</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>FilterDispatcher</filter-name>
        <url-pattern>*.do</url-pattern>
      </filter-mapping>
    </web-app>
    <?xml version="1.0" encoding="UTF-8"?>
    <mvc>
    <action name="loginAction" class="{类名全路径}" method="execute">
    <result name="success">/index2.jsp</result>
    <result name="fail">/index.jsp</result>
    </action>
    </mvc>

    框架逻辑校验

    public class LogicXmlValidate implements IXmlValidate {
        //检查xmlPath是否符合逻辑,比如不会出现一个类中没有的方法
        public boolean validate(String xmlPath) {
            return false;
        }
    }

    逻辑校验流程:

    1)读取XML文件

    2)使用反射技术初始化一个对象(配置文件中的class属性值)

    3)检查是否存在配置文件中配置的方法

    4)检查方法的返回值是否是String,并且无输入参数,同时必须继承指定类或接口

    策略场景类

    public class Checker {
        //使用哪一个策略
        private IXmlValidate validate;
        //xml配置文件的路径
        String xmlPath;
    
        //构造函数传递
        public Checker(IXmlValidate _validate) {
            this.validate = _validate;
        }
    
        public void setXmlPath(String _xmlPath) {
            this.xmlPath = _xmlPath;
        }
    
        //检查
        public boolean check() {
            return validate.validate(xmlPath);
        }
    }

    监听接口

    public interface Watchable {
        //监听
        public void watch();
    }

    文件监听者

    public class FileWatcher extends Observable implements Watchable {
        //是否要重新加载XML文件
        private boolean isReload = false;
    
        //启动监视
        public void watch() {
            //启动一个线程,每隔15秒扫描一下文件,发现文件日期被修改,立刻通知观察者
            super.addObserver(new Checker());
            super.setChanged();
            super.notifyObservers(isReload);
        }
    }

    修正后的检查者

    public class Checker implements Observer {
        public void update(Observable arg0, Object arg1) {
            //检查是否符合条件
            arg1 = check();
        }
    }

    【模型管理器】

    public interface IActionDispather {
        //根据Action的名字,返回处理结果
        public String actionInvoke(String actionName);
    }
    public class ActionDispather implements IActionDispather {
        //需要执行的Action
        private ActionManager actionManager = new ActionManager();
        //拦截器链
        private ArrayList<Interceptors> listInterceptors = InterceptorFactory.createInterceptors();
    
        public String actionInvoke(String actionName) {
            //前置拦截器
            return actionManager.execAction(actionName);
            //后置拦截器
        }
    }
    public abstract class ActionSupport {
        public final static String SUCCESS = "success";
        public final static String FAIL = "fail";
    
        //默认的执行方法
        public String execute() {
            return SUCCESS;
        }
    }

     

    public class ActionManager {
        //执行Action的指定方法
        public String execAction(String actionName) {
            return null;
        }
    }
    public abstract class AbstractInterceptor {
        //获得当前的值栈
        private ValueStack valueStack = ValueStackHelper.getValueStack();
        //拦截器类型:前置、后置、环绕
        private int type = 0;
    
        //当前的值栈
        protected ValueStack getValueStack() {
            return valueStack;
        }
    
        //拦截处理
        public final void exec() {
            //根据type不同,处理方式也不同
        }
    
        //拦截器类型
        protected abstract void setType(int type);
    
        //子类实现的拦截器
        protected abstract void intercept();
    }
    public class Interceptors implements Iterable<AbstractInterceptor> {
        //根据拦截器列表建立一个拦截器链
        public Interceptors(ArrayList<AbstractInterceptor> list) {
        }
    
        //列出所有的拦截器
        public Iterator<AbstractInterceptor> iterator() {
            return null;
        }
    
        //拦截器链的执行方法
        public void intercept() {
            //委托拦截器执行
        }
    }
    public class InterceptorFactory {
        public static ArrayList<Interceptors> createInterceptors() {
            //根据配置文件创建出所有的拦截器链
            return null;
        }
    }

    【视图管理器】

    public class GBLangData extends AbsLangData {
        @Override
        public Map<String, String> getItems() {
        /*
        * Map 的结构为:
        * key='title', value='标题'
        * key='menu', value='菜单'
        */
            return null;
        }
    }
    
    public class ENLangData extends AbsLangData {
        @Override
        public Map<String, String> getItems() {
        /*
        * Map结构为:
        * key='title',value='title';
        * key='menu', value='menu'
        */
            return null;
        }
    }
    public abstract class AbsView {
        private AbsLangData langData;
    
        //必须有一个语言文件
        public AbsView(AbsLangData _langData) {
            this.langData = _langData;
        }
    
        //获得当前的语言
        public AbsLangData getLangData() {
            return langData;
        }
    
        //页面的URL路径
        public String getURI() {
            return null;
        }
    
        //组装一个页面
        public abstract void assemble();
    }
    public class JspView extends AbsView {
        //传递语言配置
        public JspView(AbsLangData _langData) {
            super(_langData);
        }
    
        @Override
        public void assemble() {
            Map<String, String> langMap = getLangData().getItems();
            for (String key : langMap.keySet()) {
        /*
        * 直接替换文件中的语言条目
        *
        */
            }
        }
    }
    public class SwfView extends AbsView {
        public SwfView(AbsLangData _langData) {
            super(_langData);
        }
    
        @Override
        public void assemble() {
            Map<String, String> langMap = getLangData().getItems();
            for (String key : langMap.keySet()) {
        /*
        * 组装一个HTTP的请求格式:
        * http://abc.com/xxx.swf?key1=value&key2=value
        */
            }
        }
    }
    public class ViewManager {
        //Action的名称
        private String actionName;
        //当前的值栈
        private ValueStack valueStack = ValueStackHelper.getValueStack();
    
        //接收一个ActionName
        public ViewManager(String _actionName) {
            this.actionName = _actionName;
        }
    
        //根据模型的返回结果提供视图
        public String getViewPath(String result) {
            //根据值栈查找到需要提供的语言
            AbsLangData langData = new GBLangData();
            //根据action和result查找到指定的视图,并加载语言
            AbsView view = new JspView(langData);
            //返回视图的地址
            return view.getURI();
        }
    }

    【工具类】

    <action name="loginAction" class="{类名全路径}" method="execute">
      <result name="success">/index2.jsp</result>
      <result name="fail">/index.jsp</result>
    </action>
    public abstract class ActionNode {
        //Action的名称
        private String actionName;
        //Action的类名
        private String actionClass;
        //方法名,默认是execute
        private String methodName = "excuete";
        //视图路径
        private String view;
    
        public String getActionName() {
            return actionName;
        }
    
        public String getActionClass() {
            return actionClass;
        }
    
        public String getMethodName() {
            return methodName;
        }
    
        public abstract String getView(String Result);
    }
    public class XmlActionNode extends ActionNode {
        //需要转换的element
        private Element el;
    
        //通过构造函数传递
        public XmlActionNode(Element _el) {
            this.el = _el;
        }
    
        @Override
        public String getActionName() {
            return getAttValue("name");
        }
    
        @Override
        public String getActionClass() {
            return getAttValue("class");
        }
    
        @Override
        public String getMethodName() {
            return getAttValue("method");
        }
    
        public String getView(String result) {
            ViewPathVisitor visitor = new ViewPathVisitor("success");
            el.accept(visitor);
            return visitor.getViewPath();
        }
    
        //获得指定属性值
        private String getAttValue(String attName) {
            Attribute att = el.attribute(attName);
            return att.getText();
        }
    }
    public class ViewPathVisitor extends VisitorSupport {
        //获得指定的路径
        private String viewPath;
        private String result;
    
        //传递模型结果
        public ViewPathVisitor(String _result) {
            result = _result;
        }
    
        @Override
        public void visit(Element el) {
            Attribute att = el.attribute("name");
            if (att != null) {
                if (att.getName().equals("name") && att.getText().equals(result)) {
                    viewPath = el.getText();
                }
            }
        }
    
        public String getViewPath() {
            return viewPath;
        }
    }

    MVC用到了哪些框架:

    ● 工厂方法模式:通过工厂方法模式把所有的拦截器链实现出来,方便在系统初始化时直接处理。

    ● 单例模式:Action的默认配置都是单例模式,在一般的应用中单例已经足够了,在复杂情况下可以使用享元模式提供应用性能,减少单例模式的性能隐患。

    ● 责任链模式:建立拦截器链以及过滤器链,实现任务的链条化处理。

    ● 迭代器模式:非常方便地遍历拦截器链内的拦截器,而不用再自己写遍历拦截器链的方法。

    ● 中介者模式:以核心控制器为核心,其他同事类都负责为核心控制器“打工”,保证核心控制器瘦小、稳定。

    ● 观察者模式:配置文件修改时,不用重启应用可以即刻生效,提供使用者的体验。

    ● 桥梁模式:使不同的视图配合不同的语言文件,为终端用户展示不同的界面。

    ● 策略模式:对XML文件的检查可以使用两种不同的策略,而且可以在测试机和开发机中使用不同的检查策略,方便系统间自由切换。

    ● 访问者模式:在解析XML文件时,使用访问者非常方便地访问到需要的对象。

    ● 适配器模式:把一个开发者不熟悉的对象转换为熟悉的对象,避免工具或框架对开发者的影响。

    ● 门面模式:Action分发器负责所有的Action的分发工作,它提供了一个调用Action的唯一入口,避免外部模块深入到模型模块内部。

    ● 代理模式:大量使用动态代理,确保了框架的智能化。

  • 相关阅读:
    std::bind常见的坑
    valgrind使用指南
    Makefile (1) gcc基础
    准备篇(三)Makefile
    win10激活
    C语言结构体篇 结构体
    C语言字符篇(五)内存函数
    C语言字符篇(四)字符串查找函数
    C语言字符篇(三)字符串比较函数
    C语言字符篇(二)字符串处理函数
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/8447983.html
Copyright © 2011-2022 走看看