装饰者模式: 动态的给对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更灵活。
比如说,在不使用装饰者模式的情况下,我要给人添加装扮。
定义一个Person类,一个Wear类, Person类里面定义一个Wear属性,然后Wear类里面定义上衣,裤子,鞋子等属性。
但是这样写的话,将来要新增腰带,帽子等衣服的时候,就要去改原来的Wear类,会影响到其他已经被创建了类和对象,违背了开闭原则,对拓展开放 对修改封闭。
装饰者模式的UML图如下:
被修饰的组件接口
component
/**
* @ClassName component
* @Author laixiaoxing
* @Date 2019/6/10 上午10:20
* @Description 被装饰的组件接口
* @Version 1.0
*/
public interface Component {
void operator();
}
组件接口实现类
ConcreteComponentA
/**
* @ClassName concreteComponentA
* @Author laixiaoxing
* @Date 2019/6/10 上午10:22
* @Description 被装饰的组件实体A
* @Version 1.0
*/
public class ConcreteComponentA implements Component {
@Override
public void operator() {
System.out.println("被装饰的组件实体A");
}
}
装饰器
Decorator
/**
* @ClassName Decorator
* @Author laixiaoxing
* @Date 2019/6/10 下午2:42
* @Description 抽象装饰类 用于拓展Component的功能,但是Component不需要知道Decorator的存在
* @Version 1.0
*/
public abstract class Decorator implements Component {
private Component component;
public void setComponent(Component component) {
this.component = component;
}
@Override
public void operator() {
if (component!=null){
component.operator();
}
}
}
拓展功能A
/**
* @ClassName ConcreteDecoratorA
* @Author laixiaoxing
* @Date 2019/6/10 下午2:51
* @Description 具体的装饰器
* @Version 1.0
*/
public class ConcreteDecoratorA extends Decorator {
/**
* 拓展属性
*/
private String extension="拓展属性A";
@Override
public void operator() {
extenstion();
System.out.println(extension);
super.operator();
}
/**
* 拓展功能
*/
private void extenstion(){
System.out.println("拓展功能A");
}
}
ConcreteDecoratorB
装饰器实现类B
/**
* @ClassName ConcreteDecoratorB
* @Author laixiaoxing
* @Date 2019/6/10 下午2:51
* @Description 具体的装饰器
* @Version 1.0
*/
public class ConcreteDecoratorB extends Decorator {
/**
* 拓展属性
*/
private String extension="拓展属性B";
@Override
public void operator() {
extenstion();
System.out.println(extension);
super.operator();
}
/**
* 拓展功能
*/
private void extenstion(){
System.out.println("拓展功能B");
}
}
应用
public class Application {
public static void main(String[] args) {
Component component = new ConcreteComponentA();
Decorator decorator = new ConcreteDecoratorA();
decorator.setComponent(component);
invoker(decorator);
System.out.println();
//而且装饰之后 还可以继续装饰
Decorator decoratorB = new ConcreteDecoratorB();
decoratorB.setComponent(decorator);
invoker(decoratorB);
}
public static void invoker(Component component) {
component.operator();
}
}
//组件不需要关心自己如何被修饰,要拓展哪些功能。 多个组件可以被同一个修饰器修饰
//修饰器不需要关心自己要修饰哪个组件,一个修饰器可以修饰多个组件
//调用者不需要关心自己接受的参数是component还是decorator ,因为decorator都是实现的同一个Component接口,所以其实是一个东西
//而且装饰之后 还可以继续装饰 多个不同的装饰可以进行组合
//参照经典的java的io的设计 就是装饰器模式,给InputStream进行不同的功能添加
//InputStream in=null;
//InputStreamReader reader=new InputStreamReader(in);
//BufferedInputStream bufferedInputStream=new BufferedInputStream(in);
现在用之前的那个穿衣服的例子实现一下:
一个装饰者子类叫person
/**
* @ClassName Person
* @Author laixiaoxing
* @Date 2019/6/10 下午4:20
* @Description TODO
* @Version 1.0
*/
public class Person implements Component {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public void operator() {
System.out.println(name+"穿完衣服");
}
}
穿大裤衩
public class BIgTrouser extends Decorator {
@Override
public void operator() {
System.out.println("穿大裤衩");
super.operator();
}
}
带帽子
public class Hat extends Decorator{
@Override
public void operator() {
System.out.println("带大帽子");
super.operator();
}
}
穿t恤
public class Tshirts extends Decorator {
@Override
public void operator() {
System.out.println("穿T恤");
super.operator();
}
}
应用
public class ApplicationPerson {
public static void main(String[] args) {
Component xiaoming = new Person("小明");
//小明穿t恤
Decorator tshirts = new Tshirts();
tshirts.setComponent(xiaoming);
//穿完t恤穿大裤衩
Decorator bIgTrouser = new BIgTrouser();
bIgTrouser.setComponent(tshirts);
//穿完大裤衩带帽子
Decorator Hat=new Hat();
Hat.setComponent(bIgTrouser);
Hat.operator();
System.out.println("");
Component xiaohong = new Person("小红");
//小红带帽子
Decorator HatRed=new Hat();
HatRed.setComponent(xiaohong);
HatRed.operator();
}
}
可以给小明穿任意衣服,也可以给小红穿任意的衣服。
这个类似于代理模式,但是代理,主要是为了封装被代理的对象,比如控制它被人访问的权限,即使有增强功能,但也不够灵活。
装饰者模式是为已有的功能动态的添加更多功能的方式
什么情况下使用:当系统需要新功能的时候,是向旧的类里面添加新的代码,且新的代码通常装饰了原有类的核心职责或者主要行为。
比如说往某个类里面添加了某些特定情况下才会用到的字段或者业务逻辑, 这样使得这个类变得更复杂了。
一个好的解决方案就是将要将某些并非是核心职责且是在某些特定情况下才会用到的逻辑封装到一个单独的装饰器类中,使用的时候 就可以灵活视情况使用。
比如说inputStream 和buffInputStream ,就是给inputStream加了缓冲区。