为何需要模式?
模式 是做事的方法,是实现目标、研磨技术的方法。
它是 思想的体现,非具体的实现。
为何需要设计模式?
设计模式是一种模式,在面向对象的语言中,它运用类与它们的方法来达到目标。
设计模式提升了代码的水准,使之简洁而实用,通常会使用更少的类完成目标。
设计模式的组织
任何模式的核心要素还在于它的意图,这才是运用模式的潜在价值。
设计模式的意图在于用更为简便的方式来表达需求,而这些通常是Java提供的常规机制所无法满足的。
- 接口型模式
- 职责型模式
- 构造型模式
- 操作型模式
- 扩展型模式
接口型模式
类的接口,是类允许其他类对象访问的方法与字段集。
接口通常代表一种承诺,即方法需要实现接口方法名表示的操作,遵循代码注释、测试和其他文档说明。
Java将接口概念提升为独立的结构,体现了接口(对象必须遵循的承诺)与实现(对象如何履行承诺)的分离。
抽象类与接口的区别
- 前者会有具体方法;
- 前者允许存在字段;
- 前者有构造器;
- 可见性的级别;
- extend & implement...
接口与职责
Java接口的优势在于它限制了对象之间的协作,这种约束其实提供了更大的自由,即使实现接口的类的实现发生了巨大变化,接口的客户端仍然可以不受影响。
Stub:即提供空实现的接口实现类,然后在子类中重写对应用程序具有重要意义的接口方法。
超越普通接口
如果你期望 | 可运用模式 |
---|---|
适配类的接口以匹配客户端期待的接口 | 适配器模式 |
为一组类提供一个简单接口 | 外观模式 |
为单个对象与复合对象提供统一的接口 | 合成模式 |
解除抽象与实现之间的耦合,使得两者能够独立演化 | 桥接模式 |
职责型模式
面向指责的模式提供了用于集中、加强以及限制普通对象责任的技术。
常规的职责型模式
属性与职责应该统一在一起。
在面向对象的系统中,职责的合理分配所建立的原则,是意义非凡的:
每个类和方法都应该清晰地定义了它的职责,并且被正确地得到使用。
根据可见性控制职责
限制类、字段和方法的可见性,从而去限制其它开发人员对你所开发代码的调用。
一个对象是能引用该类其它实例的私有成员的,因为修饰符的限定是在类级别。
超越普通职责
面向对象开发通常都会将职责分散到各个独立的对象中;面向对象开发促进了封装,封装是指对象基于自己的数据进行操作。
职责分离是一种常规的做法。
如果你的意图是 | 适用的模式 |
---|---|
将责任集中到某个类的实例中 | 单例模式 |
将对象从依赖于它的对象中解耦 | 观察者模式 |
将职责集中在某个类,该类可以监督其它对象的交互 | 调停者模式 |
让一个对象扮演其它对象的行为 | 代理模式 |
允许将请求传递给职责链的其它对象,直到这个请求被某个对象处理 | 职责链模式 |
将共享的、细粒度的对象职责集中管理 | 享元模式 |
构造型模式
超出常规的构造函数
如果你的意图是 | 使用的模式 |
---|---|
在请求创建对象前,逐步收集创建对象需要的信息 | 构造者模式 |
决定推迟实例化类对象 | 工厂方法模式 |
创建一族具有某些共同特征的对象 | 抽象工厂模式 |
根据现有对象创建一个新的对象 | 原型模式 |
通过包含了对象内部状态的静态版本重新构建一个对象 | 备忘录模式 |
操作型模式
Java方法 级别:高于单行代码的一个基本单元
涉及:整体设计、架构以及测试计划 实现:面向对象编程的中心环节
但是方法是什么?它是如何工作的?
操作和方法
- 操作:一个服务的规格说明,它可以被类的实例调用。
- 方法:操作的实现。
这意味着操作是方法的一种抽象。
操作表示类做了什么,还表示服务提供的接口。不同的类可能用不同的方法实现同样的操作。
在Java语言中,方法的声明包括方法头和方法体两部分。
- 方法体是一系列的指令,可以通过调用方法的签名来执行。
- 方法头包括方法的返回类型以及方法签名,还可能包含访问修饰符与异常语句。
签名
方法的签名包括方法名、传入参数的数量以及类型。
- 方法签名:代表了客户调用的方法;
- 操作:是可以被请求的服务规格。
两者的区别主要在于它们的不同应用场景:
- 当涉及不同类中的方法拥有相同的接口时,使用“操作”;
- 当涉及如何将Java方法调用匹配到接受对象的方法上时,使用“签名”。
签名依赖于方法的名字和参数,但是不依赖于方法的返回类型。
异常
….
算法和多态
算法是已经定义好的计算程序,将数据或者数据集作为输入,将产生的数据或者数据集作为输出。
算法是一个过程-----一个有输入和输出的指令序列。
算法完成了一些事情,它可能是方法的一部分,也可能调用了很多方法。
在面向对象的设计中,需要多个方法参与的算法通常依赖于多态,因为
多态机制允许一个操作具有多个不同的实现。
多态是一个既依赖于调用的操作,又依赖于调用接收者类型的一种方法调用的原则。
通俗地讲,多态是指合适的对象调用合适的方法。
小节
操作和签名一样,是服务的规格说明;操作意味着许多方法拥有相同的接口;签名意味着方法的查询规则;方法的定义包括它的签名——方法名和参数列表,以及访问修饰符、返回类型与方法体。方法拥有签名和操作的实现。
超越常规的操作
Java支持多态:不同类在实现同一个操作时采用不同的方式;这被多种设计模式所使用。
如果你的意图是 | 使用的模式 |
---|---|
在方法中实现算法,推迟对算法步骤的定义使得子类能够重新实现 | 模版方法模式 |
将操作分散,使得每个类都能够表示不同的状态 | 状态模式 |
封装操作,使得实现是可以互相替换的 | 策略模式 |
用对象来封装方法调用 | 命令模式 |
将操作分散,使得每个实现能够运用到不同类型的集合中 | 解释器模式 |
扩展型模式
Java编程本身就是一种扩展。
扩展代码库的常见技术:…...;使用设计模式添加新的行为
面向对象设计的原则
Liskov替换原则
它的主要思想是:一个类的实例应该具有其父类的所有功能。
迪米特法则
消除代码的坏味道
超越常规的扩展
面向扩展的模式通常涉及两种开发角色。
例子 | 使用的模式 |
---|---|
某个烟火模拟器的设计者设计了一个接口,要求所建立的对象必须实现该接口,以便于参与模拟 | 适配器模式 |
允许在运行时组合可执行对象的工具集 | 解释器模式 |
父类提供了一个方法,要求子类来实现其中的一些步骤 | 模版方法模式 |
一个对象允许扩展它的行为,通过对象中封装的方法,并且在合适的时机来调用 | 命令模式 |
通过代码生成器来插入某些行为,以便形成模拟对象在本季执行的假象 | 带咯模式 |
该设计允许注册一些回调方法,并且在对象发生变化时触发 | 观察者模式 |
该设计允许提供已经定义好接口的抽象操作,并且能够添加实现该接口的新驱动器 | 桥接模式 |
如果你的意图是 | 使用该模式 |
---|---|
让开发者动态组合的行为 | 装饰器模式 |
提供一个方法来顺序访问集合中的元素 | 迭代器模式 |
允许开发者定义一个新的操作,而无须改变分层体系中的类 | 访问者模式 |
小节
编写代码的主要目的是扩展新的功能,这需要重新组织代码,改善代码的质量。需要学会面向对象的一些好的设计原则。
Liskov替换原则要求子类的实例应该具有父类的全部功能,应该能够识别和评估违反该原则的代码;迪米特法则是一组规则,可以降低类之间的依赖,使代码变得更加整洁。