个人学习笔记分享,当前能力有限,请勿贬低,菜鸟互学,大佬绕道
如有勘误,欢迎指出和讨论,本文后期也会进行修正和补充
前言
中秋刚过没多久,虽然我这种粗人对月饼无感,但是公司发的肯定得收的嘛
拿回家当零食吃算了,一个硬纸袋,打开是一个盒子,盒子打开时十多个小盒子,小盒子打开是塑料包装的月饼,撕开塑料包装,终于能吃了
吃了一口,emmm就这?还没小时候吃的冰糖五仁月饼好吃呢,弄这么花里胡哨
就一块味道并不咋地的月饼,花里胡哨包装一层又一层,何必呢?还不如改善工艺做好吃点
说的再难听点,这些精心包装的月饼,跟普通袋装的月饼,区别也就只是包装吧(虽然大部分人送的是心意)
包装对于月饼,就只是装饰而已,差不多做法生产的月饼,经过一层又一层包装,就能变成在店铺里形形色色的礼品月饼,本质上依然是月饼
而且理论上包装可以无限层的套娃。。。。
我们早上去早餐店买煎饼,可以加鸡蛋、生菜、肉松等等,从一个薄饼整成一个巨无霸,但说到底,仍然是个煎饼。
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
添加了新功能后是原对象的子类,根据里氏代换原则,新的对象也能够被再次修饰,进而可以无限套娃
1.介绍
使用目的:向一个现有的对象添加新的功能,同时又不改变其结构
使用时机:在不想改变结构的情况下扩展类
解决问题:避免扩展时常规继承方法,随着扩展功能的增多,子类会很膨胀
实现方法:Component
类充当抽象角色,修饰类引用和继承 Component 类,具体扩展类重写父类方法,而修饰类也同样可被扩展
应用实例:
- 买手抓饼的时候,我们并非只有做之前可以说加什么,做完之后加肉松,或者加火腿什么的都是可以的,但怎么加都是手抓饼
- 化妆的时候,经常是涂涂抹抹好几层,而且顺序并不严格固定,也可以最后根据情况再涂几层,怎么好看怎么来,但怎么涂都是自己的脸
优点:
- 装饰类和被装饰类可以独立发展,不会相互耦合
- 可以被多次装饰,使用时自由度高
缺点:多层装饰时思路比较复杂,需要清晰的理解业务
2.结构
通常包括4个角色
- 抽象组件角色(Component): 定义可以动态添加任务的对象的接口
- 具体组件角色(ConcreteComponent):定义一个要被装饰器装饰的对象,即
Component
的具体实现 - 抽象装饰器(Decorator): 维护对组件对象和其子类组件的引用,需要实现
Component
- 具体装饰器角色(ConcreteDecorator):向组件添加新的职责
ConcreteComponent
负责Component
的具体实现Decorator
是一个虚拟类,需要实现Component
,并持有一个Component
对象ConcreteDecorator
作为装饰器,负责给组件添加职责
ConcreteDecorator
作为Decorator
的子类,根据里氏代换原则,也可被ConcreteDecorator
持有并装饰
说白了就是,我装饰我自己
3.实现
-
定义抽象组件角色(
Component
)interface Component { String operate(); }
-
定义具体组件角色(
ConcreteComponent
),并实现Component
class ConcreteComponent implements Component { @Override public String operate() { return "原始对象"; } }
-
定义抽象装饰器(
Decorator
),实现Component
abstract class Decorator implements Component { private Component component; public Decorator(Component component) { this.component = component; } @Override public String operate() { //调用被装饰者的方法 return component.operate(); } }
-
定义具体装饰器角色(
ConcreteDecorator
),继承Component
class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } @Override public String operate() { return super.operate() + " 加上修饰器A"; } } class ConcreteDecoratorB extends Decorator { public ConcreteDecoratorB(Component component) { super(component); } @Override public String operate() { return super.operate() + " 加上修饰器B"; } }
-
测试客户端
public class DecoratorTest { public static void main(String[] args) { Component component = new ConcreteComponent(); Component componentA=new ConcreteDecoratorA(component); Component componentAB=new ConcreteDecoratorB(componentA); Component componentABA=new ConcreteDecoratorA(componentAB); Component componentBAB=new ConcreteDecoratorB(new ConcreteDecoratorA(new ConcreteDecoratorB(new ConcreteComponent()))); System.out.println(componentABA.operate()); System.out.println(componentBAB.operate()); }
完整代码
package com.company.test.decorator;
interface Component {
String operate();
}
class ConcreteComponent implements Component {
@Override
public String operate() {
return "原始对象";
}
}
abstract class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public String operate() {
//调用被装饰者的方法
return component.operate();
}
}
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public String operate() {
return super.operate() + " 加上修饰器A";
}
}
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public String operate() {
return super.operate() + " 加上修饰器B";
}
}
public class DecoratorTest {
public static void main(String[] args) {
Component component = new ConcreteComponent();
Component componentA=new ConcreteDecoratorA(component);
Component componentAB=new ConcreteDecoratorB(componentA);
Component componentABA=new ConcreteDecoratorA(componentAB);
Component componentBAB=new ConcreteDecoratorB(new ConcreteDecoratorA(new ConcreteDecoratorB(new ConcreteComponent())));
System.out.println(componentABA.operate());
System.out.println(componentBAB.operate());
}
}
运行结果
4.小结
4.1.为何要使用装饰模式
-
解耦
ConcreteComponent
和ConcreteDecorator
,从常见的继承关系变为关联关系,使他们可以独立变化,只需要遵守共同的规则(Component
)即可否则只能使他们一层一层继承,耦合度极高,不利于扩展
-
ConcreteComponent
和ConcreteDecorator
都算是Component
的实现,因此对于Component
适用的接口,ConcreteComponent
和ConcreteDecorator
都适用,这样以来,客户端使用和外部接口对接也会简单很多因此外部代码只需要针对
Component
设计即可 -
可以自己装饰自己,是独一无二的优点,可以无限制的自由增加功能
4.2.存在的隐患
均为设计或者管理不当导致,也就是人为错误,可以凭借开发者能力规避的东西
-
套娃次数太多,会导致逻辑混乱
比如server层之间的互相引用,很容易出现套娃,逻辑极其混乱
-
死循环
类似于递归的死循环爆栈
-
装载顺序报错(先有鸡还是先有蛋?)
比如两个service(A和B)互相引用,那么装载A时需要先装载B,装载B时需要先装载A,会直接报错
后记
我装饰我自己,这就是装饰模式所想达到的目的
装饰后的对象,依然是同一种对象,因此可以非常自由的反复装饰,同时原本适用的接口或者方案,装饰之后依然能够使用
比如,“我是一个人”,加上装饰“我是一个正直善良聪明可爱但也许并不算帅气的男生”,但是说到底我仍然是个人,我拥有一个人所拥有的思考和行为方式
作者:Echo_Ye
WX:Echo_YeZ
Email :echo_yezi@qq.com
个人站点:在搭了在搭了。。。(右键 - 新建文件夹)