Ruby's Louvre

每天学习一点点算法

导航

newland.js的Ioc实现

newland.js之所以是框架而不是类库,最重要的原因是它只要几步就能建立起一个网站!换言之,它已经包含了网站从启动到运行的重要流程,至于你还需要什么,是制定还是完善等等不确定的东西,框架已经预留了位置给你填空了。


框架让程序员变成流水线上的工人这一事实是不可逆转的,唯一的区别的有的流水线非常智能,让你过得非常惬意,有的则非常恶心,让你变成苦逼的码畜!


JAVA的三大框架之一,Spring最伟大的举措就是发明了IoC容器。是的,框架帮你做了许多事,但有些文件还是要你去建的,建在指定的目录下;有些代码你还要去写,依照规定好的格式,是建哪个类,继承哪个父类,差一步也不行。框架带来便捷的同时,也带来的枷锁!IoC的目的是让这些痛苦减少些!


首先抄一段话解释什么叫IoC——“在依赖注入的模式下,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由容器来完成,然后注入给调用者,因此也称为依赖注入”。


在我的newland.js框架中,最开始的mass.js模块其实只是提供模块加载机制与一些通用方法,不干正事的,它唯一做的有意义的是调用了mvc这个模块。

 $.require("system/deploy,system/mvc", function(deploy){
        deploy(  process.cwd() );//监听app目录下文件的变化,实现热启动
    });

mvc模块的作用是启动服用器,接受请求!在此之前,它会读取配置文件,把用户指定的拦截器与默认拦截器与所有控制器统统读入内存,装配到系统中!


所谓的栏截器其实就是structs那套东西,不认识JAVA的同学如果懂node.js,就去看看connectjs的中间件,差不多就是这个意思,用于处理请求与响应用的工具包。


而控制器是重点,MVC不能没有它。一个控制器有许多功能,因此我们把共用的功能抽取出来构建成基类, 而我们所建的控制器作为子类继承它就可以节约许多代码。

//遍历app/controllers目录下所有控制器模块,并与拦载器模块一起加载它们!
$.walk("app/controllers", function(files){
        $.require( inter.concat( files ), function(){
            //拦截器放在最前面
            var intercepters = [].slice.call(arguments,0, inter.length);
            resource_ready( intercepters )
        });
    });

在没有用IoC之前,我们的控制器是这个样子的:

.define("doc_controller",function(){
    var klass = $.factory({
        inherit: $.base_controller,
        index: function(flow){
            $.log("已进入doc#index action");
            flow.session.set("xxx","in doc")
            var view_url = $.path.join("app","views", flow.req.url );
            flow.fire("get_view", view_url, flow.req.url )
        }

    });
    $.controllers[ "doc"] = new klass
});

其实用户要写的就是index,show, edit, destroy这样action方法,其他部分就是死格式!什么指定父类,new实例其实交给系统去处理就行了!因此我们的自定义控制器可以削减成这样子!

$.define("doc_controller",function(){
    return {
        index: function(flow){
            $.log("已进入doc#index action");
            flow.session.set("xxx","in doc")
            var view_url = $.path.join("app","views", flow.req.url );
            flow.fire("get_view", view_url, flow.req.url )
        }
    }
});

那么子类的创建与继承关系的指定与实例的创建传到mvc.js中去管理:

   var rcname = /\/(\w+)_controller/;
    //遍历app/controllers目录下所有控制器模块,并与拦载器模块一起加载它们!
    $.walk("app/controllers", function(files){
        $.require( inter.concat( files ), function(){
            //取得放在前面的拦截器
            var intercepters = [].splice.call(arguments, 0, inter.length);
            //取得放在后面的控制器
            var controllers = arguments;
            //进行控制反转,构建我们所需要的控制器子类与它的实例
            files.forEach(function(el, i){
                //mac下的路径为     app/controllers/doc_controller.js
                //window下的路径为  app\\controllers\\doc_controller.js
                var match = el.replace(/\\/g,"/").match(rcname);
                var controller = controllers[i];
                controller.inherit =  $.base_controller
                var klass = $.factory(controller);
                $.controllers[ match[1] ] = new klass;
            });
            resource_ready( intercepters )
        });
    });

需要说明一下的是,newland.js分成两大块,app目录下的模块是用户自建的文件或系统指令下建立的模块(下称app模块),system目录下的模块则是辅助app模块运行用的。需要用户动手的app模块越简单就越好!任何复杂的类最好不要用,就算用都交由框架去处理,去new 实例;任何复杂的功能都做用钩子的形式,或通俗地说,是回调函数的形式,交由框架去调度;所有不确定的功能都做成自定义事件形式,由框架或框架的另外加载的模块去fire。诸如此类,所有耦合就松绑了,得以最大限度地适应需求的变化。

http://dotnetfresh.cnblogs.com/archive/2005/06/27/181878.html

posted on 2012-08-12 20:56  司徒正美  阅读(3355)  评论(3编辑  收藏  举报