面向对象设计模式(23种总结)-装饰模式
概述:设计模式的定义
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
计模式的基本要素
设计模式一般有如下几个基本要素:模式名称、问题、目的、解决方案、效果、实例代码和相关设计模式,其中的关键元素包括以下四个方面:
- 模式名称 (
Pattern name
) - 问题 (
Problem
) - 解决方案 (
Solution
) - 效果 (
Consequences
)
GoF模式简要说明
模式类别 | 模式名称 | 模式说明 |
---|---|---|
创建型 | 抽象工厂 | 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 |
工厂方法 | 定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。 | |
单例模式 | 保证一个类仅有一个实例,而且自行实例化并且向这个系统提供这个实例 | |
建造者模式 | 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 | |
原型模式 | 通过给出一个原型对象来指明所需要创建的对象类型,然后通过复制这个原型对象的办法来创建更多同类型的对象 | |
结构型 | Adapter ( 适配器模式 ) | 将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容的那些类可以一起工作。 |
桥接模式 | 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 | |
组合模式 | 通过组合多个对象形成树形结构以表示"部分-整体"的层次结构。对单个对象和组合对象的使用具有一致性。 | |
装饰模式 | 动态地给一个对象添加一些额外的职责。 | |
享元模式 | 运用共享技术有效地支持大量细粒度的对象 | |
代理模式 | 为其他对象提供一种代理以控制对这个对象的访问。 | |
行为型 | 责任链模式 | 避免请求的发送者和接收者耦合在一起,让多个对象都有可能接受请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。 |
命令模式 | 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。 | |
解释器模式 | 描述如何为一个语言定义一个文法,如何咋在该语言中定义一个句子,以及如何解释这些句子 | |
迭代器模式 | 提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示 | |
备忘录模式 | 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 | |
中介者模式 | 通过中介对象来封装一系列的对象交互。使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 | |
观察者模式 | 定义对象间的一种一对多的依赖关系,使得每当一个对象的状态发生改变时,其依赖对象都得到通知并被自动更新。 | |
状态模式 | 允许一个对象在其内部状态发生改变时改变它的行为 | |
策略模式 | 定义一系列的算法并将每个算法封装起来,并使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 | |
模板方法 | 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中 | |
访问者模式 | 一个作用于某对象结构中的各元素的操作。 它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 |
设计模式的分类
根据其目的(模式是用来做什么的)可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三种:
- 创建型模式主要用于创建对象。
- 结构型模式主要用于处理类或对象的组合。
- 行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。
1.装饰模式
模式动机
有两种方式可以实现给一个类或对象增加行为:
**继承机制:**使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。java不支持多继承。
关联机制: 即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)。
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机
模式结构
装饰模式包含如下角色:
- Component: 抽象构件
- ConcreteComponent: 具体构件
- Decorator: 抽象装饰类
- ConcreteDecorator: 具体装饰类
模式分析
package 结构模型结构图;
public abstract class Component {
public void operation(){};
}
class ConcreteComponent extends Component {
@Override
public void operation(){
System.out.println("This is a ConcreteComponent.");
}
}
class Decorator extends Component{
private Component component;
@Override
public void operation() {
component.operation();
}
public Decorator(Component component) {
this.component = component;
}
}
class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedBehavior();
}
public void addedBehavior(){
System.out.println("addedBehaviorB");
}
}
class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedBehaviorA();
}
public void addedBehaviorA(){
System.out.println("addedBehaviorA");
}
}
例子:在某咖啡店,用户可以在选择茶或者咖啡作为基础饮料,还可以任意添加红糖、奶油、冰糖等料,请用装饰器模式实现该店饮料计费系统,以便能方便的计算不同类型的饮料价格。使用装饰模式设计该系统,绘制类图并编程实现。
public interface Beverage {
void charging();
double getPrice();
}
public class Coffee implements Beverage {
@Override
public void charging() {
System.out.println("加咖啡");
}
@Override
public double getPrice() {
return 7.5d;
}
}
public class Decorator implements Beverage {
private Beverage beverage;
public Decorator(Beverage beverage) {
this.beverage = beverage;
}
@Override
public void charging() {
beverage.charging();
}
@Override
public double getPrice() {
return beverage.getPrice();
}
public Beverage getBeverage() {
return beverage;
}
public void setBeverage(Beverage beverage) {
this.beverage = beverage;
}
}
public class Cream extends Decorator {
public Cream(Beverage beverage) {
super(beverage);
}
@Override
public void charging() {
System.out.println("加奶油"+getPrice());
}
@Override
public double getPrice() {
return super.getPrice()+3.7;
}
}
public class Sugar extends Decorator {
public Sugar(Beverage beverage) {
super(beverage);
}
@Override
public void charging() {
System.out.println("加糖"+getPrice());
}
@Override
public double getPrice() {
return super.getPrice()+3.5d;
}
}
public class Tea implements Beverage {
@Override
public void charging() {
System.out.println("加茶作");
}
@Override
public double getPrice() {
return 4.5d;
}
}
关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。关联关系的缺点是比继承关系要创建更多的对象。
使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。