源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns
这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23种设计的模式的各种实现方式以及应用场景,非常适用于学习以及提高我们的设计思维,如果对大家有所帮助,请记得star一下给予作者一定的精神支持,你的star是我写出更好的博客的动力,谢谢大家。
装饰模式(decorator)
职责(作用)
- 动态的为一个对象增加新的功能;
- 装饰模式是一种用于替代继承的技术, 无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,这样更加灵活, 同时也能避免类型体系的快速膨胀。
实现细节
-
Component抽象构件角色:
真实对象和装饰对象有相同的接口。这样,客户端对象就能够与真实对象以相同的方式进行装饰对象交互。 -
ConcreteComponent 具体构件角色(真实对象):
io流中的FileInputStream、FileOutputStream -
Decorator装饰角色:
持有一个抽象构件的引用,装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象,这样,就能在真实对象调用前后增加新的功能。 -
ConcreteDecorator具体装饰角色:
负责给构件对象增加新的责任。
简单案例说明
下面我们通过这么一个小案例来说明一下装饰模式,类图如下所示:
我们平时生活中的车只能再陆地上跑,而不能在水里游,天上飞等等,我们通过给车插上翅膀,那么它就能在天上飞了,通过给车加上浮沉箱,那么它就能在水上漂了,通过给车加上人工智能,那么它就能实现自动驾驶了…等等之类的,上面说白了就是在原有功能的基础上动态的增加新的功能,下面我们用代码来实现一下。我在源码中用注解详细的标注了。
代码测试:
package com.oldou.decorator;
/**
* 抽象构建
*/
public interface ICar {
void move();//跑
}
/** ConcreteComponent
* 具体构建角色(真实对象)
*/
class Car implements ICar{
@Override
public void move() {
System.out.println("陆地上跑.....");
}
}
/**
* 装饰器角色
*/
class SuperCar implements ICar{
protected ICar car; //需要持有真实对象的引用
public SuperCar(ICar car) {
super();
this.car = car;
}
@Override
public void move() {
car.move();
}
}
/** ConcreteDecorator具体装饰角色
* 具体的装饰器1
*/
class FlyCar extends SuperCar{
public FlyCar(ICar car) {
super(car);
}
//增加新的功能
public void fly(){
System.out.println("可以天上飞了");
}
@Override
public void move() {
super.move();//调用原有的
fly();//增加新的功能
}
}
/** ConcreteDecorator具体装饰角色
* 具体的装饰器 2
*/
class WaterCar extends SuperCar{
public WaterCar(ICar car) {
super(car);
}
//新的功能
public void swim(){
System.out.println("可以水里游了。。。");
}
@Override
public void move() {
super.move();
swim();//增加上水里游的功能
}
}
/** ConcreteDecorator具体装饰角色
* 具体的装饰器 3
*/
class AICar extends SuperCar{
//可以自己实现一下
}
客户端:
package com.oldou.decorator;
import java.io.*;
/**
* 设计模式之装饰者模式的测试
*/
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move(); //真实角色只有在陆地上跑的功能
System.out.println("增加新功能--");
FlyCar flyCar = new FlyCar(car);//需要加入真实对象对其增加新的功能
flyCar.move();
System.out.println("**********************************");
System.out.println("增加新的功能--");
WaterCar waterCar = new WaterCar(car);
waterCar.move();
System.out.println("*******************两种功能都给安排上****************");
WaterCar waterCar1 = new WaterCar(new FlyCar(new Car()));
waterCar1.move();
//Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(""))));
}
/**
* 以上的测试代码和我们之前所学习的I/O留非常相似
* 例如:Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(""))));
* 这里的FileInputStream就相当于真实的对象,相当于我们这里的Car
* InputStreamReader和 BufferedReader就相当于装饰器,我们这里的WaterCar和FlyCar
*/
}
测试结果:
开发中使用的场景
- IO中输入流和输出流的设计;
- Swing包中图形界面构件功能;
- Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类,增强了request对象的功能。
- Struts2中,request,response,session对象的处理。
IO流实现细节
-
Component抽象构件角色:
io流中的InputStream、OutputStream、Reader、Writer -
ConcreteComponent 具体构件角色:
io流中的FileInputStream、FileOutputStream -
Decorator装饰角色:
持有一个抽象构件的引用:io流中的FilterInputStream、FilterOutputStream -
ConcreteDecorator具体装饰角色:
负责给构件对象增加新的责任。Io流中的BufferedOutputStream、BufferedInputStream等。
装饰模式总结
总结
- 装饰模式(Decorator)也叫包装器模式(Wrapper);
- 装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
优点
- 扩展对象功能,比继承灵活,不会导致类个数急剧增加;
- 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象;
- 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
缺点
- 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
- 装饰模式易于出错,调试排查比较麻烦。
寄言
学习设计模式时一定要动手去敲代码,再加以理解,一定要熟悉到自己能够手写出来,因为面试的时候经常会让你手写出来(亲测)。如果本文对你有所帮助,记得点赞支持一下哈,谢谢。
源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns
这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23种设计的模式的各种实现方式以及应用场景,非常适用于学习以及提高我们的设计思维,如果对大家有所帮助,请记得star一下给予作者一定的精神支持,你的star是我写出更好的博客的动力,谢谢大家。