模块的封装性分析-读书笔记

引子

最近看《Java Application Architecture-Modularity Patterns with Examples Using OSGi-中文译名Java应用架构设计》时,在物理模块的封装设计方面深受启发。市面上很多书都是介绍类的封装、访问性控制、逻辑设计,但是关于物理模块的设计的书并不多见,这本书是这方面的好书,有Bob大叔推荐作序。同时此书推荐的一本老书《Large-Scale C++ Software Design》也是这方面的经典好书。就像这本书所说的缺乏物理设计的逻辑设计并不会带来预期的影响,深有同感。

问题描述

讨论一个和参考资料[1]中3.4节、[2]、[3]中描述的问题相同的简化问题。根据面向接口编程的理念,提供服务的模块只暴露服务接口,隐藏实现。客户端模块以接口访问服务端模块的服务。客户端模块中不能出现任何具体实现类的引用耦合。这样便于以后改变服务端模块实现的同时不影响客户端模块。我们希望具体实现类对客户端模块不可见。这样在提供服务端模块时强制以接口公开服务。

解决方法

[1]中采用Spring框架注入实现类,[3]中描述了采用ServiceLoader和META-INF注入实现类。以下以[2]中类似的代码为例介绍Java的方法,此处没有采用框架,仅仅是用了一个简单的工厂控制实现类的注入。并和.NET的解决方法对比。这里采用参考资料[1]中的模块定义,Java定义jar文件为物理模块单元,.NET定义程序集dll文件为物理模块单元,这也是我们平时常用引用第三方类库的方法。

Java的解决方法

服务接口

package org.p2.helloworld;

public interface HelloService {  
void sayHello(String name);  
}

实现类

package org.p2.helloworld.impl;

import org.p2.helloworld.HelloService;

public class HelloServiceImpl implements HelloService {
public void sayHello(String name){
    System.out.println("Hello," + name);
}
}

简单的工厂控制实现

package org.p2.helloworld;

import org.p2.helloworld.impl.HelloServiceImpl;

public class HelloFactory {
    public static HelloService getHelloService() {
        return new HelloServiceImpl();
    }
}

服务模块单元provider.jar包含以上几个包,客户端client.jar内容如下。

package org.p1.helloworld.main

import org.p2.helloworld.*;

public class Main {
public static void main(String[] args) {
    HelloService helloService = HelloFactory.getHelloService();
    helloService.sayHello("World"); 
}
}

以上实现由于将接口和实现类放在了不同的包中,所以实现类可见性必须为public。如果将实现类和接口放在同一个包中,则实现类可见性可设置为仅包可见。实现类代码如下,其他类同上,可实现provider.jar仅向外暴露接口。

class HelloServiceImpl implements HelloService {
public void sayHello(String name){
    System.out.println("Hello," + name);
}
}

.NET解决方案讨论

服务接口

namespace Provider
{
    public interface HelloService
    {
        void SayHello(string name);
    }
}

实现

namespace Provider.Impl
{
    internal class HelloServiceImpl : HelloService
    {
        public void SayHello(string name)
        {
            Console.WriteLine("Hello," + name);
        }
    }
}

工厂类

using Provider.Impl;
namespace Provider
{
    public class HelloServiceFactory
    {
        public static HelloService GetHelloService()
        {
            return new HelloServiceImpl();
        }
    }
}

以上为服务模块单元provider.dll包含内容,.NET下可实现将实现类和接口放在不同命名空间下,同时向外仅暴露接口。

分析讨论

