导图社区 软件体系结构和设计模式
本图梳理了软件体系结构和设计模式的内容,包含工厂方法模式、抽象工厂模式、适配器模式、桥接模式、策略模式、状态模式、访问者模式、调停者模式等。
编辑于2021-10-27 09:10:46软件体系结构和设计模式
L0 基础部分
类之间的关系
关联关系
聚合关系:部分可以单独存在的关系
组合关系
依赖关系
继承关系
实现关系
Java抽象类
接口类:没有构造方法
面向对象设计原则
开闭原则
依赖倒置原则
接口隔离原则
L1 工厂方法模式
概述
介绍:(将选择与初始化一个合适的类的功能封装在一个专门的类的一个专门的方法中-委托).
选择一个类:选择一个合适的类的类层次结构的基础上,应用程序上下文和其他影响因素 创建该类的对象:所选类和实例化 以超类的类型返回该对象:返回父类类型的一个实例 不做任何其它事情
Client doesn’t need to know which concrete class has been instantiated (客户类只知道哪种类型的对象被创建了,而不必知道哪个具体的子类被初始化了;客户类只知道父类类型).
因为工厂方法将选择的类实例作为父类类型的对象返回,所以客户端程序不需要知道层次结构中类的存在。
两种方法
简单工厂方法模式【静态工厂方法】
工厂类:Creator (工厂类): 中心. 包含业务逻辑. 创建产品类对象.
最终成果:具体的JAva类趋势线接口或者是抽象类
优点: 一些逻辑被放在了工厂类里面 客户类不用自己创建对象 责任分离
工厂方法模式【动态工厂方法】
工厂类是一个借口,下面拥有实现类分别对应产品类
需要再监视器中对实现的产品类类型进行判断
使用的场景
A class contains a lot of conditional statements for creating objects (大量条件语句). A class uses its subclasses to specify which objects it creates (即,创建对象的任务分散在客户类的子类中,比较乱;可使用工厂方法模式将创建产品类的子类对象的责任分离出来). You want to localize the knowledge of which class gets created.
L2 抽象工厂模式
介绍:如果包含多个产品层次类【结构相同】
对于每个Product层次类, 我们构造一个工厂层次类×
Two concrete factory classes, each is responsible for creating 3 objects.
理论:工厂类中有2个工厂方法;每个工厂方法创建一个Product类的对象
使用场景:当Client对象想要创建一族层次类的某个子类对象,而不想知道到底是哪个子类对象被创建了。
设计
L3 适配器模式
L4 桥接模式
该模式不是简单地将这些类摆在一起,而是要提供这些类之间的关联方式。
介绍:将抽象部分与实现部分分开
理论
实现接口仅提供原始操作(例如,写入数据库,写入数据文件等等) The Implementor interface provides only primitive operations 抽象接口定义基于原始操作的高层操作(高层业务逻辑) The Abstraction defines higher-level operations based on these primitives
设计
结构模式
L5 策略模式 【行为型模式】
关心对象之间的责任分配,侧重描述通信模式
关于设计模式的调用
客户类代表调用者类
客户类调用该模式
对于不同模式,调用方式不同
依赖倒转原则
通过设计一个排序程序来介绍策略模式
优点
When a new algorithm is added, the existing Sorting class hierarchy doesn’t need to be changed and recompiled
When an algorithm is modified, the remaining classes in the Sorting hierarchy don’t need to be changed and recompiled
Both the client class and the implementation classes depends on the abstract interface
依赖倒转原则
策略模式理论
组成
策略strategy
声明一个通用的接口并且上下文使用这个具体的策略来进行调用具体的策略中实现的算法
具体的战略concertrateStrategy
上下文context
使用ConcreteStrategy对象配置
维持对策略对象的引用
可以定义一个接口,让stategy访问其数据。
使用时间
1) 当你要处理一些仅仅行为不同的相关的类的时候When many related classes differ only in their behaviors. Strategies provide a way to configure a class with one of many behaviors. 2) 当你要隐藏实现细节的时候 When you need to hide complex algorithm details When an algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures. 3) 当你要取消许多条件语句的时候 When you want to cancel many conditional statements When a class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.
为什么要使用策略模式进行设计? 假设在用户在输入一组数据以后,程序将为你根据需要画出你所需要的图表类型。 各种图表,虽表现形式不同,但都显示同一组数据,功能是相同的。可以使用策略模式实现各种图表的显示。 将该根据用户输入的一组数据,利用各种不同的图标显示。为简单起见,我们在本例子中,只使用 条形图(Bar),和 饼图(Pie)。
context实现方式
向策略传递数据:当某算法被调用时,Context类将Strategy类所需要的所有数据一次性地传递完毕
Context将自己作为一个对象传递给Strategy类,然后Strategy类再利用该对象反过来调用Context类,以便获得某些数据与功能
工作机制
首先,客户端通常创建一个ConcreteStrategy对象并将其传递给上下文;
其次,上下文将客户的请求转发给策略。
此后,客户只与上下文交互(目的)。
优点
定义重用的相关算法
容易扩展
缺点
当更改现有算法实现或向组中添加新算法时,现有策略类层次结构和上下文都不受影响。
使用策略模式的设计示例
L6 状态模式【行为模式
关心对象之间的责任分配,侧重描述通信模式
例子
构建一个状态类层次结构,将每个状态封装到一个单独的类中
状态模式
定义客户程序需要的接口 保持状态类型State的引用,程序运行时,Context对象包含当前状态子类对象 可以包含部分业务逻辑
状态:定义一个接口,用于封装与上下文的特定状态相关联的行为。 状态子类:每个子类实现与上下文状态相关联的行为。
使用场合
当对象的行为依赖于状态,而该对象必须根据其状态(在运行时)改变其行为
当操作带有大量状态相关的、多部分的条件语句
协作关系
Context代表状态相关的请求 Context可将自己作为一个对象通过参数传递给状态对象,从而可让状态对象访问Context类的方法
客户对象先创建一个具体的状态子类的对象s,然后,在创建Context对象时,通过参数将s传递给Context对象。此后,客户程序就不必与该状态对象直接交互。 状态转换: Context类或具体的状态子类负责
建议
关于状态的转换的建议: 客户类Client不负责状态转换 客户类只创建一个“种子对象”,然后,传递给Context对象; 再由Context对象根据状态变化的情况,负责创建所有的其它的对象 或由State层次类决定状态的转换
优点
Easy in adding a new state class
它使状态转换显式
设计使用状态模式的例子
交互情况
状态类:负责转换状态,将当前具体状态传递给bankcontext
具体状态类
负责具体操作:存款取款
负责更新bankcontext中的balance
优点
可扩展性好
深入探讨
状态模式
状态相关的行为
状态对象可以负责更新配置给Context类 的状态对象
状态的选择/转换 依赖于Context/State对象
有状态转换
可以将一些业务逻辑包含在context类里面(包含状态转换)
策略模式
不是状态相关的行为,提供的是不同的功能
客户雷闯检测率子类对象传递给context对象
由应用类选择策略子类对象
没有状态转换
可以将一些业务逻辑包含在context类里面(没有状态转换)
L7 访问者模式
行为模式
访问者模式的介绍
某些设计【关于好多层的那一种就是一个集成另一个但是他还有儿子孙子重孙子的那一种】
可维护性差
可扩展性差
改善设计:将具体的计算税收的方法从层次类中分离出来在层次类中保留数据维护方法 分离类的主要功能,即让“Tax”类独立于应用于它们的操作。
将每个子类中的计算功能封装在TaxCalculator类中
进一步改善:为了使上面的设计更加有效
TaxCalculator 改名 visit
所有汇总到计算类中的方法改名为visit×××
在所有层次类中增加visit方法
设计原因 增加访问者方法和接收方法
意图利用这两个方法在层次类和汇总类之间精心的设计接口
相互连接的方式:在客户类中定义访问者对象,并且使用父类定义某个tax层次类对象 通过使用accept方法而不是构造方法将访问对象拉入 将tax层次类对象传入访问者,告知是哪一个访问者来访问
访问者模式类图
为了批量访问元素节点使用了聚合结构包含多个节点
子主题
访问者模式
组件
访问这类:为每一个子类准备一个访问者方法
访问者决定要访问那个类【通过子类对象直接访问接口】
访问者模式构建
实现访问者类中接口中声明的所有操作 每个操作实现为结构中相应的对象类定义的算法片段。
提供算法环境、存储局部状态、积累遍历结构体的结果
元素
定义accept
具体元素
实现accept方法并且还可以实现其他一些方法
ObjectStructure(Program)可以省略
能列举出它的元素。 可以提供一个高级界面,允许访问者访问其元素。 可以是一个组合,也可以是一个集合,比如列表或集合。
该类可以使用一个聚合结构例如 ArrayList或者Vector将被访问对象集合在一起,然后再使用一个循环语句批量调用accept方法。
使用场景
子类种类相对固定
包含很多个子类
不同地类进行不同的操作
类的接口不同
例子
计算机部件销售的例子
在本设计中,使用了CompositeStructure类。ComputerPartsGUI类根据用户请求提交的计算机部件名称, 创建各个相应的部件对象,然后, 将这些对象添加到复合对象CompositeStructure中。 CompositeStructure对象负责接受访问者PriceVisitor对象,对该聚合对象所包含的各个对象访问。
关于组件结构类:封装了长度可以弹性增长的数据结构ArrayList
可以添加许多带访问的对象不必担心数组越界问题
可以负责批量接受访问者需要被访问的对象
典型交互
在以上客户程序的代码实现的中,首先创建了CompositeStructure类的对象, 然后调用了该类的方法accept(PriceVisitor pv) 与accept(InventoryVisitor iv)。 在以上的accept方法中,采用了一个循环语句,但是没有条件语句。也就是说,CompositeStructure类的对象负责将等待访问的Part对象保存,但是并不关心确切地哪个对象被保存了。 当需要接受访问者的时候,使用一个循环语句,遍历所有的待接受访问的对象,使得每个对象都接受访问。
几何形状计算问题
设计
对象结构包含很多个子类; 这些类有不同的接口; 你需要针对不同的类进行不同的操作
深入探讨
使用时间
对象结构包含很多个子类,而这些类有不同的接口。你需要针对不同的类进行不同的操作
许多不同的且不相干的操作需要施加于对象结构,而你想要避免这些不同的操作污染这些类
Visitor让你把相关的操作定义在一个类中(例如,计算总价)。【计算机部件的例子】 当对象结构被许多应用程序共享时,使用Visitor将操作放在那些需要它们的应用程序中。
对象结构类很少改变(例如税收的种类很少改变),但是你需要经常地在这些结构体上增加新的运算(税率可能经常改变)。
注意要点
使用Visitor模式的客户端必须创建一个ConcreteVisitor对象,然后遍历对象结构,使用Visitor访问每个元素。 当访问一个元素时,它调用与它的类相对应的Visitor操作。元素将自身作为此操作的参数提供,以便访问者在必要时访问其状态。
优点
容易添加新的操作
相对的,不容易扩展类,不容易扩展结构
A visitor gathers related operations and separates unrelated ones. (例如,将计算总价格放在一个具体的visitor类中)
Related behavior isn't spread over the classes defining the object structure; it's localized in a visitor. Unrelated sets of behavior are partitioned in their own visitor subclasses.
缺点
Adding new ConcreteElement classes is hard. Each new ConcreteElement gives rise to a new abstract operation on Visitor and a corresponding implementation in every ConcreteVisitor class. ConcreteElementfunctionalities
重点
用于使得被访问者和访问者之间建立自动访问的accept方法,建立了两个层次类之间的关联,使得自动访问成为可能
注: 另外,类objectStructure类对于批量访问很重要。另外使用此类,可以使得客户类包含较少的条件语句。能够有效地做到责任分离。 结论: 要写好accept方法与objectStructure
L8 调停者模式
介绍
机场指挥塔
理论
描述
面向对象应用程序有一些互动的对象组成,当对象比较少的时候对象之间可以相互交互
我们经常这样做,例如 在策略模式和状态模式里面,Context类的对象与Strategy层次类对象的耦合是双向的 在状态模式里面,Context类的对象与State层次类的对象之间的耦合是双向的
而随着对象数目的增加相互直接交互可能会导致混乱
比如说如果增加一个新的类,所有类的接口都需要进行改变
问题
负责方法调用
影响维护
减少复用性
解决:星型拓扑结构——调停模式
实现
Mediator类应该与参与者类(对象A, B, C, … ,H的类)之间有某种形式的关联, 而参与者类之间不应该有关联。
中介者必须拥有register方法
The mediator class must know all the concrete participate colleagues, and so this class needs a register method The register method can be used to let the mediator class keep all the participate objects
每个参与者类必须保持中介者的引用
so that it can call the methods in the mediator class to do something.
组成
程序的构件说明: Mediator:中介者的接口。 ConcreteMediator:具体的中介者,可以有多个具体的中介者。 Colleague:参与者对象接口 Colleague1, Colleague2:具体的参与者。可以有多个具体的参与者。
用途
减少对象之间直接的交互
中介者模式
中介模式表明抽象对象交互细节到一个单独的类,中介类负责所有对象交互 中介维持每个参与者类的引用 中介提供调用参与对象的方法
典型交互
任何两个不同对象之间的交互都通过Mediator类路由。 所有对象将它们的消息发送给中介(调用中介的方法) 然后,中介将消息发送到适当的对象,以实现应用程序的需求(然后在中介中调用每个其他对象的方法)。
Object B calls a method of mediator object. Then mediator object will call methods in objects E、F、G. Objects E, F, G may also call back the methods in Mediator object Mediator object may in turn call other objects 注:Object B may not know which object has been called
优点
参与者类的复用性更好
将对象间依赖关系移出单个对象可以增强对象的可重用性
子主题
参与者对象之间的关系可以由中介者子类对象调节
单元测试【参与者类】
because objects do not need to refer to each other directly
参与者类的修改
allows individual classes to be modified without affecting other classes.
缺点:降低性能
例子
航空宾馆旅游信息系统
三者之间的交互以及协议类型
相同的界面
三家企业信息共享:客户名字身份证号国籍并且有相同的界面搭建
三家企业之间的关系是相互通知的关系
使用中介者模式
负责注册企业【含有每个参与者的引用】
更新每个参与者中的信息
添加可能的顾客
实现细节
写一个中介者类
编写中介类,并声明具有参与中介模式设计的所有对象类型的私有变量 私人hotelGui: hotelGui; 私人airlineGui: airlineGui; 私人tourGui: tourGui
写注册方法
在中介类中,编写所有注册方法来注册所有参与的对象。例如,参与的对象类型应该分别包含在注册方法的参数中 registerHotelGUI (HotelGUI hg) registerAirlineGUI (AirlineGUI ag) registerTourGUI (TourGUI tg)
在每个注册方法内部,将从参数传递的对象赋值给相应的私有成员。例如, registerHotelGUI (HotelGUI hg) { hotelGui = hg; }
注册进了中介者对象中
main方法的实现
Create mediator object. Inside the client class, an object of the mediator class should be created Create participant object. And then the objects for all the participating classes should be created with the just-created object passing in though the parameters
L9 观察者模式
当数据有变化时,OceanData对象通知DataAnalizer对象 调用其中相应的函数
引用
改善调用方式,当数据有变化的时候,被观察者通知观察者,由观察者进行数据更新
大气监测显示的例子:绘制浓度随时间的变化曲线
概念
步骤
1. 注册观察者对象进入被贯彻着的列表【属性】
2. 当有变化的时候通知观察者对象
3. AirDSP 子类对象绘图并显示相应数据
优点:松散的耦合
容易修改代码
当需要修改Air代码的时候,AirDsp层次类不受影响 当需要修改AirDsp代码的时候, Air类不受影响
容易扩展
容易在AirDsp中增加新子类,而 原来已经存在的所有的类都不受影响
观察者模式:对于设计在观察者和被观察对象之间的一致的通信模型有用
使用场景:当你可以吧程序中的对象划分为观察者和被观察者的时候可以使用观察者模式进行设计
观察者:一组依赖于别观察者的对象
类图
双方需要获知的:观察者要知道被观察者的引用,被观察者要有观察者的引用
笔记:一个主题可以有多个观察者,主题包含一个动态列表记录观察者
主题无法维护此类观察者的静态列表,因为给定主题的观察者列表可能会动态变化)。
观察者模式必须包含的活动
Observer / 客户注册 register itself: Any object with interest in the state of the subject needs to explicitly register itself as an observer with the subject. Observable must notify the observers: Whenever the subject undergoes a change in its state, it notifies all of its registered observers. An observer can query about the state of the obsevable:【可以调用一些方法】 Upon receiving notification from the subject, each of the observers queries the subject to synchronize its state with that of the subject’s.
观察者/客户注册登记本身: 任何对主体状态感兴趣的对象都需要显式地将自己注册为主体的观察者
Observable必须通知观察者: 当主体的状态发生变化时,它会通知所有注册的观察者
一个观察者可以查询关于obsevable的状态:【可以调用一些方法】 在收到来自主题的通知后,每个观察者都会查询主题以使其状态与主题的状态同步。
通知观察者的两种策略
观察者模式有很多变形
The push model(将观察者所需数据全部推给观察者, 例如, update(Object a)): The subject should send the state information that the observers may be interested in
The pull model(主题提供接口,供观察者访问,例如 update(Observable obs)): The subject should provide an interface that enables observers to query the subject for the required state information to update their state.
优点
可以动态添加观察者不影响主题
当主题的状态或者逻辑发生变化的时候
如何使用观察者模式
一个对象的状态改变必须反映在另一个对象中,而你又不想让两个对象保持高耦合 你设计的框架将来需要添加许多观察者,而你希望以最小限度地改变程序
Java支持
提供了被观察者类【实现了addObserver、setChanged、notifyObservers方法】
提供了观察者类
实现了既推又拉的方式
例子
温度转换的例子
设计1 用户定义的观察者模式
设计要点:设计两个接口类Observeable和Observer,声明观察者模式所需要的方法
在被观察者中,需要实现的方法:notifyObservers();register(Observer)
在观察者实现类中需要实现的方法是既推又拉的方法
设计2 使用Java API支持的观察者模式
客户类. In the TestObserverObservable, use addObserver(observer:Observer) to add an observer CelsiusGUI, FahrenheitGUI, and KelvinGUI to the TemperatureGUI object 被观察类. In class TemperatureGUI, use setChanged() and notifyObservers() together to notify the observer that the state of the Object TemperatureGUI has changed, and then the update(o: Observable, e: Object) method in CelsiusGUI, FahrenheitGUI, and KelvinGUI objects will be automatically invoked to update display of temperature. In the update method, in turn, observable can be called to check the state change.
客户类. 在TestObserverObservable中,使用addObserver(observer: observer)添加一个观察者CelsiusGUI, FahrenheitGUI和KelvinGUI到TemperatureGUI对象 被观察类. 在类TemperatureGUI中,一起使用setChanged()和notifyObservers()来通知观察者对象TemperatureGUI的状态已经改变 然后CelsiusGUI, FahrenheitGUI和KelvinGUI对象中的更新(o: Observable, e: Object)方法将被自动调用来更新温度显示。 在update方法中,可以反过来调用observable来检查状态的变化。
在client类中,创建被观察者对象、观察者对象并且把观察者对象添加到被观察者对象中,通知观察者
行为模式
行为模式关心算法和对象之间的责任分配。 它关心的不是仅仅描述对象或类的模式,而是要更加侧重描述它们之间的通信模式。 行为模式刻画了很难在运行时跟踪的复杂的控制流。该模式将软件开发者的注意力从控制流转移到对象相互关联的方式方面。
设计模式
L1 MVC 设计模式/体系结构
介绍
MVC设计模式:将来可能会添加一些功能 在输入、信息显示方面
希望能够把所有的业务逻辑都封装到一个类里面
解决方法:使用MVC设计模式
Model:业务逻辑
受到Controller控制
View:输入输出图形界面;用户视图
相互控制
Controller:图形控制器:用户输入
相互控制
理论
架构形模式
在用户和应用程序之间的交互划分成三种角色
相互之间的关联 显式调用、隐式调用或其他机制(例如HTTP协议)
Model的责任:整个业务逻辑
业务逻辑实现
从数据库中读取数据和并将数据存储到java程序中定义的某个变量里面
之后负责数据验证并且将数据缓存如数据库
VIEW
捕捉用户输入
向控制器分发处理请求
显示输出【根据控制器的指示】
Controller
接收来自用户的请求【view过来的、用户控制的请求】
调用model业务逻辑
调用view展示执行结果
两个主要的分离
表示从模型中分离出来
控制器从view中分离出来
数据更新
改变-传播机制
可以由观察者模式实现,保证了用户界面和模型的一致性
如果一个view通过控制其改变了model,那么所有view都必须反应
数据发生变化的时候,model通知所有的view数据改变
views可以遍历model中的数据,以便及时更新显示数据
注意:view可以不必调用Controller,
注意:controller包含model、view的引用,view包含model、controller的引用,Model包含的至于偶view的引用
如果通过观察者模式实现改变传播机制的事后,model就是subject,view是observer
优点
容易增加或者改变视图
容易独立的更新各个独立的软件模块
代码容易开发和维护
业务逻辑容易测试
非可视化比可视化的更容易测试
整体的过程
控制器选择试图并且获取用户输入【controller和view之间的交互】
调用model里面的业务逻辑 controller
Model通知view更新数据
view调用model中的方法获取数据,因为需要更新视图
例子
采用MVC模式使用挂插着机制,用户输入界面两个显示界面分别独立显示
L2 层次结构
概念
层次系统是按照层次组织的,每一层都为上面的一层提供服务并接受下一层的服务
限制:交互仅仅在相邻层按照特定方向进行
典型应用领域
优点
基于逐层增加的抽象级设计,允许实现浙江复杂的问题进一步划分为一系列逐渐增加的抽象级别的步骤
支持更新
支持复用
同一层有不同的实现,只要它们相互支持到相邻的相同接口
通过标准层接口,可以由不同的软件开发团队构建
缺点
不是所有系统都能够很容易的实现通过分层的方式构建
很难找到抽象层次
三层软件架构
运行在互联网上的三层架构:客户端服务器架构
通用三层架构
表现层
图形用户界面
用户输入用户请求用户请求的返回结果等等
调用应用层
但是应用层从来不会调用表示层的功能
应用层
业务逻辑层,主要包含应用的业务逻辑,实现了商用的功能
组件封装了应用的核心数据和功能
不能直接访问数据库,需要调用永久数据存储层的相应功能
永久数据存储层
数据库的访问和永久数据存储到数据库的功能
Java实现中,包含了利用JDBC写的数据库访问代码
不能够调用应用层和现实层,只能将执行应用层的请求所得到的数据库访问结果返回给显示层
三层软件结构和MVC的比较
两种架构相似之处如下: 都是由三部分软件模块组成的 三层架构的显示层与MVC架构的View类似; 三层架构的应用层与MVC架构的Model类似。
区别
各个模块之间的调用关系不同
三层体系结构是线性的
MVC架构是三角形的
view对象放松更新给controller对象,controller更新model对象并且view对象直接的从model对象中获得更新
对于数据库的访问方式不同
MVC架构没有制定专门的数据库访问模块,一般情况下是model,但是controller也可以直接访问数据库
关于控制模块
层次架构中没有,一般是在应用层立面单独指定一个类似的控制模块
其主要责任是接收从显示层输入的用户请求,然后根据请求的类型,决定调用应用层的其它组件。
观察者模式的使用
应用层和表示层之间使用观察者模式
导致应用层对现实层的调用
违背了层次架构的原则
但是这个小小的违规带来的是观察者机制更新图形界面的效率
model和view之间使用
例子学习
自动机器人控制系统
感知
控制
规划路径
L3 主程序-子程序系统与面向对象系统
发展
非结构化编程
使用goto语句
所有代码都在一个主程序里面
引入:迭代、分支和GOTO
缺点
很难追踪程序逻辑; 很难合并其它代码; 修改代码并不容易(都是goto惹的祸); 很难测试特定部分的代码。
结构化编程
定义
子结构、块状结构、循环结构
试图抛弃Goto语句
定理
序列、选择、迭代结构
调用返回体系
他的子类型
主程序和子程序 (main program and subroutine) 体系结构
面向对象系统
通性
采用分割【divide】征服策略
减少复杂度,分成小的系统
调用返回架构执行顺序被单线程控制
具有主函数{PPT17}
软件组件构成的
满足的规则:子程序与附程序之间返回的是控制权
在调用一个子程 序之后,控制权返 回到调用者子程序
软件组件只有得到了控制权之后,才能运行。
主程序和子程序
组成
一个主程序和一些分层组织的子程序组成
主程序调用高层子程序; 高层子程序调用底层子程序
一个子例程的正确性通常取决于它调用的子程序是否正确
子程序:子程序(也称为过程)是较大程序中的一部分代码,它执行特定任务,相对独立于其余代码。子程序是现在的函数与方法的简单情况。
结构化的设计使用自顶向下的功能化设计;C语言的设计风格;
该系统从功能化的角度进行设计,从高级视图开始,逐步细化为更详细的设计【逐步划分,直到函数简单】
系统依赖于一组子程序 (函数),没有对象的概念
优点:自顶向下的方法是非常成功的设计方法 对于10万行以下的代码的程序设计没有问题。
缺点:当程序超过10万行代码的时候,该方法表现很差。
代码开发变得越来越慢; 而且测试软件和保证其可靠性变得越来越困难。
问题
功能化设计不容易进化(可扩展性差) 实际的系统很难按照功能化的观点刻画. 功能化丢失了数据. 功能化设计的程序复用性比较差.
面向对象设计
不是结构化设计
是由对象构成的,不是相互调用的函数组成的,每个对象都有自己的操作集
程序架构
原理/思想/原则:面向对象设计的原理:基于信息隐藏
概念
对象:: An Object is something with a State (i.e., it holds Data), and Semantics (i.e., rules for changing its state).【语义】
性质
封装
继承
动态绑定
指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
复用和维护
其他
对象是现实世界实体的抽象. Objects are abstractions of real-world or system entities and manage themselves 对象之间互相独立. Objects are independent (from encapsulation point of view) 系统功能由对象服务【函数和方法全体】表达. System functionality is expressed in terms of object services (functions) 取消了共享数据区. Shared data areas are eliminated 对象可以是分布式的. Objects may be distributed 对象可以按顺序执行或者并行执行. Objects may execute sequentially or in parallel
例子
L4 数据流系统与批处理架构
数据流的概念
定义:满足以下条件的系统
数据的可用性控制着计算 设计的结构由数据在进程之间的有序运动决定的 数据的模式是明确的
有数据的时候【数据到达的时候被激活,无数据的时候就休眠】
一般来说数据可以按照任意方式流动
关于控制流
关注程序中控制流轨迹
数据可能伴随控制,但是数据不是主导
我们关心程序的执行顺序
设计方面注意事项
数据的流动方式
随着设计的流动,控制被激活
设计的注意事项
数据的可用性
数据变换
数据延迟
数据流开发方法论
将系统分解为一些模块 Decompose system into modules − Abstraction isolates complexity【抽象】 − Operations performed on data objects 将模块组合成图 Compose modules into a graph − Connect modules forming directed graph − Interfaces are negotiated to match data types 运行该图 Run the graph − Data flows between the modules − scheduler automates parallelism − memory manager optimizes memory usage
批处理软件体系结构概念
定义
批处理是由一系列处理步骤构成的
每一步都将会卓一些操作在输入存储上去获得一些有用的信息或者形成资源存储的内容,然后存储最后的结果信息
性质
处理步骤之间是独立的程序,没有交互
每一步需要完整的运行完成之后才能够进行下一步
数据作为一个整体在各个步骤之间传输
理解为特殊的数据流
典型应用
业务数据库处理主要由数据库更新控制:预定类型的离散交易;周期性定期报告;对错误请求的特殊处理。
在批处理中的程序案例
千年虫和政治问题
图像处理
人口信息处理程序
L4-2 管道过滤器架构
概念
管道【传输数据的】+过滤器【对数据进行处理的一个程序】
过滤器功能
添加信息【符合条件的信息添加进去】
变换数据:改变数据的表达形式
流对流变换:变换完之后直接往下写,不保留状态
不保留状态:忘记已经发生的事情
管道动能
中介
单向流
数据传输图
整体运行机制
运行管道与过滤器,一直到没有任何计算Run pipes and filters until no more computations are possible 数据搬运是中介,Action is mediated by data delivery
数据以数据流的方式从左端流入,流经各个过滤器,对数据进行处理;对于处理完的数据,立即写入到下游管道.
例子
千年虫和政治问题
以流的形式写:一次只写一个字符【字符流、数据流】
编译器
编译器示例的典型架构是下一页描述的管道和过滤器架构。
编译原理环节
Unix操作系统
带分支的管道-过滤器架构
对比
批处理:处理过程之间互不调用【与面向对象区别,箭头代表数据流动】
数据处理方式不同
批处理架构,数据以 块状 形式传输, 管道-过滤器架构,数据以 流 的形式传输
所处理的数据量不同
批处理架构,数据量是有限的 管道-过滤器架构,数据量是无限的
优缺点
复用(reuse)性好: It supports reuse, since each filter can function in isolation 容易扩展(Easy evolution): New functions are easily added to the system by inserting filters at the appropriate points in the processing sequence.【别的过滤器不受影响】 容易修改(Easy modification): it’s easy to modify the system since filters are logically independent of other filters.
过滤器之间互不调用
人-机交互差 (Poor Interaction) 纯粹的管道-过滤器架构设计的软件没有人-机交互;但是在实际应用中,可以改善此架构,例如,对于每个过滤器,都可以增加一个用户图像界面 浪费内存 (Waste of space):【现在可能没有了】 由于每个过滤器必须不断地将数据(流)从输入端口复制到其输出端口,因此对于内存空间使用空间效率低下。
L5 案例分析
千年虫和政治问题
不使用goto即可实现任何代码