Presentation is loading. Please wait.

Presentation is loading. Please wait.

软件建模训练(7) 设计模式 张静 南京理工大学计算机科学与工程学院.

Similar presentations


Presentation on theme: "软件建模训练(7) 设计模式 张静 南京理工大学计算机科学与工程学院."— Presentation transcript:

1 软件建模训练(7) 设计模式 张静 南京理工大学计算机科学与工程学院

2 GoF设计模式简介 范围\目的 创建型模式 结构型模式 行为型模式 类模式 工厂方法模式 (类)适配器模式 解释器模式 模板方法模式
对象模式 抽象工厂模式 建造者模式 原型模式 单例模式 (对象)适配器模式 桥接模式 组合模式 装饰模式 外观模式 享元模式 代理模式 职责链模式 命令模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 访问者模式

3 结构型模式 结构型模式 适配器模式 装饰模式 外观模式

4 结构型模式 结构型模式概述 结构型模式(Structural Pattern)描述如何将类或者对象 结合在一起形成更大的结构,就像搭积木,可以通 过简单积木的组合形成复杂的、功能更为强大的结 构。

5 结构型模式 结构型模式概述 结构型模式可以分为类结构型模式和对象结构型模 式:
类结构型模式关心类的组合,由多个类可以组合成一个 更大的系统,在类结构型模式中一般只存在继承关系和 实现关系。 对象结构型模式关心类与对象的组合,通过关联关系使 得在一个类中定义另一个类的实例对象,然后通过该对 象调用其方法。根据“合成复用原则”,在系统中尽量 使用关联关系来替代继承关系,因此大部分结构型模式 都是对象结构型模式。

6 适配器模式 模式动机

7 适配器模式 模式动机 在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配 器模式。
通常情况下,客户端可以通过目标类的接口访问它所提供的服务。 有时,现有的类可以满足客户类的功能需要,但是它所提供的接口 不一定是客户类所期望的,这可能是因为现有类中方法名与目标类 中定义的方法名不一致等原因所导致的。 在这种情况下,现有的接口需要转化为客户类期望的接口,这样保 证了对现有类的重用。如果不进行这样的转化,客户类就不能利用 现有类所提供的功能,适配器模式可以完成这样的转化。

8 适配器模式 模式动机 在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这 个包装类指的就是适配器(Adapter),它所包装的对象就是适配者 (Adaptee),即被适配的类。 适配器提供客户类需要的接口,适配器的实现就是把客户类的请求 转化为对适配者的相应接口的调用。也就是说:当客户类调用适配 器的方法时,在适配器类的内部将调用适配者类的方法,而这个过 程对客户类是透明的,客户类并不直接访问适配者类。因此,适配 器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适 配器模式的模式动机。

9 适配器模式 模式定义 适配器模式(Adapter Pattern) :将一个接口转换成客 户希望的另一个接口,适配器模式使接口不兼容的 那些类可以一起工作,其别名为包装器(Wrapper)。 适配器模式既可以作为类结构型模式,也可以作为 对象结构型模式。

10 适配器模式 模式结构 类适配器

11 适配器模式 模式结构 适配器模式包含如下角色: Target:目标抽象类 Adapter:适配器类 Adaptee:适配者类
Client:客户类

12 适配器模式 模式分析 典型的类适配器代码: public class Adapter extends Adaptee implements Target { public void request() specificRequest(); }

13 适配器模式 模式分析 典型的对象适配器代码: public class Adapter extends Target {
private Adaptee adaptee; public Adapter(Adaptee adaptee) this.adaptee=adaptee; } public void request() adaptee.specificRequest();

14 适配器模式 适配器模式实例与解析 实例:加密适配器
某系统需要提供一个加密模块,将用户信息(如密码 等机密信息)加密之后再存储在数据库中,系统已经 定义好了数据库操作类。为了提高开发效率,现需要 重用已有的加密算法,这些算法封装在一些由第三方 提供的类中,有些甚至没有源代码。使用适配器模式 设计该加密模块,实现在不修改现有类的基础上重用 第三方加密方法。

15 适配器模式

16 适配器模式 模式优缺点 适配器模式的优点 将目标类和适配者类解耦,通过引入一个适配器类来重 用现有的适配者类,而无须修改原有代码。
增加了类的透明性和复用性,将具体的实现封装在适配 者类中,对于客户端类来说是透明的,而且提高了适配 者的复用性。 灵活性和扩展性都非常好,通过使用配置文件,可以很 方便地更换适配器,也可以在不修改原有代码的基础上 增加新的适配器类,完全符合“开闭原则”。

