码迷,mamicode.com
首页 > Web开发 > 详细

《设计模式之禅》--MVC框架

时间:2018-02-14 11:42:14      阅读:333      评论:0      收藏:0      [点我收藏+]

标签:isp   设计模式   actions   tin   abc   response   ide   values   设计模式之禅   

需求:设计一个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的唯一入口,避免外部模块深入到模型模块内部。

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

《设计模式之禅》--MVC框架

标签:isp   设计模式   actions   tin   abc   response   ide   values   设计模式之禅   

原文地址:https://www.cnblogs.com/anni-qianqian/p/8447983.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!