软件设计和体系结构
一、引言
软件
定义:一系列按照特定顺序组织的计算机数据、指令的集合
特点:
- 软件不是生产制造,是设计开发
- 软件不会磨损和老化
- 软件需要根据实际情况进行定制开发
软件设计的基本原则
-
抽象方法
- 过程抽象:是指具有明确和有限功能的指令序列
- 数据抽象:描述数据对象的冠名数据集合
-
体系结构
程序构件的结构或组织、这些构件交互的形式以及这些构件所用数据的结构。
-
设计模式
- 含义:模式是指解决某一类问题的方法论
- 目的:为了可重用代码、让代码更容易被他人理解、保证代码的可靠性
软件体系结构
定义:软件系统的基本组织,包含构件、构件之间、构件与环境之间的关系,以及相关的设计与进化原则等
四个研究领域
- 通过体系结构描述语言(ADL)解决体系结构描述问题。
- 目标:提供设计体系结构更好的方法,便于设计人员相互交流,并使用相关工具来分析案例
- 体系结构领域知识的总结性研究
- 针对特定领域的框架的研究
- 软件体系结构形式化支持的研究
二、软件模型和描述
软件模型的发展脉络
功能模型
也可称为过程模型和函数模型,是模型化软件结构方法中的第一个基本模型
对象模型
以对象为核心,通过对象进行对数据组织的抽象并实现数据组织和数据处理的统一,并在此基础上建立面向对象软件构造方法
组件模型
在对象模型的基础上强调了异族对象关系以及独立性问题
配置型组件模型
又称服务器组件模型,专门针对应用服务器,定义其基于组件的基础结构模型
服务模型
服务由数据、业务逻辑、接口及服务描述构成
抽象模型
对软件系统的简化和概括,提供了对系统组成和行为的高层次描述
软件体系结构的描述
-
非形式化描述
-
统一建模语言(UML):
- 可视化的建模语言
- 建立在对象模型之上的标准系统建模方法
- 可以对静态或动态结构系统进行建模
优点:在系统开发的各个阶段具有一致性,可以面向各种应用领域系统建模
-
-
形式化描述
体系结构描述语言(ADL)
关注的是使用意图,而缺乏必要的规范定义
含义:一种用于描述软件与系统结构的计算机语言
要素:构件、操作、模式、闭包、规格说明
三、软件体系结构建模和 UML
统一建模语言(UML):
- 可视化的建模语言
- 在对象模型基础之上的标准系统建模方法
- 可以对任何静态或动态的结构系统进行建模
优点:在系统开发的各个阶段具有一致性,可以面向各种应用领域系统建模
特点:
- 统一标准
- 面向对象的特性
- UML在演变过程中提出心的概念:模板、职责。扩展机制等
- 独立于开发过程
抽象类和接口的区别
- 抽象类是一种可以包含实现方法和抽象方法的类
- 接口是一种只包含抽象方法和常量声明的结构
- 类可以继承一个抽象类但实现多个接口
四、软件设计过程
软件体系结构设计方法
多视图建模
- 多视图建模:4+1模型
- 逻辑视图:又称概念视图,主要是支持系统功能需求的抽象描述,即系统最终将提供给用户什么样的服务。逻辑视图描述了系统的功能需求及其之间的相互关系。
- 开发视图:又称模块视图,主要侧重于描述系统的组织,与逻辑视图密切相关,都描述了系统的静态结构
- 过程视图:主要侧重于描述系统的动态行为,即系统运行时所表现出的相关特性,着重解决系统的可靠性、吞吐量、并发性、分布性、容错性
- 物理视图:描述如何把系统软件元素映射到硬件上,通常要考虑系统的性能、规模和容错等问题,展示了软件在生命周期的不同阶段中所需要的物理环境、硬件配置、分布状况
- 场景视图:场景是用户需求和系统功能实例的抽象,设计者通过分析如何满足每个场景所要求的的约束,来分析软件的体系结构
领域特定的软件体系结构设计
领域特定的软件体系结构(DSSA)是领域工程的核心部分。
领域特定的软件体系结构借鉴领域中已经成熟的软件体系结构,实现解决方案在某个领域内的复用。
五、软件体系结构风格
人们在开发某些类型软件过程中积累起来的组织规则和结构,形成了软件体系结构风格。
软件体系结构风格是描述某一特定应用领域中系统组织方式的惯用模式。
基本风格解析
1. 管道-过滤器
定义:
- 输入集合输入数据流,输出集合输出数据流
- 功能模块称为过滤器,连接过滤器之间的通路称为管道
- 数据流可以在过滤器中进行相关增量计算得到输出流
特征
- 在管道-过滤器风格中,构件即过滤器,对输入流进行处理、转换,处理后的结果在输出端流出。这种计算 常常是递进的,所以可能在全部的输入接收完之前就开始输出。可以并行地使用过滤器
- 连接件位于过滤器之间,起到信息流的导管的作用,即管道
- 每个构件都有输入/输出集合,构件在输入出读取数据流,并在输出处生成数据流,一个构件的输入是上一个构件的输出
- 过滤器必须是独立的实体,不了解信息流从哪个过滤器流出,也不需要知道信息将流入哪个过滤器。可以 指定输入的格式,可以确保输出的结果,但是可能不知道在管道之后将会是什么样子。过滤器之间也不共享状态
优点
- 由于每个构件的行为不受其他构件的影响,因此整个系统的行为比较易于理解
- 支持功能模块的复用
- 具有较强的可维护性、可扩展性
2.基于事件的隐式调用风格
定义
- 组件之间不直接调用对方的方法,而是通过发布事件和订阅事件的方式进行通信。当某个组件发生特定事件时,它会通知所有订阅了该事件的其他组件,从而触发相应的响应行为
特点
- 事件的触发者并不知道哪些构件会响应
3.仓库风格和黑板风格
仓库风格:
- 定义:基于中央仓储,系统组件通过中央仓库进行通信和协作
- 特点:
- 中心化的数据存储
- 低耦合
- 同步机制,确保数据的一致性和可靠性
- 灵活度高
黑板风格:一种特殊的仓库风格
- 定义:基于全局的共享知识库(黑板),系统中的组件通过黑板写入和读取信息进行协作和推理
- 特点:
- 全局知识库:系统中的组件通过读写共享的黑板来获取和传递知识
- 非确定性推理:组件可根据黑板上的信息进行推理和决策
4.模型-视图-控制器风格
MVC(模型-视图-控制器) 模式:
- 模型类
- 视图类
- 控制类
客户/服务器风格
系统被划分为客户端和服务器端两个角色,客户端发送请求给服务器端,服务器端处理请求并返回响应
优点:
- 可扩展性
- 可重用性
- 灵活性
- 性能优化
缺点:
- 单点故障
- 通信开销
- 维护复杂性
- 安全性风险
三层 C/S 体系结构风格
在二层中加了一层应用服务器
将系统按照职责划分为客户端、应用服务器和数据库服务器三个层次
优点:
- 分离关注点:三层C/S体系结构将用户界面、业务逻辑和数据存储分离,使得各层之间的关注点清晰,提高了系统的可维护性和可扩展性。
浏览器/服务器风格
B/S模式第一层客户机的主体是浏览器。第二层Web服务器是实现B/S结构的关键。
正交软件体系结构
- 概念:由组织层和线索的构件构成
六、面向对象方法
1、面向对象系统开发过程概述
面向对象的思想设计软件开发的各个阶段,
- 面向对象的分析(OOA)
- 面向对象的设计(OOD)
- 面向对象的编程实现(OOP)
九、设计模式
1.设计模式概述
设计模式的核心思想是总结和积累前人成功的设计经验,通过对这些经验的学习,使得人们在面对新的设计问题时,不用再重复所有的环节,而是尽量套用已有的模式实施,以提高编程的效率。模式是解决特定问题的经验,其实质是软件的复用。
模式由特定的环境,问题、解决方案三个要素组成,按照软件开发的层次可以分为体系结构模式、设计模式、程序模式,体系结构模式属于层次较高的模式,如MVC。
设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。基本设计模式共23种。
2.设计模式的主要作用(*)
- 优化的设计经验:设计模式为开发者提供了良好的经过优化的设计经验
- 较高的复用性:设计模式重用面向对象代码提供了一种方便途径,使得复用某些成功的设计和结构更加容易
- 丰富的表达能力:提供了一种共享的设计语言和思维方式,有助于团队协作开发
- 降低耦合性:设计模式的基本思想就是将程序中可能变化的部分与不变化的部分进行分离,尽量减少对象之间的耦合。
3.常用设计模式解析(*)
根据目的的不同,将 23 种设计模式分为 三 种
- 创建型模式:主要用于创建对象
- 结构型模式:主要用于处理类和对象的组合
- 行为型模式:主要用于描述对类或对象怎么样交互和怎样分配职责
创建型设计模式
-
简单工厂模式
-
定义:定义一个类来负责创建其他类的实例,又称静态工厂方法模式,属于类的创建型模式
// 产品接口 interface Product { void operation(); } // 具体产品类A class ConcreteProductA implements Product { @Override public void operation() { System.out.println("具体产品A的操作"); } } // 具体产品类B class ConcreteProductB implements Product { @Override public void operation() { System.out.println("具体产品B的操作"); } } // 简单工厂类 class SimpleFactory { public Product createProduct(String productType) { if (productType.equals("A")) { return new ConcreteProductA(); } else if (productType.equals("B")) { return new ConcreteProductB(); } else { throw new IllegalArgumentException("无效的产品类型"); } } } // 客户端代码 public class Client { public static void main(String[] args) { SimpleFactory factory = new SimpleFactory(); Product productA = factory.createProduct("A"); productA.operation(); // 输出:具体产品A的操作 Product productB = factory.createProduct("B"); productB.operation(); // 输出:具体产品B的操作 } }
-
-
工厂方法模式
-
定义:对简单工程模式进行了抽象和推广,具体的生产工作推延到其子类去完成
-
将对象的创建委托给具体的工厂类,从而使得客户端代码与具体的产品类解耦。
// 产品接口 interface Product { void operation(); } // 具体产品类A class ConcreteProductA implements Product { @Override public void operation() { System.out.println("具体产品A的操作"); } } // 具体产品类B class ConcreteProductB implements Product { @Override public void operation() { System.out.println("具体产品B的操作"); } } // 抽象工厂类 abstract class AbstractFactory { public abstract Product createProduct(); } // 具体工厂类A class ConcreteFactoryA extends AbstractFactory { @Override public Product createProduct() { return new ConcreteProductA(); } } // 具体工厂类B class ConcreteFactoryB extends AbstractFactory { @Override public Product createProduct() { return new ConcreteProductB(); } } // 客户端代码 public class Client { public static void main(String[] args) { AbstractFactory factoryA = new ConcreteFactoryA(); Product productA = factoryA.createProduct(); productA.operation(); // 输出:具体产品A的操作 AbstractFactory factoryB = new ConcreteFactoryB(); Product productB = factoryB.createProduct(); productB.operation(); // 输出:具体产品B的操作 } }
-
-
抽象工厂模式
-
定义:提供了一个接口用于创建一系列相关对象,而无需指定具体的实现类。
// 抽象产品接口A interface AbstractProductA { void operationA(); } // 具体产品类A1 class ConcreteProductA1 implements AbstractProductA { @Override public void operationA() { System.out.println("具体产品A1的操作"); } } // 具体产品类A2 class ConcreteProductA2 implements AbstractProductA { @Override public void operationA() { System.out.println("具体产品A2的操作"); } } // 抽象产品接口B interface AbstractProductB { void operationB(); } // 具体产品类B1 class ConcreteProductB1 implements AbstractProductB { @Override public void operationB() { System.out.println("具体产品B1的操作"); } } // 具体产品类B2 class ConcreteProductB2 implements AbstractProductB { @Override public void operationB() { System.out.println("具体产品B2的操作"); } } // 抽象工厂类 interface AbstractFactory { AbstractProductA createProductA(); AbstractProductB createProductB(); } // 具体工厂类1 class ConcreteFactory1 implements AbstractFactory { @Override public AbstractProductA createProductA() { return new ConcreteProductA1(); } @Override public AbstractProductB createProductB() { return new ConcreteProductB1(); } } // 具体工厂类2 class ConcreteFactory2 implements AbstractFactory { @Override public AbstractProductA createProductA() { return new ConcreteProductA2(); } @Override public AbstractProductB createProductB() { return new ConcreteProductB2(); } } // 客户端代码 public class Client { public static void main(String[] args) { AbstractFactory factory1 = new ConcreteFactory1(); AbstractProductA productA1 = factory1.createProductA(); AbstractProductB productB1 = factory1.createProductB(); productA1.operationA(); // 输出:具体产品A1的操作 productB1.operationB(); // 输出:具体产品B1的操作 AbstractFactory factory2 = new ConcreteFactory2(); AbstractProductA productA2 = factory2.createProductA(); AbstractProductB productB2 = factory2.createProductB(); productA2.operationA(); // 输出:具体产品A2的操作 productB2.operationB(); // 输出:具体产品B2的操作 } }
-
-
单例模式(*)
-
概念:保证某个类有且仅有一个实例
-
目的:保证应用只有一个全局唯一的实例,并且提供一个访问它的全局访问点
-
饿汉式
- 特点:在类声明时就完成了初始化
- 优点:实现简单,执行效率高,线程安全
- 缺点:类加载时就初始化,可能占用不必要的内存
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }
-
懒汉式
- 特点:使用时才初始化,即懒加载
- 优点:避免造成不必要的资源浪费
- 缺点:使用关键词进行加锁,会影响性能
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
-
枚举
public enum Singleton { INSTANCE; // 添加其他属性和方法 private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } } public class Main { public static void main(String[] args) { Singleton singleton = Singleton.INSTANCE; singleton.setName("Singleton Instance"); System.out.println(singleton.getName()); // 输出:Singleton Instance } }
-
-
原型模式
-
建造者模式
结构型设计模式
-
适配器模式
-
桥接模式
-
目的:将抽象部分与实现部分分离,使它们可以独立地变化。
桥接模式通过组合关系而不是继承关系来连接抽象和实现
-
优点:
- 分离抽象和实现
- 增加系统的灵活性和可扩展性
-
缺点
- 增加系统的复杂性和代码量
- 系统运行速度变慢
// 实现部分的接口 interface Implementor { void operationImpl(); } // 具体实现类A class ConcreteImplementorA implements Implementor { public void operationImpl() { System.out.println("Concrete Implementor A"); } } // 具体实现类B class ConcreteImplementorB implements Implementor { public void operationImpl() { System.out.println("Concrete Implementor B"); } } // 抽象部分的接口 abstract class Abstraction { protected Implementor implementor; protected Abstraction(Implementor implementor) { this.implementor = implementor; } abstract void operation(); } // 扩展抽象部分的类A class RefinedAbstractionA extends Abstraction { protected RefinedAbstractionA(Implementor implementor) { super(implementor); } void operation() { System.out.println("Refined Abstraction A"); implementor.operationImpl(); } } // 扩展抽象部分的类B class RefinedAbstractionB extends Abstraction { protected RefinedAbstractionB(Implementor implementor) { super(implementor); } void operation() { System.out.println("Refined Abstraction B"); implementor.operationImpl(); } } // 客户端代码 public class Client { public static void main(String[] args) { Implementor implementorA = new ConcreteImplementorA(); Abstraction abstractionA = new RefinedAbstractionA(implementorA); abstractionA.operation(); Implementor implementorB = new ConcreteImplementorB(); Abstraction abstractionB = new RefinedAbstractionB(implementorB); abstractionB.operation(); } }
-
适用场景
- 避免抽象方法和其实现方法绑定在一起
- 抽象接口和实现都需要扩展出子类以备使用
- 变动实现的方法不会影响客户程序调用的部分
-
-
组合模式
-
装饰模式
-
外观模式
-
享元模式
-
代理模式
行为型设计模式
描述算法及对象之间的任务职责分配,所描述的不仅仅是类或对象的设计模式,还有之间的通信模式。
4.常用原则
SOLID
- 单一责任原则
- 单一职责原则要求类的职责单一,引起类变化的原因单一。
- 优点:降低了类的复杂度,提高了可读性、可维护性,降低了变更引起的风险。
- 开放封闭原则
- 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
- 里氏替换原则/迪米特法则
- 对于里氏替换原则,所有引用基类的地方必须透明地使用其子类的对象。
- 迪米特原则一个类应该对自己需要耦合或调用的类知道的最少
- 接口隔离原则
- 接口隔离原则强调接口的高内聚和低耦合,客户端不应该依赖它不需要的接口
- 依赖倒置原则
- 对于依赖倒置原则,要求面向对象的设计要对结构化的方法进行倒置,即高层模块不应依赖底层模块,二者都应依赖于抽象
十、Web 服务体系结构
- 定义:通过 Web 接口提供的某个功能程序段
- 特点:
- 平台无关性
- 通用的通信信道
- 企业的互操作性
- 功能复用
- 拓展业务
- 服务器的中立性
- 安全的通信
- SOAP:简单对象访问协议
- 定义:一种基于 XML 的协议,通过 HTTP 或其他协议在网络上进行应用程序之间的通信和信息交换
- XML:可扩展标记语言
- 为消息交换定义了描述和格式
- HTTP:超文本传输协议
- 定义了客户端和服务器之间交换的消息格式和规则,实现了从客户端请求到服务器响应的数据传输和交互过程
- WSDL:Web 服务描述语言
- 一种用于描述 Web 服务接口及其访问方式的 XML 文件标准
十一、基于分布构件的体系结构
EJB技术
EJB 是基于分布式事务吃力的企业级应用程序的组件。EJB是用于开发和部署多层结构的、分布式的、面向对象的Java应用系统的跨平台构件体系结构。
DCOM
- DCOM是微软基于COM扩展的分布式计算技术,具有支持远程对象通信、透明性、安全性、可靠性和互操作性等特点。
CORBA
- CORBA(Common Object Request Broker Architecture)是一种通用的对象请求代理体系结构,用于支持分布式计算环境中的对象通信和交互,具有跨平台、跨语言的特点。