《软件设计模式》笔记2
六、代理模式
1.模式定义
代理模式(Proxy)为其他对象提供一种代理,以控制对这个对象的访问。
2.模式结构
代理模式包含如下角色:
Subject: 抽象主题角色
Proxy: 代理主题角色
RealSubject: 真实主题角色
3.代理模式的优点
协调调用者和被调用者;
远程代理使得客户端可以访问在远程机器上的对象虚拟代理,可以减少系统资源的消耗,对系统进行优化并提高运行速度;
保护代理可以控制对真实对象的使用权限。
4.代理模式的缺点
有些类型的代理模式可能会造成请求的处理速度变慢。
实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
5.代理模式的类型
远程(Remote)代理、虚拟(Virtual)代理、Copy-on-Write代理、保护(Protect or Access)代理、缓冲(Cache)代理、防火墙(Firewall)代理、同步化(Synchronization)代理、智能引用(Smart Reference)代理
6.应用
论坛权限控制代理、数学运算代理、图片代理——对大图浏览的控制
7.小结
远程代理为一个位于不同的地址空间的对象提供一个本地的代表对象,它使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建,这个小对象称为虚拟代理。虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
保护代理可以控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
七、观察者模式
1.观察者模式(Observer Pattern)
定义对象间的一种一对多依赖关系,让多个观察者对象同时监听一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己
2. 观察者模式包含如下角色
Subject:主题(或抽象通知者、目标)
ConcreteSubject:具体主题(目标)
Observer:观察者
ConcreteObserver: 具体观察者
3.模式分析
观察者模式描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。
这一模式中的关键对象是观察主题和观察者,一个主题可以有任意数目的与之相依赖的观察者,一旦主题的状态发生改变,所有的观察者都将得到通知。
作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与主题状态同步,主题对象是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者接收通知。
4.优点
观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
观察者模式在观察主题和观察者之间建立一个抽象的耦合。
观察者模式支持广播通信。
观察者模式符合“开闭原则”的要求。
5.缺点
抽象主题还是依赖抽象观察者,万一没有了抽象观察者这一接口,通知的功能就完不成。
八、适配器模式
1.适配器模式(Adapter Pattern)
将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作。
2.适配器模式适用环境
系统需要使用现有的类,而这些类的接口不符合系统的需要。
想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
九、单例模式
1.单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.单例模式的要点
(1) 某个类只能有一个实例;
(2)它必须自行创建这个实例;
(3) 它必须自行向整个系统提供这个实例。
单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。
十、设计原则
(一)单一职责原则(Single Responsibility Principle 简称SRP)
1. 核心思想
就一个类而言,应该仅有一个引起它变化的原因。
2. 产生原因
之所以会出现单一职责原则就是因为在软件设计时会出现以下类似情况:T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。也就是说职责P1和P2被耦合在了一起。
3. 解决办法
遵守单一职责原则,将不同的职责封装到不同的类或模块中。
(二)开放——封闭原则(Open Closed Principle,简称OCP)
1. 核心思想
软件实体(类、模块、函数等)应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况;对修改封闭,意味着类一旦设计完成,就不要对类进行任何修改。
2.产生原因
“需求总是变化的”、“世界上没有一个软件是不变的”,因此对于软件设计者来说,必须在不修改原有系统的情况下,实现灵活的系统扩展。
3. 实施办法
只有依赖于抽象。实现开放封闭的基本思路就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和多态机制,可以实现对抽象类的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。
(三)依赖倒转原则( Dependence Inversion Principle ,简称DIP)
核心思想
(1)高层模块不应该依赖低层模块,两者都应该依赖于抽象。
(2)抽象不应该依赖于细节。细节应该依赖抽象(要针对接口编程而不要针对实现编程)。
其中,抽象指抽象类或接口;细节指具体实现类。依赖倒转原则的本质是通过抽象(抽象类或接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合。
(四)里氏代换原则( Liskov Substitution Principle,简称LSP )
1. 核心思想
子类型必须能够替换掉它们的父类型。
可以简单地理解为,一个软件实体如果使用的是一个父类,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。即软件里面把父类都替换成它的子类,程序的行为没有变化。
2.解决方案
当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法。
继承包含这样一层含义:父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
夜雨聆风