设计模式
总体来说设计模式分为三大类:
- 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
装饰器模式
装饰器模式就是通过组合替代继承的方式在不改变原来的类的情况下添加功能,主要解决继承关系复杂的问题
通过IO包来理解装饰器模式
为什么要使用装饰器模式?
IO类大致分为字节输入输出流和字符输入输出流这四类,四大类下又分为大大小小的功能流,如果全部使用继承去实现就会存在继承关系的混乱,同时代码冗余太强,每种子类都需要继承相关父类,但是子类也不是全部需要对父类的重写,只是对父类的方法进行增强,为了解决这种继承混乱的问题,提出使用组合和委托来达到继承的效果,动态的组合对象,实现对方法功能的增强
就比如一个InputStream需要有一个文件输入流FileInputStream,那么他就需要继承InputSream,而文件输入流又需要一个缓冲流BufferFileInputStream,这个类继承FileInputStream,如果继续增加一个传输基本数据类型的缓冲流DataBufferFileInputStream,也需要继承BufferFileInputStream,如果全部继承实现的话,字节输入流需要这个类,那么字节输出流也需要,字符输入输出流同样需要这些类,难道要全部实现吗?这样就会造成一种情况,继承的类过于臃肿,类的结构过于复杂
为了解决这个继承问题,我们选择使用组合和委托来代替继承,这样也符合设计模式原则:多用组合少用继承,同时选择组合和委托也可以动态的组合对象,无需修改现有代码,直接在新的代码直接添加功能即可,符合模式设计原则的开闭原则,即类应该对拓展开放,对修改关闭,基于组合和委托我们设计出了装饰器模式
IO流继承关系图
装饰器模式的结构
抽象组件(component):被装饰类的原始对象,可以是一个接口也可以是一个抽象类
具体组件:继承于抽象组件,对抽象组件的方法进行重写,即被装饰的对象
抽象装饰者(decorator):每个抽象的装饰者都包装一个抽象组件,抽象的装饰者存在一个实例变量用来保存对抽象组件的引用,使用protected修饰,确保不被其他类访问,通过构造器方法将抽象组件指向实例变量
具体装饰者:继承于抽象装饰类,对抽象装饰者实现新的方法即实现具体的包装逻辑,功能扩展
// 抽象组件
interface Component {
void operation();
}
// 具体组件
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("执行原始操作");
}
}
// 抽象装饰者
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 具体装饰者
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("添加额外功能A");
}
}
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("添加额外功能B");
}
}
// 使用装饰者模式
public class DecoratorPatternExample {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component.operation(); // 执行原始操作
Component decoratedComponentA = new ConcreteDecoratorA(component);
decoratedComponentA.operation(); // 执行原始操作 + 添加额外功能A
Component decoratedComponentB = new ConcreteDecoratorB(component);
decoratedComponentB.operation(); // 执行原始操作 + 添加额外功能B
Component decoratedComponentAB = new ConcreteDecoratorB(decoratedComponentA);
decoratedComponentAB.operation(); // 执行原始操作 + 添加额外功能A + 添加额外功能B
}
}
装饰器模式同样用到继承,不是组合实现吗?
在装饰器模式中,使用继承的主要目的是让装饰器和抽象组件是一样的类型,也就是要有共同的超类,也就是使用继承达到类型匹配,而不是利用继承获得行为
当我们将装饰器与组件组合时,就是在加入新的行为。这种新的行为并不是继承自超类,而是由组合对象得来的
注意:装饰器模式也是有问题的,它会导致设计中出现许多小类,如果过度使用,会让程序变得很复杂