以上将HelloService接口和实现类HelloServiceImpl放在了同一个物理provider.jar下的两个包下,以provider.jar类库形式提供给客户端。无论是采用[1]中的Spring框架注入实现类,还是[3]中的方法注入实现类,如果将实现类和接口放在不同包中,都必须将HelloServiceImpl的包可见性设置为public。这样导致了一旦客户端模块引用了服务端模块并导入包,则可直接实例化实现类。这就是参考资料里所说的Java没有提供将包或类定义为模块作用域的方法,导致一个模块中的类总是能够访问另一个模块的实现细节,这也OSGi这样的框架致力解决的问题。如果将实现类和接口放在一个包中则可以向外仅暴露接口,但同一物理模块jar下的其他包无法使用实现类。
对比.NET下的解决方法,.NET下可以将实现类设置为internal,物理模块内可见,对引用此模块的客户端程序不可见。而Java的包可见性有逻辑方面和物理设计方面的限制,并不是很纯粹。因此java的包和.NET的命名空间有很大不同。个人猜测这可能和跨平台有关,毕竟物理模块和具体平台有关。结合实际的应用情况,确实需要物理方面的可见性控制,这样才能提供更好的封装性。物理模块的组织设计及良好的封装性确实是这本书给我最大的启示。

参考资料

  1. Java Application Architecture-Modularity Patterns with Examples Using OSGi, Kirk Knoernschild, 中文译名Java应用架构设计-模块化与OSGi
  2. OSGi中文社区,OSGi入门篇:模块层
  3. OSGi:简介,优酷jevon_fu

转载于:https://www.cnblogs.com/tsingfei/p/3901833.html

