装饰模式:动态地给一个对象增加一些额外的职责。就扩张功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案
假设有一个接口Human,一个接口的实现类Man。人类Human是可以跑步的,但是不能飞
如果想给人类加上飞翔的翅膀,可以有三种解决方案:
1、修改实现类Man的方法,但不符合开闭原则
2、给实现类Man添加一个子类,扩展一个人类可以飞的功能。问题在于,如果又想给人类增加猎豹般奔跑的速度,需要继续扩展一个子类。显然,使用继承的方式去扩展一个类的功能,会增加类的层级,类的臃肿会加大维护的成本。
3、使用装饰模式扩展一个类的功能。好处在于,如果继承关系是纵向的,那么装饰类则是某个类横向的扩展,并不会影响继承链上的其他类。例如:C extends B , B extends A,如果需要扩展B的功能,可以设计一个B的装饰类,它并不会影响B的子类C。如果采用在B里面增加方法,势必会使B的所有子类结构被改变
二,装饰模式
基本步骤:
- 定义一个抽象类或者接口Human
- 定义一个被装饰的类Man
- 定义一个装饰的抽象类,内部持有被装饰类的引用
- 定义一个装饰的实现类
定义一个抽象类Human,代码如下:
public abstract class Human {
public abstract void run();
}
定义一个被装饰的类Man,代码如下:
public class Man extends Human{
@Override
public void run() {
System.out.println("人会跑");
}
}
定义一个装饰的抽象类,代码如下:
public class AbstractDecorator extends Human{
//持有被装饰类的引用
protected Human human;
//构造函数注入被装饰者
public AbstractDecorator(Human human) {
this.human = human;
}
@Override
public void run() {
human.run();
}
}
定义第一个装饰的实现类,代码如下:
public class Man1Decorator extends AbstractDecorator{
public Man1Decorator(Human human) {
//调用父类的构造方法
super(human);
}
//装饰类增加的功能
private void fly() {
System.out.println("人可以飞");
}
//增强了功能的run方法
@Override
public void run() {
super.run();
fly();
}
}
定义第二个装饰的实现类,代码如下:
public class Man2Decorator extends AbstractDecorator{
public Man2Decorator(Human human) {
super(human);
}
//装饰类增加的功能
private void eat() {
System.out.println("人可以吃");
}
//增强了功能的run方法
@Override
public void run() {
super.run();
eat();
}
}
测试代码如下:
public class Test {
public static void main(String[] args) {
/** //创建被装饰的类
Human human = new Man();
Man1Decorator man1Decorator= new Man1Decorator(human);
//创建装饰的类,并添加被装饰类的引用
Human superMan= new Man2Decorator(man1Decorator);
//执行增强后的run方法
superMan.run();**/
//创建装饰的类,并添加被装饰类的引用
Human superMan = new Man2Decorator(new Man1Decorator(new Man()));
//执行增强后的run方法
superMan.run();
}
}
三,使用场景,及优缺点
使用场景:
- 替代继承,扩展一个类的功能
- 动态的给一个对象添加功能,以及动态的撤销该功能
优点:
- 动态扩展一个实现类的功能,在不需要添加功能的时候,可以撤销装饰。
- 装饰类和被装饰类模块间,通过抽象产生依赖,不会相互耦合
- 对于扩张一个对象的功能,装饰模式比继承模式更加灵活,不会导致类的数量急剧增加
缺点:
- 在使用装饰模式的时候进行系统设计时会产生很多小对象,这些对象的区别在于他们之间相互连接的方式有所不同,而不是他们的类或者属性值有所不同,大量小对象势必产生一大部分的系统资源开销。影响系统性能
- 装饰模式是一种比继承更加灵活的解决方案。但同时,也意味着比继承更加容易出错,更加难排长。对于多层装饰的对象,需要逐级排查,较为繁琐。
四,装饰模式与代理模式的区别
装饰模式:侧重给一个实现类动态添加功能,不会对实现类的方法进行过滤拦截
代理模式:侧重将一个实现类的功能,委托给代理类来处理,可以对实现类的方法进行过滤拦截(某种情况下,可能不执行实现类的方法)
---------------------
详见请查看博主原文
来源:CSDN
原文:https://blog.csdn.net/pihailailou/article/details/82813374
版权声明:本文为博主原创文章,转载请附上博文链接!