适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用情况
系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
适配器类型
- 类适配器模式
类适配器模式需要通过多重继承对一个接口与另一个接口进行匹配。 - 对象适配器模式
注意
- 在双方都不太容易修改的时候在使用适配器模式
所以适配器模式一般是在软件开发后期或维护期使用。 - 或者考虑使用第三方开发组件时,使用适配器模式
假如这套组件的接口跟原系统的接口不相同,但是没有必要去更改原系统的接口,这样就可以通过适配器模式来兼容接口。
装饰模式
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
解决问题
- 违反了
开放-封闭原则
当系统需要新功能的时候,是向旧的类添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。 - 增加了原来代码的复杂度
在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。
适用情况
为已有功能动态地添加更多功能的一种方式。
实现方法
把每个要装饰的功能放在单独的类中,并让这个类包装它所要修饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装了对象。
/**
* 定义了一个对象接口
* 可以给这些对象动态地添加职责
*/
public interface Component {
void operation();
}
/**
* 定义了一个具体的对象
* 可以给这个对象添加一些职责
*/
public class ConcreteComponent implements Component {
@Override
public void operation() {
//具体对象的操作
}
}
/**
* 装饰抽象类
* 继承了Component,从外类来扩展Component类的功能
* 对于Component来说,无需知道Decorator的存在
*/
public class Decorator implements Component {
protected Component component;
public void setComponent(Component component) {
this.component = component;
}
@Override
public void operation() {
if (component != null) {
component.Operation();
}
}
}
/**
* 具体的装饰对象,起到对Component添加职责的功能
* addedState为这个装饰对象专有的成员对象
* 可以在operaction()方法中使用这个成员对象
*/
public class ConcretDecoratorA implements Decorator {
private String addedState;
@Override
public void operation() {
super.operation();
//do something with the added state
}
}
/**
* 具体的装饰对象,起到对Component添加职责的功能
* addedBehaviour()为这个装饰对象专有的成员方法
* 可以在operaction()方法中使用这个成员方法
*/
public class ConcretDecoratorB implements Decorator {
@Override
public void operation() {
super.operation();
//do something with the added behaviour
}
private void addedBehaviour() {
//added behaviour
}
}
代理模式
为其他对象提供一种代理以控制对这个对象的访问。
使用场合
- 远程代理
为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。 - 虚拟代理
针对需要创建开销很大的对象。通过代理来存放实例化需要很长时间的真实对象。 - 安全代理
用来控制真实对象访问时的权限。 - 智能指引
值当调用真实的对象时,代理处理另外一些事。
外观模式
为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
使用场合
在设计初期阶段,应该有意识的将不同的两个层分离
例如经典的MVC三层架构,就是在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade。
这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。开发阶段,子系统往往因为不断的重构演化变得越来越复杂
增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。在维护一个遗留的大型系统时
可能这个系统已经非常难以维护和扩展,而新的寻求开发必须要依赖它。可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。
桥接模式
将抽象部分与它的实现部分分离,是它们都可以独立地变化。
即用聚合跟组合来代替继承关系,遵循了合成/聚合复用原则
。
适用情况
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系
- 设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的
- 一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合
- 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者
组合模式
将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
适用场合
需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时。
好处
- 结构分层
组合模式定义和包含了基本对象和组合对象的类层级结构。基本对象可以被组合成更复杂的组合对象,而这个对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以用到组合对象了。 - 用户透明性
用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句。 - 一致
让客户可以一致地使用组合结构和单个对象。
享元模式
运用共享技术有效地支持大量细粒度的对象。