`

系统的扩展性(怎么设计插件)

阅读更多
本文谈下我个人对“系统的扩展性”的看法

首先需要声明,这里的扩展性不是指伸缩性(scalability),而是指灵活性(flexibility)

一、名词解释

这里有2个关键词,一个是系统,一个是扩展性

那么要说明这个主题,就先要解释一下这2个关键词。按照我的习惯,还是从最小的东西开始举例子

“系统”,我认为就是三要素,输入,逻辑,输出。按照这个定义,最小的系统就是一个方法
public String sayHi(String name){
    return "hi "+ name;
}

我认为这个方法就是一个系统,输入是name,逻辑是加上一个"hi ",输出也是一个字符串

这三要素可以为空,比如有无参数的方法,无返回值的方法,或者没有业务逻辑的方法。。在极端情况下,甚至可以三要素都为空,不过就不具现实意义了
public void doNothing(){
}

这个方法没有意义,不过不可否认它也是符合语法的,也有三要素,只不过都为空而已,所以我认为这个也可以算一个系统

因此,从方法往上延伸,类和模块也是系统;淘宝商城,去掉展现层,也是系统;常用的spring,一般认为是个框架,不过其实它也是系统;tomcat是一个servlet容器,但是它也是系统

下面解释我理解的扩展性。这个词我给不出精确的定义,所以只能用大白话加例子来说明。我认为扩展性就是“可变化”,或者说“没写死”

比如说这个方法,我认为没有扩展性
public void sayHi(){
    System.out.println("hi kyfxbl");
}

不管怎么调用,它也只能在屏幕上打出hi kyfxbl这句话,所以是“不可变”的,“写死了”,没有扩展性
加一个参数,就有扩展性了
public void sayHi(String name){
    System.out.println("hi " + name);
}

这个方法根据被调用时接受参数的不同,会呈现出不同的结果,就有扩展性了。结合第一点说的,方法也是系统,那么可以认为,这个方法,是一个最小的“有扩展性的系统”

二、系统即容器

上面为了解释清楚“系统”和“扩展性”的意思,选了很极端的例子,没有什么实际意义。现在就回到常见的场景中

还是以tomcat来举例子,tomcat作为一个servlet容器,也是一个运行的系统,而且是一个扩展性非常强的系统

当tomcat启动并加载一个web app的时候,它并不知道这个web app有哪些servlet规范规定的组件。有多少个Servlet呢,有没有Listener呢,都不清楚

但是当它启动web app初始化流程的时候,它就找到ContextListener的组件,然后实例化,再调用生命周期方法。所以如果我们的web app应用没有ContextListener,那么就不会执行;如果有一个,就执行一个;如果有两个,就执行两个……

这种感觉就像是,我们在给tomcat写插件一样,或者说我们在根据servlet规范的要求,写一些组件,然后放到servlet容器里运行起来

再举一个spring的例子,spring是常见框架,并且也是一个扩展性很强的系统。大部分情况下,我们只是使用spring提供的功能,比较少会去扩展它。但是实际上是可以扩展的。比如在ApplicationContext初始化的过程中,它会去调用PostBeanDefinitionProcess,PostBeanDefinitionProcess是一个接口,我们完全可以自己增加一个自定义的PostBeanDefinitionProcess实现类,放到配置文件里,那么也就会被spring给执行了

这种情况下,spring的各个组件实际上都是在spring这个容器中运行的。spring容器本身运行的流程,是spring设计者规定的(相当于servlet的规范)。同时,设计者在流程中预先就保留了一些扩展点,等着后来的人(spring的用户)去自行扩展

因此,spring能不能扩展,能在哪些环节被扩展,是在设计的时候就决定的。试想如果rod johnson在一开始,就没有设计查找并执行PostBeanDefinitionProcess这个环节,那我们就不能在这个环节上对spring系统进行扩展了

日常我们写的系统,也是这样。以后能不能扩展,在哪里扩展,怎么扩展,都是在设计的时候就决定的。如果系统中,某个环节调用某个组件,都被固定下来,是“写死的”,那么这个环节就不具扩展性了。当然这个时候,系统依然是容器,只是容器中的组件是不可变的

三、接口即设计

因此,为什么说接口就是设计呢,我认为就在这里。以前另外一篇博客,也谈到过接口的作用。当时我说的是,接口可以使两个模块之间的依赖减小。比如模块A依赖模块B,但是A只依赖B中的一个接口,那么不管模块B的内部实现怎么变,只要这个接口是稳定的,对A就没有影响

这里要说到接口的第二个作用,就是它关系到系统的扩展性。拿一段代码举例子:
public void process(){
    ComponentA a = new ComponentA();
    a.doProcess();
}

这个方法就没有扩展性了,因为不管在任何情况下,调用process()方法,执行序列都是一样的。要想改变它,除非拿到源码,把ComponentA的实现改掉。当然在实际中,这是不可能的

那么如果是这样写
public void process(){
    Component a = searchForComponent();
    a.doProcess();
}

searchForComponent()方法的逻辑,是从配置文件里找到一个Component接口的实现类,实例化并返回,那么这个方法就很有扩展性了

随时都可以自行实现一个实现Component接口的实现类,比如MySpecialComponent,放到配置文件里。那么这个方法运行时的逻辑,就完全是灵活的了

接口Component在这里,就是充当了一个占位符的作用,但同时又把整体的流程确定了下来,先找到实例-->调用实例的方法。我们可以随意扩展Component,但是这个整体的流程却是不会改变的

联系上面的内容,这个process()方法(系统),也是一个容器。Component就是它的组件,是不确定的

想想前面举的tomcat和spring的例子,它们之所以有扩展性,就是因为容器本身的代码,用的是接口(ContextListener和PostBeanDefinitionProcess)来占位,而没有用实际的类把逻辑“写死”。但是整体的流程,是固定下来的

这里就体现了接口,对于设计的意义

四、可扩展性的要素

总结上面的例子,一个系统是否具有扩展性,是在设计之初就固定下来的。

那么系统要有扩展性,就至少需要3个要素:

1、在规定了流程的前提下,允许某些环节扩展
2、将允许扩展的部分,以API的方式对外部提供
3、对外部提供规则

第1条前面已经说了很多了,第2条和第3条也很简单

servlet和spring是可以扩展的,但是如果没有拿到ContextListener和PostBeanDefinitionProcess这2个接口,又怎么能写出实现类呢。那也就只能看着系统运行默认组件了

但是提供API,不需要把整个系统的接口都暴露出去,提供必需的子集即可。比如只需要有servlet-api.jar,就可以开发servlet应用了,并不需要拿到catalina.jar。tomcat的源码里,大部分都是容器自身的实现,允许扩展的部分,仅仅通过servlet-api.jar来提供就足够了

对外部提供规则,就是告诉外部要怎么扩展。容器是别人设计的,用户怎么知道要怎么扩展呢?当然就需要容器的设计者来提供信息。告诉用户,你可以实现ContextListener接口,然后在web.xml里配置一下……

五、所谓的插件

写本文的原因,其实是最近在分析一个系统。这两天在研究它的插件体系,想到这么多就写下来

搞清楚上面的内容,插件也就不复杂了

从用户的角度来看,要写一个插件,就是拿到API,然后按照规则写扩展组件

从系统(容器)设计者的角度看,我的系统要支持插件扩展,就是:

1、规定流程,设计扩展点(包括加载机制)
2、把扩展点打包成API,作为二次开发的SDK提供给用户
3、告诉用户,应该怎么使用这个API

好吧,其实第5点才是我想总结的,前面的4点只是胡思乱想
分享到:
评论

相关推荐

    Spring-Boot插件式开发框架,为动态扩展系统而生的插件开发框架

    - **可扩展性**:插件化设计使得系统能够轻松添加新功能,且不影响现有功能的稳定性。 - **可维护性**:每个插件独立,方便定位和修复问题,降低维护成本。 - **敏捷开发**:开发者可以快速迭代和发布插件,适应...

    插件模式系统设计

    这种方式极大地提高了软件的可扩展性和灵活性,降低了维护成本。 系统框架在插件模式中的角色至关重要。一个良好的插件系统框架应该提供以下关键组件: 1. **插件接口**:这是定义插件行为和交互的标准。所有插件...

    IE扩展插件订餐系统

    【IE扩展插件订餐系统】是一个专为IE浏览器设计的辅助工具,它通过扩展功能增强了用户在特定网站上的订餐体验。这个插件的核心特性是实现一键登录,让用户能够快速方便地进入指定的订餐网站,并进行相关操作,如浏览...

    Microserver是Spring和SpringBoot一个方便可扩展的微服务插件系统

    Microserver是一款专为Spring和Spring Boot设计的微服务插件框架,它提供了丰富的功能和高度的可扩展性,使得在构建分布式系统时更加便捷。这款框架的核心目标是简化微服务的开发过程,同时允许开发者根据需求自定义...

    右键扩展功能插件 (显示隐藏系统文件+扩展名)

    在计算机使用过程中,有时我们需要查看或...安装和使用这类插件需要注意的是,虽然它们增强了系统的可操作性,但也可能增加了暴露系统敏感信息的风险,因此在操作时要确保清楚自己的操作意图,避免误操作导致系统问题。

    C# 插件结构设计 C# 插件结构设计

    这种架构允许程序的核心部分与可扩展的功能模块(即插件)分离,从而提高了软件的灵活性、可维护性和可扩展性。下面将详细讨论C#插件架构的相关知识点。 1. **插件的基本概念** 插件是一种软件组件,它能够增强或...

    SHOPEX-扩展属性多选插件

    标题中的“SHOPEX-扩展属性多选插件”是指一种专为SHOPEX电子商务平台设计的扩展功能插件。SHOPEX是一款基于PHP和MySQL开发的开源网上商店管理系统,它允许商家建立自己的在线商店。这个插件的核心功能是提供商品多...

    C# 构建可扩展的应用程序(插件)

    插件架构是一种实现可扩展性的方式,它允许程序在运行时动态加载新的功能或组件,而无需重新编译整个应用程序。本篇文章将深入探讨C#中如何利用插件技术构建可扩展的应用程序。 首先,我们要理解什么是插件。插件...

    软件工程中的可扩展性与维护性设计.pptx

    - **可扩展性设计原则** - **模块化设计**:将系统拆分为独立的模块,模块之间耦合度低。 - **高内聚**:模块内部功能高度相关,功能单一。 - **松耦合**:模块之间的依赖关系简单,一个模块的改动不会对其他模块...

    易语言插件系统演示

    本主题“易语言插件系统演示”将深入探讨如何使用易语言来构建一个插件系统,这样的系统能显著提升程序的可扩展性和灵活性。 首先,插件系统的核心是模块化设计。在易语言中,我们可以通过定义接口或者类来规范插件...

    操作系统课程设计-程序插件

    这种模块化的设计使得软件具有高度的可扩展性和灵活性,用户可以根据需要选择安装或卸载特定的插件,以定制自己的软件环境。 在操作系统中,程序插件的应用非常广泛。例如,在浏览器中,我们经常使用各种插件来实现...

    .NET插件系统开发架构资料

    .NET插件系统开发架构是一种灵活的设计模式,它允许在运行时动态加载和卸载功能模块,从而提高了软件的可扩展性和可维护性。在本文中,我们将深入探讨.NET插件系统开发的关键概念、架构设计以及如何利用C#语言实现。...

    基于插件技术毕业设计

    学习这个项目,你可以了解到如何创建插件接口、编写插件实现、设计插件加载器以及如何在应用程序中管理和调用插件。此外,通过阅读源码,还可以深入理解.NET框架下的编程实践,提升你的软件开发技能。

    插件程序设计

    这允许用户在不重启或修改主程序的情况下添加、更新或移除插件,提高了系统的可扩展性和维护性。 4. **接口与协议**: 插件和主程序间的通信基于特定的接口或协议。这些接口定义了插件如何暴露其功能,以及主程序...

    插件系统简单描述

    ### 插件系统简述及关键技术点 #### 插件系统概述 插件系统是一种软件设计模式,允许软件开发者在不修改主...对于希望开发具有高度可扩展性的软件项目的开发者来说,本插件系统的架构提供了一种值得借鉴的设计模式。

    unity天气系统插件

    总之,Unity天气系统插件是游戏开发中一个强大的辅助工具,它简化了天气效果的创建过程,同时也为开发者提供了足够的灵活性和扩展性,以便于构建更加生动、多变的游戏世界。通过深入学习和实践,开发者可以充分利用...

    基于.NET 平台的插件式系统开发

    这种插件式的设计极大地提高了系统的可维护性和扩展性。 #### 结论 插件式开发方法通过将可变的部分抽象为独立的插件,使得软件系统能够在运行时根据需求动态加载这些插件,从而实现了系统的高度灵活性和可扩展性...

    KX全系统的插件

    这些插件可能是由KX官方开发,也可能是由第三方开发者贡献,它们共同构成了KX系统强大的可扩展性。 在压缩包中,我们看到只有一个名为"插件包"的文件,这可能是一个集合文件,包含了所有插件。通常,这样的文件会...

Global site tag (gtag.js) - Google Analytics