17 适配器模式 模式优缺点 类适配器模式还具有如下优点: 类适配器模式的缺点如下:
由于适配器类是适配者类的子类,因此可以在适配器类 中置换一些适配者的方法,使得适配器的灵活性更强。 类适配器模式的缺点如下: 对于Java、C#等不支持多重继承的语言,一次最多只能 适配一个适配者类,而且目标抽象类只能为抽象类,不 能为具体类,其使用有一定的局限性,不能将一个适配 者类和它的子类都适配到目标接口。

18 适配器模式 模式优缺点 对象适配器模式还具有如下优点: 对象适配器模式的缺点如下:
一个对象适配器可以把多个不同的适配者适配到同一个 目标,也就是说,同一个适配器可以把适配者类和它的 子类都适配到目标接口。 对象适配器模式的缺点如下: 与类适配器模式相比,要想置换适配者类的方法就不容 易。如果一定要置换掉适配者类的一个或多个方法,就 只好先做一个适配者类的子类,将适配者类的方法置换 掉,然后再把适配者类的子类当做真正的适配者进行适 配,实现过程较为复杂。

19 适配器模式 模式适用环境 在以下情况下可以使用适配器模式: 系统需要使用现有的类,而这些类的接口不符合系统 的需要。
想要建立一个可以重复使用的类,用于与一些彼此之 间没有太大关联的一些类,包括一些可能在将来引进 的类一起工作。

20 适配器模式 模式应用 Sun公司在1996年公开了Java语言的数据库连接工具 JDBC,JDBC使得Java语言程序能够与数据库连接, 并使用SQL语言来查询和操作数据。JDBC给出一个客 户端通用的抽象接口,每一个具体数据库引擎(如 SQL Server、Oracle、MySQL等)的JDBC驱动软件都 是一个介于JDBC接口和数据库引擎接口之间的适配 器软件。抽象的JDBC接口和各个数据库引擎API之间 都需要相应的适配器软件,这就是为各个不同数据 库引擎准备的驱动程序。

21 适配器模式 模式扩展 双向适配器 在对象适配器的使用过程中,如果在适配器中同时包含对目 标类和适配者类的引用,适配者可以通过它调用目标类中的 方法,目标类也可以通过它调用适配者类中的方法,那么该 适配器就是一个双向适配器。

22 适配器模式

23 组合模式 模式动机

24 组合模式 模式动机 对于树形结构,当容器对象(如文件夹)的某一个方 法被调用时,将遍历整个树形结构,寻找也包含这个 方法的成员对象(可以是容器对象,也可以是叶子对 象,如子文件夹和文件)并调用执行。(递归调用) 由于容器对象和叶子对象在功能上的区别,在使用这 些对象的客户端代码中必须有区别地对待容器对象和 叶子对象,而实际上大多数情况下客户端希望一致地 处理它们,因为对于这些对象的区别对待将会使得程 序非常复杂。

25 组合模式 模式动机 组合模式描述了如何将容器对象和叶子对象进行递 归组合,使得用户在使用时无须对它们进行区分, 可以一致地对待容器对象和叶子对象,这就是组合 模式的模式动机。

26 组合模式 模式定义 组合模式(Composite Pattern):组合多个对象形成树形 结构以表示“整体-部分”的结构层次。组合模式对单 个对象(即叶子对象)和组合对象(即容器对象) 的使用具有一致性。 组合模式又可以称为“整体-部分”(Part-Whole)模式, 属于对象的结构模式,它将对象组织到树结构中, 可以用来描述整体与部分的关系。

27 组合模式 模式结构

28 组合模式 模式结构 组合模式包含如下角色: Component: 抽象构件 Leaf: 叶子构件 Composite: 容器构件
Client: 客户类

29 组合模式 模式分析 组合模式的关键是定义了一个抽象构件类,它既 可以代表叶子,又可以代表容器,而客户端针对 该抽象构件类进行编程,无须知道它到底表示的 是叶子还是容器,可以对其进行统一处理。 同时容器对象与抽象构件类之间还建立一个聚合 关联关系,在容器对象中既可以包含叶子,也可 以包含容器,以此实现递归组合,形成一个树形 结构。

30 组合模式 模式分析 文件系统组合模式结构图:

31 组合模式 模式分析 典型的抽象构件角色代码: public abstract class Component {
public abstract void add(Component c); public abstract void remove(Component c); public abstract Component getChild(int i); public abstract void operation(); }