Java应用架构设计:模块化模式与OSGi 英文版 中文版介绍: 全球资深Java技术专家的力作,系统、全面地讲解如何将模块化设计思想引入开发中,涵盖18个有助于实现模块化软件架构的模式 中文目录: 第一部分 模块化的理由 第1章 模块定义 1.1 定义模块 1.1.1 可部署 1.1.2 可管理 1.1.3 可测试 1.1.4 原生可重用 1.1.5 可组合 1.1.6 无状态 1.2 软件模块的简洁定义 1.3 结论 第2章 模块化的两个方面 2.1 运行时模型 2.2 开发模型 2.2.1 编程模型 2.2.2 设计范式 2.3 模块化现状 2.4 结论 第3章 架构与模块化 3.1 定义架构 3.2 关于软件架构的一个故事 3.2.1 象牙塔 3.2.2 乌龟和塔 3.3 架构的目标 3.3.1 悖论 3.3.2 消除架构 3.4 模块化:被忽视的部分 3.5 回答我们的问题 3.6 结论 3.7 参考文献 第4章 征服复杂 4.1 企业级复杂 4.2 技术债 4.3 设计腐化 4.3.1 干扰可维护 4.3.2 阻止可扩展 4.3.3 抑制可重用 4.3.4 限制可测试 4.3.5 妨碍集成 4.3.6 阻碍理解 4.4 循环依赖 4.4.1 循环类型 4.4.2 悄然引入的循环 4.4.3 管理循环 4.4.4 循环总是不好的吗 4.5 结合点、模块和SOLID 4.6 管理复杂 4.7 模块化的益处 4.8 结论 4.9 参考文献 第5章 实现重用 5.1 可用重用悖论 5.2 关于重用的免责声明 5.2.1 粒度 5.2.2 重量级 5.3 重用还是可用 5.4 模块化权衡 5.5 模块化设计 5.6 结论 5.7 参考文献 第6章 模块化与SOA 6.1 重新审视“自上而下” 6.2 粒度--架构师的强大对手 6.2.1 现实世界的一个例子 6.2.2 提升一个等级 6.2.3 另一个维度 6.2.4 全景图 6.2.5 服务样例 6.3 另一个视图 6.4 结论 第7章 参考实现 7.1 为什么不用OSGi 7.2 这个练习的背景:构建系统 7.3 初始版本 7.4 第一次重构 7.5 第二次重构 7.6 第三次重构 7.7 第四次重构 7.7.1 关于OSGi的好处 7.7.2 小结并准备下一次重构 7.8 第五次重构 7.9 第六次重构 7.10 第七次重构 7.11 事后剖析 7.11.1 关于模块测试 7.11.2 关于管理模块依赖 7.11.3 关于模块重用 7.11.4 关于构建 7.11.5 关于面向对象 7.12 结论 7.13 参考文献 第二部分 模 式 第8章 基本模式 8.1 管理关系 8.1.1 表述 8.1.2 描述 8.1.3 多种实现 8.1.4 影响 8.1.5 样例 8.1.6 小结 8.2 模块重用 8.2.1 表述 8.2.2 描述 8.2.3 多种实现 8.2.4 效果 8.2.5 样例 8.2.6 小结 8.3 模块内聚 8.3.1 表述 8.3.2 描述 8.3.3 多种实现 8.3.4 效果 8.3.5 样例 8.3.6 小结 第9章 依赖模式 9.1 非循环关系 9.1.1 表述 9.1.2 描述 9.1.3 多种实现 9.1.4 效果 9.1.5 样例 9.1.6 小结 9.2 等级化模块 9.2.1 表述 9.2.2 描述 9.2.3 多种实现 9.2.4 效果 9.2.5 样例 9.2.6 小结 9.3 物理分层 9.3.1 表述 9.3.2 描述 9.3.3 多种实现 9.3.4 效果 9.3.5 样例 9.3.6 小结 9.4 容器独立 9.4.1 表述 9.4.2 描述 9.4.3 多种实现 9.4.4 效果 9.4.5 样例 9.4.6 小结 9.5 独立部署 9.5.1 表述 9.5.2 描述 9.5.3 多种实现 9.5.4 效果 9.5.5 样例 9.5.6 小结 9.6 参考文献 第10章 可用模式 10.1 发布接口 10.1.1 表述 10.1.2 描述 10.1.3 多种实现 10.1.4 效果 10.1.5 样例 10.1.6 小结 10.2 外部配置 10.2.1 表述 10.2.2 描述 10.2.3 多种实现 10.2.4 效果 10.2.5 样例 10.2.6 小结 10.3 默认实现 10.3.1 表述 10.3.2 描述 10.3.3 多种实现 10.3.4 效果 10.3.5 样例 10.3.6 小结 10.4 模块门面 10.4.1 表述 10.4.2 描述 10.4.3 多种实现 10.4.4 效果 10.4.5 样例 10.4.6 小结 第11章 扩展模式 11.1 抽象化模块 11.1.1 表述 11.1.2 描述 11.1.3 多种实现 11.1.4 效果 11.1.5 样例 11.1.6 小结 11.2 实现工厂 11.2.1 表述 11.2.2 描述 11.2.3 多种实现 11.2.4 效果 11.2.5 样例 11.2.6 小结 11.3 分离抽象 11.3.1 表述 11.3.2 描述 11.3.3 多种实现 11.3.4 效果 11.3.5 样例 11.3.6 小结 11.4 参考文献 第12章 通用模式 12.1 就近异常 12.1.1 表述 12.1.2 描述 12.1.3 多种实现 12.1.4 效果 12.1.5 样例 12.1.6 小结 12.2 等级化构建 12.2.1 表述 12.2.2 描述 12.2.3 多种实现 12.2.4 效果 12.2.5 样例 12.2.6 小结 12.3 测试模块 12.3.1 表述 12.3.2 描述 12.3.3 多种实现 12.3.4 效果 12.3.5 样例 12.3.6 小结 第三部分 模块化架构模式与OSGi 第13章 OSGi简介 13.1 一点历史 13.2 OSGi所能带来的收益 13.2.1 模块化开发 13.2.2 管理依赖 13.2.3 模块平台 13.2.4 版本化的bundle 13.2.5 动态(重)部署 13.2.6 环境相关的控制 13.3 深入理解OSGi 13.4 OSGi bundle 13.4.1 bundle状态 13.4.2 OSGi ?Service 13.5 OSGi运行时管理 13.6 重新查看模块化的两个方面 13.7 OSGi与模式 13.7.1 管理依赖 13.7.2 动态 13.7.3 Blueprint规范 第14章 贷款样例与OSGi 14.1 起步 14.2 清单文件 14.3 ?Service 14.3.1 Blueprint服务 14.3.2 贷款样例配置 14.3.3 OSGi ?Service声明 14.4 安装与执行 14.5 结论 第15章 OSGi与Scala 15.1 起步 15.2 Scala代码 15.3 Scala bean配置 15.4 Scala Service配置 15.5 构建Scala模块 15.6 安装与执行 15.7 结论 第16章 OSGi与Groovy 16.1 起步 16.2 Groovy代码 16.3 Groovy bean配置 16.4 Groovy ?Service配置 16.5 构建Groovy模块 16.6 安装与执行 16.7 结论 第17章 OSGi的未来 17.1 将OSGi作为推动者 17.2 颠覆 17.3 生态系统的威力 17.3.1 生态系统与模块化的两个方面 17.3.2 基于组件的开发(CBD)不是已经成功了吗 17.4 生态系统 17.5 结论 附录A 类设计的SOLID原则
Java应用架构设计:模块化模式与OSGi 英文版 中文版介绍: 全球资深Java技术专家的力作,系统、全面地讲解如何将模块化设计思想引入开发中,涵盖18个有助于实现模块化软件架构的模式 中文目录: 第一部分 模块化的理由 第1章 模块定义 1.1 定义模块 1.1.1 可部署 1.1.2 可管理 1.1.3 可测试 1.1.4 原生可重用 1.1.5 可组合 1.1.6 无状态 1.2 软件模块的简洁定义 1.3 结论 第2章 模块化的两个方面 2.1 运行时模型 2.2 开发模型 2.2.1 编程模型 2.2.2 设计范式 2.3 模块化现状 2.4 结论 第3章 架构与模块化 3.1 定义架构 3.2 关于软件架构的一个故事 3.2.1 象牙塔 3.2.2 乌龟和塔 3.3 架构的目标 3.3.1 悖论 3.3.2 消除架构 3.4 模块化:被忽视的部分 3.5 回答我们的问题 3.6 结论 3.7 参考文献 第4章 征服复杂 4.1 企业级复杂 4.2 技术债 4.3 设计腐化 4.3.1 干扰可维护 4.3.2 阻止可扩展 4.3.3 抑制可重用 4.3.4 限制可测试 4.3.5 妨碍集成 4.3.6 阻碍理解 4.4 循环依赖 4.4.1 循环类型 4.4.2 悄然引入的循环 4.4.3 管理循环 4.4.4 循环总是不好的吗 4.5 结合点、模块和SOLID 4.6 管理复杂 4.7 模块化的益处 4.8 结论 4.9 参考文献 第5章 实现重用 5.1 可用重用悖论 5.2 关于重用的免责声明 5.2.1 粒度 5.2.2 重量级 5.3 重用还是可用 5.4 模块化权衡 5.5 模块化设计 5.6 结论 5.7 参考文献 第6章 模块化与SOA 6.1 重新审视“自上而下” 6.2 粒度--架构师的强大对手 6.2.1 现实世界的一个例子 6.2.2 提升一个等级 6.2.3 另一个维度 6.2.4 全景图 6.2.5 服务样例 6.3 另一个视图 6.4 结论 第7章 参考实现 7.1 为什么不用OSGi 7.2 这个练习的背景:构建系统 7.3 初始版本 7.4 第一次重构 7.5 第二次重构 7.6 第三次重构 7.7 第四次重构 7.7.1 关于OSGi的好处 7.7.2 小结并准备下一次重构 7.8 第五次重构 7.9 第六次重构 7.10 第七次重构 7.11 事后剖析 7.11.1 关于模块测试 7.11.2 关于管理模块依赖 7.11.3 关于模块重用 7.11.4 关于构建 7.11.5 关于面向对象 7.12 结论 7.13 参考文献 第二部分 模 式 第8章 基本模式 8.1 管理关系 8.1.1 表述 8.1.2 描述 8.1.3 多种实现 8.1.4 影响 8.1.5 样例 8.1.6 小结 8.2 模块重用 8.2.1 表述 8.2.2 描述 8.2.3 多种实现 8.2.4 效果 8.2.5 样例 8.2.6 小结 8.3 模块内聚 8.3.1 表述 8.3.2 描述 8.3.3 多种实现 8.3.4 效果 8.3.5 样例 8.3.6 小结 第9章 依赖模式 9.1 非循环关系 9.1.1 表述 9.1.2 描述 9.1.3 多种实现 9.1.4 效果 9.1.5 样例 9.1.6 小结 9.2 等级化模块 9.2.1 表述 9.2.2 描述 9.2.3 多种实现 9.2.4 效果 9.2.5 样例 9.2.6 小结 9.3 物理分层 9.3.1 表述 9.3.2 描述 9.3.3 多种实现 9.3.4 效果 9.3.5 样例 9.3.6 小结 9.4 容器独立 9.4.1 表述 9.4.2 描述 9.4.3 多种实现 9.4.4 效果 9.4.5 样例 9.4.6 小结 9.5 独立部署 9.5.1 表述 9.5.2 描述 9.5.3 多种实现 9.5.4 效果 9.5.5 样例 9.5.6 小结 9.6 参考文献 第10章 可用模式 10.1 发布接口 10.1.1 表述 10.1.2 描述 10.1.3 多种实现 10.1.4 效果 10.1.5 样例 10.1.6 小结 10.2 外部配置 10.2.1 表述 10.2.2 描述 10.2.3 多种实现 10.2.4 效果 10.2.5 样例 10.2.6 小结 10.3 默认实现 10.3.1 表述 10.3.2 描述 10.3.3 多种实现 10.3.4 效果 10.3.5 样例 10.3.6 小结 10.4 模块门面 10.4.1 表述 10.4.2 描述 10.4.3 多种实现 10.4.4 效果 10.4.5 样例 10.4.6 小结 第11章 扩展模式 11.1 抽象化模块 11.1.1 表述 11.1.2 描述 11.1.3 多种实现 11.1.4 效果 11.1.5 样例 11.1.6 小结 11.2 实现工厂 11.2.1 表述 11.2.2 描述 11.2.3 多种实现 11.2.4 效果 11.2.5 样例 11.2.6 小结 11.3 分离抽象 11.3.1 表述 11.3.2 描述 11.3.3 多种实现 11.3.4 效果 11.3.5 样例 11.3.6 小结 11.4 参考文献 第12章 通用模式 12.1 就近异常 12.1.1 表述 12.1.2 描述 12.1.3 多种实现 12.1.4 效果 12.1.5 样例 12.1.6 小结 12.2 等级化构建 12.2.1 表述 12.2.2 描述 12.2.3 多种实现 12.2.4 效果 12.2.5 样例 12.2.6 小结 12.3 测试模块 12.3.1 表述 12.3.2 描述 12.3.3 多种实现 12.3.4 效果 12.3.5 样例 12.3.6 小结 第三部分 模块化架构模式与OSGi 第13章 OSGi简介 13.1 一点历史 13.2 OSGi所能带来的收益 13.2.1 模块化开发 13.2.2 管理依赖 13.2.3 模块平台 13.2.4 版本化的bundle 13.2.5 动态(重)部署 13.2.6 环境相关的控制 13.3 深入理解OSGi 13.4 OSGi bundle 13.4.1 bundle状态 13.4.2 OSGi ?Service 13.5 OSGi运行时管理 13.6 重新查看模块化的两个方面 13.7 OSGi与模式 13.7.1 管理依赖 13.7.2 动态 13.7.3 Blueprint规范 第14章 贷款样例与OSGi 14.1 起步 14.2 清单文件 14.3 ?Service 14.3.1 Blueprint服务 14.3.2 贷款样例配置 14.3.3 OSGi ?Service声明 14.4 安装与执行 14.5 结论 第15章 OSGi与Scala 15.1 起步 15.2 Scala代码 15.3 Scala bean配置 15.4 Scala Service配置 15.5 构建Scala模块 15.6 安装与执行 15.7 结论 第16章 OSGi与Groovy 16.1 起步 16.2 Groovy代码 16.3 Groovy bean配置 16.4 Groovy ?Service配置 16.5 构建Groovy模块 16.6 安装与执行 16.7 结论 第17章 OSGi的未来 17.1 将OSGi作为推动者 17.2 颠覆 17.3 生态系统的威力 17.3.1 生态系统与模块化的两个方面 17.3.2 基于组件的开发(CBD)不是已经成功了吗 17.4 生态系统 17.5 结论 附录A 类设计的SOLID原则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值