体能状态先于精神状态,习惯先于决心,聚焦先于喜好。
Decorator
装饰器模式的意图是在运行时组合操作的新变化。
动态的给一个对象添加一些额外的职业。就增加功能来说,装饰器模式相比生成子类更为灵活。
装饰器模式的本质来说-增强一个对象的功能,
我们有很多种方式来达成一样的功能效果.比如子类继承父类、再比如使用代理模式
但是装饰器模式有其自身的特点,尤其是在代码实现上的特点:
1、装饰器模式不通过继承的方式进行增强——而是将对象作为一个变量,通过构造参数传递到装饰器类内部进行进一步处理,
这样你总是只有一个对象,但是你需要多少种特性就提供多少个装饰器类即可
2、对象所属类和装饰器类有共同的一个父抽象类(或者接口),在对象增强之后,对原对象的原方法的调用将转化为对修饰器类同名方法的调用,
在视觉感官上,保持了既有逻辑的一致性
通过1、2两点,你应该认识到修饰器模式不同于静态代理,它更像是对被修饰对象进行了一层封装,更为重要的是,这种代码结构提供了
一个非常重要的特性,即重复修饰,试想一下这种场景:一般人买汽车就是一辆汽车,但是顾客也可能需要其他服务,比如购买几个备用轮胎,
洗车、购买儿童座椅等等.每一个新的产品可以作为一个装饰器类,而可以通过重复调用来进行个数的增加-即重复修饰.
抽象构件(Component):一个抽象类,包含一个抽象方法,被装饰类和装饰器类都需要继承这个抽象类
·具体构件(ConcreteComponent):即被装饰类,需要重写抽象方法
·抽象装饰(Decorator):一个继承了抽象构建的抽象类,作为具体装饰类的共同父类,该类不是必须的;含有一个全局抽象构件的变量-未实例化,并在提供一个以被修饰类对象为入参的构造方法,在构造方法内部将该对象赋值给全局声明的抽象构建变量
·具体装饰(ConcreteDecorator):一个继承了抽象装饰类的子类,重写抽象方法,一般在方法内部调用父类的同名方法,然后增加新的装饰逻辑
·用户购买轿车
·允许用户对轿车进行升级
·比如升级发动机,汽车轮胎,倒车雷达等
·新轿车没啥
·升级即对新轿车这个对象进行修饰,升级发动机、汽车轮胎、倒车雷达等
·轮胎升级不止一个
注意本文所有代码没有包含 package,如测试请注意添加
/**
* 抽象组件
*/
public abstract class VisualComponent {
/**升级*/
public abstract String upgrade();
}
/**
* 具体构件,即被修饰对象所属类
*/
public class Car extends VisualComponent {
@Override
public String upgrade() {
return "购买原型车";
}
}
/**
* 抽象装饰器类
* 所有具体装饰器类继承自该类
*/
public abstract class Decorator extends VisualComponent{
/**待修饰的对象*/
private VisualComponent visualComponent;
public Decorator(){}
/**提供一个以被修饰对象为参数的构造函数
* 子类构造函数可以直接调用父类的构造函数
* */
public Decorator(VisualComponent visualComponent){
this.visualComponent=visualComponent;
}
@Override
public String upgrade() {
//该方法可以由子类来做具体实现
return this.visualComponent.upgrade();
}
}
/**
* 升级 发动机 的具体装饰器类
*/
public class EngineDecorator extends Decorator {
public EngineDecorator(){
}
/**子类提供传入被修饰对象的构造方法
* 内部直接调用父类构造方法
* */
public EngineDecorator(VisualComponent visualComponent){
super(visualComponent);
}
@Override
public String upgrade() {
return super.upgrade()+";升级发动机";
}
}
/**
* 升级 轮胎 的具体装饰器类
*/
public class TyreDecorator extends Decorator {
public TyreDecorator(){
}
/**子类提供传入被修饰对象的构造方法
* 内部直接调用父类构造方法
* */
public TyreDecorator(VisualComponent visualComponent){
super(visualComponent);
}
@Override
public String upgrade() {
return super.upgrade()+";升级轮胎";
}
}
/**
* 升级 倒车雷达 的具体装饰器类
*/
public class RadarDecorator extends Decorator {
public RadarDecorator(){
}
/**子类提供传入被修饰对象的构造方法
* 内部直接调用父类构造方法
* */
public RadarDecorator(VisualComponent visualComponent){
super(visualComponent);
}
@Override
public String upgrade() {
return super.upgrade()+";升级倒车雷达";
}
}
import org.junit.Test;
public class DecoratorTest {
@Test
public void testUpgrade(){
//购买车辆
VisualComponent visualComponent=new Car();
//升级发动机
visualComponent=new EngineDecorator(visualComponent);
//升级轮胎
visualComponent=new TyreDecorator(visualComponent);
//升级倒车雷达
visualComponent=new RadarDecorator(visualComponent);
String result=visualComponent.upgrade();
System.out.println("result="+result);
}
}
输出
result=购买原型车;升级发动机;升级轮胎;升级倒车雷达
如果一个对象包含很多种组合,以至于为组合的每一种情况提供一个单独的类不现实
这种情况下就适合用装饰器模式,通过每一个装饰器类对原对象进行功能扩展
Java IO 体系非常完美的体现了 装饰器模式,分别用四个类来对应上文的距离
·抽象构建: InputStream
·抽象装饰者:FilterInputStream
·具体装饰者:BufferedInputStream
·具体构建:FileInputStream
Collections 并发包提供方法,将非线程安全的对象封装到新对像内部,然后每一次操作增加一个 mutex 互斥锁.
是装饰器模式的实现.
ArrayList list=(ArrayList) Collections.synchronizedList(new ArrayList());
[1]、https://blog.csdn.net/wwwdc1012/article/details/82764333
[2]、https://www.cnblogs.com/zuoxiaolong/p/pattern11.html
[3]、https://www.imooc.com/article/41726#
[4]、https://cloud.tencent.com/developer/article/1339008