32 组合模式 模式分析 典型的叶子构件角色代码: public class Leaf extends Component {
public void add(Component c) { //异常处理或错误提示 } public void remove(Component c) public Component getChild(int i) public void operation() //实现代码 }

33 组合模式 模式分析 典型的容器构件角色代码: public class Composite extends Component {
private ArrayList list = new ArrayList(); public void add(Component c) list.add(c); } public void remove(Component c) list.remove(c); public Component getChild(int i) (Component)list.get(i); public void operation() for(Object obj:list) ((Component)obj).operation(); 模式分析 典型的容器构件角色代码:

34 组合模式 组合模式实例与解析 实例:文件浏览
文件有不同类型,不同类型的文件其浏览方式有所区 别,如文本文件和图片文件的浏览方式就不相同。对 文件夹的浏览实际上就是对其中所包含文件的浏览, 而客户端可以一致地对文件和文件夹进行操作,无须 关心它们的区别。使用组合模式来模拟文件的浏览操 作。

35 组合模式

36 组合模式 模式优缺点 组合模式的优点 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得 增加新构件也更容易。
客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成 更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去, 可以形成复杂的树形结构。 更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件 而更改原有代码。

37 组合模式 模式优缺点 组合模式的缺点 使设计变得更加抽象,对象的业务规则如果很复杂, 则实现组合模式具有很大挑战性,而且不是所有的方 法都与叶子对象子类都有关联。 增加新构件时可能会产生一些问题,很难对容器中的 构件类型进行限制。

38 组合模式 模式适用环境 在以下情况下可以使用组合模式:
需要表示一个对象整体或部分层次,在具有整体和部 分的层次结构中,希望通过一种方式忽略整体与部分 的差异,可以一致地对待它们。 让客户能够忽略不同对象层次的变化,客户端可以针 对抽象构件编程,无须关心对象层次结构的细节。 对象的结构是动态的并且复杂程度不一样,但客户需 要一致地处理它们。

39 组合模式 模式应用 (1) XML文档解析 <?xml version="1.0"?> <books>
<author>Carson</author> <price format="dollar">31.95</price> <pubdate>05/01/2001</pubdate> </book> <pubinfo> <publisher>MSPress</publisher> <state>WA</state> </pubinfo> </books>

40 组合模式 模式应用 JDK的AWT/Swing是组合模式在Java类库中的一个典型实际应用。

41 装饰模式 模式动机

42 装饰模式 模式动机 一般有两种方式可以实现给一个类或对象增加行为:
继承机制,使用继承机制是给现有类添加功能的一种有 效途径,通过继承一个现有类可以使得子类在拥有自身 方法的同时还拥有父类的方法。但是这种方法是静态的, 用户不能控制增加行为的方式和时机。 关联机制,即将一个类的对象嵌入另一个对象中,由另 一个对象来决定是否调用嵌入对象的行为以便扩展自己 的行为,我们称这个嵌入的对象为装饰器(Decorator)。

43 装饰模式 模式动机 装饰模式以对客户透明的方式动态地给一个对象附 加上更多的责任,换言之,客户端并不会觉得对象 在装饰前和装饰后有什么不同。装饰模式可以在不 需要创造更多子类的情况下,将对象的功能加以扩 展。这就是装饰模式的模式动机。

44 装饰模式 模式定义 装饰模式(Decorator Pattern) :动态地给一个对象增加一 些额外的职责(Responsibility),就增加对象功能来说,装 饰模式比生成子类实现更为灵活。其别名也可以称为包 装器(Wrapper),与适配器模式的别名相同,但它们适用 于不同的场合。根据翻译的不同,装饰模式也有人称之 为“油漆工模式”,它是一种对象结构型模式。

45 装饰模式 模式结构

46 装饰模式 模式结构 装饰模式包含如下角色: Component: 抽象构件 ConcreteComponent: 具体构件
Decorator: 抽象装饰类 ConcreteDecorator: 具体装饰类

47 装饰模式 模式分析 与继承关系相比,关联关系的主要优势在于不会破坏类的封装性, 而且继承是一种耦合度较大的静态关系,无法在程序运行时动态 扩展。在软件开发阶段,关联关系虽然不会比继承关系减少编码 量,但是到了软件维护阶段,由于关联关系使系统具有较好的松 耦合性,因此使得系统更加容易维护。当然,关联关系的缺点是 比继承关系要创建更多的对象。 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方 式动态地给一个对象附加更多的责任。装饰模式可以在不需要创 造更多子类的情况下,将对象的功能加以扩展。

48 装饰模式 模式分析 典型的抽象装饰类代码: public class Decorator extends Component {
private Component component; public Decorator(Component component) this.component=component; } public void operation() component.operation();

49 装饰模式 模式分析 典型的具体装饰类代码: public class ConcreteDecorator extends Decorator
{ public ConcreteDecorator(Component component) super(component); } public void operation() super.operation(); addedBehavior(); public void addedBehavior() //新增方法

50 装饰模式 例子:ThirdParty.Java假定是一个现有的或者第三方的功能,因某种原因我 们不能直接修改,它提供了一个sayMsg()的方法,而我们现在要做的是想在 它的sayMsg()方法中增加一些我们想额外输出的内容,于是我们重写了一个 Decorator.java类。Test.java是客户端测试程序。 IThirdParty.Java--抽象类 ===================== public abstract class IThirdParty { public String sayMsg(); } ThirdParty.Java--具体类 =================== public class ThirdParty extends IThirdParty { public String sayMsg() {   return "hello";   }

51 装饰模式 Decorator.Java--抽象装饰类 Test.java –客户代码 =====================
public class Decorator extends IThirdParty { private IThirdParty iThirdParty; public Decorator (IThirdParty ip) { iThirdParty = ip; } public sayMsg(){ iThirdParty.sayMsg(); Decorator1.Java--具体装饰类 =================== public class Decorator1 extends Decorator { public Decorator1(IThridPart ip) { super(ip) public String sayMsg() {    return super.sayMsg()+“additional msg”;   } Test.java –客户代码 ===================== IthirdParty thirdParty =new ThirdParty(); IthirdParty decorator1 =new Decorator1(thirdParty);   System.out.println(decorator1.sayMsg());

52 装饰模式 模式优缺点 装饰模式的优点 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以 提供比继承更多的灵活性。
可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在 运行时选择不同的装饰器,从而实现不同的行为。 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很 多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功 能更为强大的对象。 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具 体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变, 符合“开闭原则”。

53 装饰模式 模式优缺点 装饰模式的缺点 使用装饰模式进行系统设计时将产生很多小对象,这些 对象的区别在于它们之间相互连接的方式有所不同,而 不是它们的类或者属性值有所不同,同时还将产生很多 具体装饰类。这些装饰类和小对象的产生将增加系统的 复杂度,加大学习与理解的难度。 这种比继承更加灵活机动的特性,也同时意味着装饰模 式比继承更加易于出错,排错也很困难,对于多次装饰 的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

54 装饰模式 模式适用环境 在以下情况下可以使用装饰模式: 在不影响其他对象的情况下,以动态、透明的方式给单 个对象添加职责。
需要动态地给一个对象增加功能,这些功能也可以动态 地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不 利于系统扩展和维护时。不能采用继承的情况主要有两 类:第一类是系统中存在大量独立的扩展,为支持每一 种组合将产生大量的子类,使得子类数目呈爆炸性增长; 第二类是因为类定义不能继承(如final类)。

55 装饰模式 应用 如JList构件本身并不支持直接滚动,即没有滚动条,要创建 可以滚动的列表,可以使用如下代码实现:
在javax.swing包中,可以通过装饰模式动态给一些构件增加新的行为或 改善其外观显示。 如JList构件本身并不支持直接滚动,即没有滚动条,要创建 可以滚动的列表,可以使用如下代码实现: JList list = new JList(); JScrollPane sp = new JScrollPane(list);

56 外观模式 模式动机 引入外观角色之后,用户只需要直接与外观角色交互,用户与子系 统之间的复杂关系由外观角色来实现,从而降低了系统的耦合度。

57 外观模式 模式定义 外观模式(Facade Pattern):外部与一个子系统的通信 必须通过一个统一的外观对象进行,为子系统中的 一组接口提供一个一致的界面,外观模式定义了一 个高层接口,这个接口使得这一子系统更加容易使 用。外观模式又称为门面模式,它是一种对象结构 型模式。

58 外观模式 模式结构

59 外观模式 模式结构 外观模式包含如下角色: Facade: 外观角色 SubSystem:子系统角色

60 外观模式 模式分析 根据“单一职责原则”,在软件中将一个系统划分为若干个子系统有 利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的 通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入 一个外观对象,它为子系统的访问提供了一个简单而单一的入口。 外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以 降低原有系统的复杂度,同时降低客户类与子系统类的耦合度。

61 外观模式 模式分析 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外 观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得 客户端只需要与外观对象打交道,而不需要与子系统内部的很多对 象打交道。 外观模式的目的在于降低系统的复杂程度。 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无 须关心子系统的工作细节,通过外观角色即可调用相关功能。

62 外观模式 模式分析 典型的外观角色代码: public class Facade {
private SubSystemA obj1 = new SubSystemA(); private SubSystemB obj2 = new SubSystemB(); private SubSystemC obj3 = new SubSystemC(); public void method() obj1.method(); obj2.method(); obj3.method(); }

63 外观模式 外观模式实例与解析 实例一:电源总开关
现在考察一个电源总开关的例子,以便进一步说明外观 模式。为了使用方便,一个电源总开关可以控制四盏灯、 一个风扇、一台空调和一台电视机的启动和关闭。通过 该电源总开关可以同时控制上述所有电器设备,使用外 观模式设计该系统。

64 外观模式 外观模式实例与解析 实例一:电源总开关

65 模式优缺点 外观模式的优点 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用 起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联 的对象也很少。 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会 影响到调用它的客户类,只需要调整外观类即可。 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的 移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一 个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不 会影响到外观对象。 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统 类。

66 外观模式 模式优缺点 外观模式的缺点 不能很好地限制客户使用子系统类,如果对客户访问子 系统类做太多的限制则减少了可变性和灵活性。
在不引入抽象外观类的情况下,增加新的子系统可能需 要修改外观类或客户端的源代码,违背了“开闭原则”。

67 外观模式 模式适用环境 在以下情况下可以使用外观模式:
当要为一个复杂子系统提供一个简单接口时可以使用外 观模式。该接口可以满足大多数用户的需求,而且用户 也可以越过外观类直接访问子系统。 客户程序与多个子系统之间存在很大的依赖性。引入外 观类将子系统与客户以及其他子系统解耦,可以提高子 系统的独立性和可移植性。 在层次化结构中,可以使用外观模式定义系统中每一层 的入口,层与层之间不直接产生联系,而通过外观类建 立联系,降低层之间的耦合度。

68 外观模式 模式扩展 一个系统有多个外观类 在外观模式中,通常只需要一个外观类,并且此外观类 只有一个实例,换言之它是一个单例类。在很多情况下 为了节约系统资源,一般将外观类设计为单例类。当然 这并不意味着在整个系统里只能有一个外观类,在一个 系统中可以设计多个外观类,每个外观类都负责和一些 特定的子系统交互,向用户提供相应的业务功能。

69 外观模式 模式扩展 不要试图通过外观类为子系统增加新行为
不要通过继承一个外观类在子系统中加入新的行为,这 种做法是错误的。外观模式的用意是为子系统提供一个 集中化和简化的沟通渠道,而不是向子系统加入新的行 为,新的行为的增加应该通过修改原有子系统类或增加 新的子系统类来实现,不能通过外观类来实现。

70 外观模式 模式扩展 外观模式与迪米特法则 外观模式创造出一个外观对象,将客户端所涉及的属于 一个子系统的协作伙伴的数量减到最少,使得客户端与 子系统内部的对象的相互作用被外观对象所取代。外观 类充当了客户类与子系统类之间的“第三者”,降低了 客户类与子系统类之间的耦合度,外观模式就是实现代 码重构以便达到“迪米特法则”要求的一个强有力的武 器。

71 外观模式 模式扩展 抽象外观类的引入 外观模式最大的缺点在于违背了“开闭原则”,当增加 新的子系统或者移除子系统时需要修改外观类,可以通 过引入抽象外观类在一定程度上解决该问题,客户端针 对抽象外观类进行编程。对于新的业务需求,不修改原 有外观类,而对应增加一个新的具体外观类,由新的具 体外观类来关联新的子系统对象,同时通过修改配置文 件来达到不修改源代码并更换外观类的目的。

72 外观模式

73 行为型模式 行为型模式概述 责任链模式 观察者模式 策略模式

74 行为型模式 行为型模式概述 行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任 和算法的抽象化。
行为型模式不仅仅关注类和对象的结构,而且重点关注它们之 间的相互作用。 通过行为型模式,可以更加清晰地划分类与对象的职责,并研 究系统在运行时实例对象之间的交互。在系统运行时,对象并 不是孤立的,它们可以通过相互通信与协作完成某些复杂功能, 一个对象在运行时也将影响到其他对象的运行。

75 行为型模式 行为型模式概述 行为型模式分为类行为型模式和对象行为型模式 两种:
类行为型模式:类的行为型模式使用继承关系在几个 类之间分配行为,类行为型模式主要通过多态等方式 来分配父类与子类的职责。 对象行为型模式:对象的行为型模式则使用对象的聚 合关联关系来分配行为,对象行为型模式主要是通过 对象关联等方式来分配两个或多个类的职责。根据“合 成复用原则”,系统中要尽量使用关联关系来取代继承 关系,因此大部分行为型设计模式都属于对象行为型 设计模式。

76 行为型模式 行为型模式简介 职责链模式(Chain of Responsibility) 命令模式(Command)
解释器模式(Interpreter) 迭代器模式(Iterator) 中介者模式(Mediator) 备忘录模式(Memento) 观察者模式(Observer) 状态模式(State) 策略模式(Strategy) 模板方法模式(Template Method) 访问者模式(Visitor)

77 责任链模式 模式动机

78 责任链模式 模式动机 职责链可以是一条直线、一个环或者一个树形结构,最常见的 职责链是直线型,即沿着一条单向的链来传递请求。
链上的每一个对象都是请求处理者,职责链模式可以将请求的 处理者组织成一条链,并使请求沿着链传递,由链上的处理者 对请求进行相应的处理,客户端无须关心请求的处理细节以及 请求的传递,只需将请求发送到链上即可,将请求的发送者和 请求的处理者解耦。这就是职责链模式的模式动机。

79 责任链模式 模式定义 职责链模式(Chain of Responsibility Pattern):避免请求 发送者与接收者耦合在一起,让多个对象都有可能 接收请求,将这些对象连接成一条链,并且沿着这 条链传递请求,直到有对象处理它为止。由于英文 翻译的不同,职责链模式又称为责任链模式,它是 一种对象行为型模式。

80 责任链模式 模式结构

81 责任链模式 模式结构 职责链模式包含如下角色: Handler: 抽象处理者 ConcreteHandler: 具体处理者
Client: 客户类

82 责任链模式 模式分析 在职责链模式里,很多对象由每一个对象对其下家的引用 而连接起来形成一条链。
请求在这条链上传递,直到链上的某一个对象处理此请求 为止。 发出这个请求的客户端并不知道链上的哪一个对象最终处 理这个请求,这使得系统可以在不影响客户端的情况下动 态地重新组织链和分配责任。

83 责任链模式 模式分析 典型的抽象处理者代码: public abstract class Handler {
protected Handler successor; public void setSuccessor(Handler successor) this.successor=successor; } public abstract void handleRequest(String request);

84 责任链模式 模式分析 典型的具体处理者代码: public class ConcreteHandler extends Handler {
public void handleRequest(String request) if(请求request满足条件) //处理请求; } else this.successor.handleRequest(request); //转发请求

85 责任链模式 职责链模式实例与解析 实例:审批假条
某OA系统需要提供一个假条审批的模块,如果员工请 假天数小于3天,主任可以审批该假条;如果员工请假 天数大于等于3天,小于10天,经理可以审批;如果员 工请假天数大于等于10天,小于30天,总经理可以审 批;如果超过30天,总经理也不能审批,提示相应的拒 绝信息。

86 责任链模式 职责链模式实例与解析 实例:审批假条

87 责任链模式 模式优缺点 职责链模式的优点 降低耦合度 可简化对象的相互连接 增强给对象指派职责的灵活性 增加新的请求处理类很方便

88 责任链模式 模式优缺点 职责链模式的缺点 不能保证请求一定被接收。
系统性能将受到一定影响,而且在进行代码调试时不 太方便;可能会造成循环调用。

89 责任链模式 模式适用环境 在以下情况下可以使用职责链模式: 有多个对象可以处理同一个请求,具体哪个对象处理 该请求由运行时刻自动确定。
在不明确指定接收者的情况下,向多个对象中的一个 提交一个请求。 可动态指定一组对象处理请求。

90 责任链模式 模式应用 Java中的异常处理机制 try { …… }
catch(ArrayIndexOutOfBoundsException e1) catch(ArithmeticException e2) catch(IOException e3) finally

91 观察者模式 模式动机

92 观察者模式 模式动机 建立一种对象与对象之间的依赖关系,一个对象发 生改变时将自动通知其他对象,其他对象将相应做 出反应。在此,发生改变的对象称为观察目标,而 被通知的对象称为观察者,一个观察目标可以对应 多个观察者,而且这些观察者之间没有相互联系, 可以根据需要增加和删除观察者,使得系统更易于 扩展,这就是观察者模式的模式动机。

93 观察者模式 模式定义 观察者模式(Observer Pattern):定义对象间的一种一 对多依赖关系,使得每当一个对象状态发生改变时, 其相关依赖对象皆得到通知并被自动更新。观察者 模式又叫做发布-订阅(Publish/Subscribe)模式、模 型-视图(Model/View)模式、源-监听器 (Source/Listener)模式或从属者(Dependents)模式。 观察者模式是一种对象行为型模式。

94 观察者模式 模式结构

95 观察者模式 模式结构 观察者模式包含如下角色: Subject: 目标 ConcreteSubject: 具体目标
Observer: 观察者 ConcreteObserver: 具体观察者

96 观察者模式 模式分析 观察者模式描述了如何建立对象与对象之间的依赖关系,如何构 造满足这种需求的系统。
这一模式中的关键对象是观察目标和观察者,一个目标可以有任 意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有 的观察者都将得到通知。 作为对这个通知的响应,每个观察者都将即时更新自己的状态, 以与目标状态同步,这种交互也称为发布-订阅(publish-subscribe)。 目标是通知的发布者,它发出通知时并不需要知道谁是它的观察 者,可以有任意数目的观察者订阅它并接收通知。

97 观察者模式 模式分析 典型的抽象目标类代码如下所示: import java.util.*;
public abstract class Subject { protected ArrayList observers = new ArrayList(); public abstract void attach(Observer observer); public abstract void detach(Observer observer); public abstract void notify(); }

98 观察者模式 模式分析 典型的具体目标类代码如下所示:
public class ConcreteSubject extends Subject { public void attach(Observer observer) observers.add(observer); } public void detach(Observer observer) observers.remove(observer); public void notify() for(Object obs:observers) ((Observer)obs).update();

99 观察者模式 模式分析 典型的抽象观察者代码如下所示: public interface Observer {
public void update(); }

100 观察者模式 模式分析 典型的具体观察者代码如下所示:
public class ConcreteObserver implements Observer { public void update() //具体更新代码 }

101 观察者模式 模式分析 Subject subject = new ConcreteSubject();
客户端代码片段如下所示: Subject subject = new ConcreteSubject(); Observer observer = new ConcreteObserver(); subject.attach(observer); subject.notify();

102 观察者模式 模式分析 观察者模式顺序图如下所示:

103 观察者模式 观察者模式实例与解析 实例一:猫、狗与老鼠
假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫 叫老鼠跑,狗也跟着叫,使用观察者模式描述该过程。

104 观察者模式 观察者模式实例与解析 实例一:猫、狗与老鼠

105 观察者模式 模式优缺点 观察者模式的优点 观察者模式可以实现表示层和数据逻辑层的分离,并定义了 稳定的消息更新传递机制,抽象了更新接口,使得可以有各 种各样不同的表示层作为具体观察者角色。 观察者模式在观察目标和观察者之间建立一个抽象的耦合。 观察者模式支持广播通信。 观察者模式符合“开闭原则”的要求。

106 观察者模式 模式优缺点 观察者模式的缺点 如果一个观察目标对象有很多直接和间接的观察者的话,将 所有的观察者都通知到会花费很多时间。
如果在观察者和观察目标之间有循环依赖的话,观察目标会 触发它们之间进行循环调用,可能导致系统崩溃。 观察者模式没有相应的机制让观察者知道所观察的目标对象 是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

107 观察者模式 模式适用环境 在以下情况下可以使用观察者模式: 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。 将这些方面封装在独立的对象中使它们可以各自独立地改变 和复用。 一个对象的改变将导致其他一个或多个对象也发生改变,而 不知道具体有多少对象将发生改变,可以降低对象之间的耦 合度。 一个对象必须通知其他对象,而并不知道这些对象是谁。 需要在系统中创建一个触发链,A对象的行为将影响B对象, B对象的行为将影响C对象……,可以使用观察者模式创建 一种链式触发机制。

108 观察者模式 模式应用 JDK1.1版本及以后的各个版本中,事件处理模型采用基于观察者模 式的委派事件模型(Delegation Event Model, DEM)。 在DEM中,事件的发布者称为事件源(Event Source),而订阅者叫做事 件监听器(Event Listener),在这个过程中还可以通过事件对象(Event Object)来传递与事件相关的信息,可以在事件监听者的实现类中实 现事件处理,因此事件监听对象又可以称为事件处理对象。 事件源对象、事件监听对象(事件处理对象)和事件对象构成了 Java事件处理模型的三要素。

109 观察者模式 模式扩展 Java语言提供的对观察者模式的支持
在JDK的java.util包中,提供了Observable类以及Observer 接口,它们构成了Java语言对观察者模式的支持。

110 策略模式 模式动机 完成一项任务,往往可以有多种不同的方式,每一 种方式称为一个策略,我们可以根据环境或者条件 的不同选择不同的策略来完成该项任务。 在软件开发中也常常遇到类似的情况,实现某一个 功能有多个途径,此时可以使用一种设计模式来使 得系统可以灵活地选择解决途径,也能够方便地增 加新的解决途径。

111 策略模式 模式动机

112 策略模式 模式动机 在软件系统中,有许多算法可以实现某一功能,如查找、排序等, 一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种 查找算法,可以将这些算法写到一个类中,在该类中提供多个方法, 每一个方法对应一个具体的查找算法;当然也可以将这些查找算法 封装在一个统一的方法中,通过if…else…等条件判断语句来进行选 择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种 新的查找算法,需要修改封装算法类的源代码;更换查找算法,也 需要修改客户端调用代码。在这个算法类中封装了大量查找算法, 该类代码将较复杂,维护较为困难。

113 策略模式 模式动机 除了提供专门的查找算法类之外,还可以在客户端程序中直接包含 算法代码,这种做法更不可取,将导致客户端程序庞大而且难以维 护,如果存在大量可供选择的算法时问题将变得更加严重。 为了解决这些问题,可以定义一些独立的类来封装不同的算法,每 一个类封装一个具体的算法,在这里,每一个封装算法的类我们都 可以称之为策略(Strategy),为了保证这些策略的一致性,一般会用 一个抽象的策略类来做算法的定义,而具体每种算法则对应于一个 具体策略类。

114 策略模式 模式定义 策略模式(Strategy Pattern):定义一系列算法,将每 一个算法封装起来,并让它们可以相互替换。策略 模式让算法独立于使用它的客户而变化,也称为政 策模式(Policy)。策略模式是一种对象行为型模式。

115 策略模式 模式结构

116 策略模式 模式结构 策略模式包含如下角色: Context: 环境类 Strategy: 抽象策略类
ConcreteStrategy: 具体策略类

117 策略模式 模式分析 策略模式是一个比较容易理解和使用的设计模式, 策略模式是对算法的封装,它把算法的责任和算 法本身分割开,委派给不同的对象管理。策略模 式通常把一个系列的算法封装到一系列的策略类 里面,作为一个抽象策略类的子类。用一句话来 说,就是“准备一组算法,并将每一个算法封装起 来,使得它们可以互换”。

118 策略模式 模式分析 不使用策略模式的代码: public class Context { ……
public void algorithm(String type) ...... if(type == "strategyA") //算法A } else if(type == "strategyB") //算法B else if(type == "strategyC") //算法C

119 策略模式 模式分析 public abstract class AbstractStrategy {
重构之后的抽象策略类: public abstract class AbstractStrategy { public abstract void algorithm(); }

120 策略模式 模式分析 客户端代码片段: …… Context context = new Context();
AbstractStrategy strategy; strategy = new ConcreteStrategyA(); context.setStrategy(strategy); context.algorithm();

121 策略模式 模式分析 在策略模式中,应当由客户端自己决定在什么情况下使用什么具 体策略角色。
策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老 算法从系统中“退休”的方便,策略模式并不决定在何时使用何种 算法,算法的选择由客户端来决定。这在一定程度上提高了系统 的灵活性,但是客户端需要理解所有具体策略类之间的区别,以 便选择合适的算法,这也是策略模式的缺点之一,在一定程度上 增加了客户端的使用难度。

122 策略模式 策略模式实例与解析 实例一:排序策略
某系统提供了一个用于对数组数据进行操作的类,该类 封装了对数组的常见操作,如查找数组元素、对数组元 素进行排序等。现以排序操作为例,使用策略模式设计 该数组操作类,使得客户端可以动态地更换排序算法, 可以根据需要选择冒泡排序或选择排序或插入排序,也 能够灵活地增加新的排序算法。

123 策略模式 策略模式实例与解析 实例一:排序策略

124 策略模式 模式优缺点 策略模式的优点 策略模式提供了对“开闭原则”的完美支持,用户可以在不修 改原有系统的基础上选择算法或行为,也可以灵活地增加新 的算法或行为。 策略模式提供了管理相关的算法族的办法。 策略模式提供了可以替换继承关系的办法。 使用策略模式可以避免使用多重条件转移语句。

125 策略模式 模式优缺点 策略模式的缺点 客户端必须知道所有的策略类,并自行决定使用哪一 个策略类。
策略模式将造成产生很多策略类,可以通过使用享元 模式在一定程度上减少对象的数量。

126 策略模式 模式适用环境 在以下情况下可以使用策略模式:
如果在一个系统里面有许多类,它们之间的区别仅在于 它们的行为,那么使用策略模式可以动态地让一个对象 在许多行为中选择一种行为。 一个系统需要动态地在几种算法中选择一种。 如果一个对象有很多的行为,如果不用恰当的模式,这 些行为就只好使用多重的条件选择语句来实现。 不希望客户端知道复杂的、与算法相关的数据结构,在 具体策略类中封装算法和相关的数据结构,提高算法的 保密性与安全性。


Download ppt "软件建模训练(7) 设计模式 张静 南京理工大学计算机科学与工程学院."

Similar presentations


Ads by Google