zoukankan      html  css  js  c++  java
  • 如何构建基于微内核的插件系统(一)

    最近,一直在看.NET版本的开源IDE——SharpDevelop,由几位国外高人编写,第一次接触这么复杂的插件系统,着实感觉无从下手,于是从网上收集了一些有关解读、分析源码的文章,可就是因为太少了,自己只能感悟一点。Eclipse是非常出色的一款Java的开源IDE环境,自然也少不了去了解一下,也大概了解了一下Eclipse的插件系统原理,设计上主要是采用了“微内核+插件”的开发模式。网上有解,关于微内核、巨内核的说法,当然各有优缺点了。SharpDevelop,初看了一下,给人的感觉应该是巨内核的那种,插件的组装全部由系统完成,而不是将任务分发到子插件上的。

    为何要提出插件系统?首先,该系统主要是针对提高桌面应用程序的扩展性而提出的;而Web网站本身在设计上就是插件化的,通过用户请求页面,相应调用对应的处理类(就是Page类)进行处理。Web网站,通过增加页面和页面对应的处理类,来实现系统扩展。新添加的页面、对应处理类打包成动态库,这些也正是桌面应用程序所不具备的特点(必须改动原有的项目),这是不利于日后的修改、新增和移除功能的操作,且容易造成影响其他正常模块的正常运行。而插件系统,一旦新增的模块造成系统问题,可以通过移除新模块来快速解决这个问题。虽然Web网站本身是插件化的,但在实际项目开发中,往往有时候把新开发的模块放在已经发布的系统中,源码、页面,生成的动态库都放在一起。一旦新旧项目并行开发,由于各组开发人员的源码的不一致或发布时候的原因,导致已经上线的系统的其它模块出错,那后果不堪设想。所以规范Web开发也是一项重要内容,但这个不在本文讨论的范围内,以后会写一些。

    说了一大堆废话,现在言归正传,我先谈谈我对插件系统的理解。打个比方,在菜市场上,菜场的管理人员把菜场大致分了个类,有肉类的、蛋类、蔬菜类、鱼类和水果类,这些就是插件系统中的几个扩展点(Extension)。卖家(插件)带了些蛋、蔬菜,去这个菜场来卖。TA把鸭蛋放在了蛋类的摊位上,把菠菜、青菜放在了蔬菜的摊位上,这样,买家(插件系统内部的调用者)就可以根据分类来找到所需要的了。按实际实现的UI界面元素,来设计主要的几个扩展点,大家都知道,系统与用户进行交互,是通过鼠标点击或键盘的敲击来完成的,也可以说是GUI元素上的事件来驱动的,譬如,菜单上的点击、鼠标右键、按钮的点击等来驱动。我们可以把整个桌面应用程序的GUI界面称之为“工作台(Workbench)”,所有的GUI元素都是在这个上面,大致可分为以下几类:主菜单(MainMenu)、工具栏(Toolbar)、文档选项卡(DocumentTab)、可停靠选项卡(DockingTab)、文件选项卡(OpenFileTab)和状态栏(Statusbar)。还是回到之前菜市场的那个比方中,菜市场管理人员可以提供电子称给需要称的卖家(这种行为就是一种服务形式),并要求卖家签订借用条款(调用服务的接口)。这样,买家买东西时,就可以根据称重和单价来付钱了。有特殊需要就要提供特别的方法,有个卖家,TA发现在这个摊位上特别好卖,所以TA就天天第一个来到菜市场来占用这个摊位了。所以,扩展点除了“工作台(Workbench)”,还需要“服务(Services)”和“自动运行(Autorun)”。插件系统启动时,先初始化“服务(Services)”,然后执行“自动运行(Autorun)”,再将“工作台(Workbench)”下的GUI元素创建出来。通过对GUI元素上的点击事件,相应的执行GUI元素对应的“命令(Command)”对象的“运行(Run)”方法,从而响应鼠标、键盘事件。

    插件系统的扩展点可以以路径形式挂载到插件树中,根路径为“/”,像之前提到的扩展点,可以记作“/SharpDevelop/Workbench/MainMenu”、“/SharpDevelop/Services”。如果需要添加一级菜单,譬如是“工具(Tool)”,那么在插件配置中可以这么设置。

    <Plugin>
        <Manifest>
            <Identity name="ICSharp.SharpDevelop.OptionDialog" />
        </Manifest>
        <Runtime>
            <Import assembly=":ICSharp.SharpDevelop" />
        </Runtime>
        <Extension path="/SharpDevelop/Workbench/MainMenu/">
            <MenuItem id="Tool" label="工具">
                <MenuItem id="Options" label="选项" class="ICSharp.SharpDevelop.MainMenu.Tool.OptionsCommand" />
            </MenuItem>
        </Extension>
    </Plugin>

    在Extension下的节点,称之为“代码子(Codon)”,大家都这么翻译,我也不理解为什么这么起名,总之,挂载到扩展点下的就是Codon。一个Codon可以对应一个或零个Command。“MenuItem”就是类型为“MenuItem”的“Codon”。如上边那个插件配置,那个“选项”菜单的Codon,通过用户点击触发事件,从而执行“ICSharp.SharpDevelop.MainMenu.Tool.OptionsCommand”类实例的“Run”方法。Codon的类型有“MenuItem”、“Class”等等,可以根据不同类型的Codon,来编写特殊的抽象类,来提供特殊的功能,如“MenuItem”,可以写一个对应的Command抽象类“AbstractMenuCommand”。

    上边简单描述了插件是如何实现扩展功能的,后边我会继续分析插件系统,有关如何加载以及延迟加载的概念。

  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/Berkaroad/p/1778173.html
Copyright © 2011-2022 走看看