java设计模式-装饰器

装饰器模式:
动态地给一个对象添加一些额外的职责,装饰模式相比生成子类更为灵活。

Component:抽象构件
ConcreteComponent 具体构件,要被装饰的类
Decorator:装饰角色,具体装饰器的父类
ConcreteDecorator:  具体装饰器角色


示例:
对一个字符串打印前,进行两个处理:1、转大写,2、删除所有的 aa 字符串。这两步顺序要求不一样就会产生不一样的结果。
 

伪代码如下:

	//定义一个打印的接口,及抽象构件
	interface Component{
		void print();//打印
	}
	//定义一个抽象类,实现需要处理的步骤,具体的打印可以在子类中实现。
	abstract Test implements Component{
			public void upcase(){}//转大写实现
			public void replace(){}//替换实现
	}

这样会发现每一个顺序都会对应一个子类的实现。如果再加上几种操作要求顺序不同,那么子类就会很多。这时候装饰器模式就很容易处理。动态扩展类的功能

 

装饰器模式实现如下:

1、还是使用上面的抽象构件

/**
 * 抽象构件
 */
public interface Component extends Serializable{
    void print(String str);
}

2、抽象构件要有一个实现类,即具体的构件

/**
 * 具体构件
 * 要被装饰的类
 */
public class ConcreteComponent implements Component{

    @Override
    public void print(String str) {
        System.out.println(str);
    }
}

3、每一个操作就是一个装饰器(ConcreteDecorator),装饰器要有一个装饰角色(Decorator),
装饰角色要实现抽象构件,并且要有抽象构件作为一个属性。

/**
 * 装饰器父类
 */
public abstract class Decorator  implements Component{

    private Component component;

    public Decorator(Component component){
        this.component = component;
    }

    @Override
    public void print(String str) {
        component.print(str);
    }
}

4、实现两个 ConcreteDecorator,都是Decorator  子类

/**
 * 装饰器A
 */
public class DecoratorA extends Decorator{

    public DecoratorA(Component component){
        super(component);
    }

    @Override
    public void print(String str) {
        //转大写
        str = str.toUpperCase();
        super.print(str);
    }
}
/**
 * 装饰器A
 */
public class DecoratorB  extends Decorator{

    public DecoratorB(Component component){
        super(component);
    }

    @Override
    public void print(String str) {
        //删除aa
        str = str.replaceAll("aa","");
        super.print(str);
    }
}

5、测试

    public static void main(String[] args) {
        //构件
        Component component = new ConcreteComponent();
        
        //装饰器
        component = new DecoratorB(component);
        //装饰器
        component = new DecoratorA(component);

        component.print("aabcccazz");
    }

只要两装饰器顺序不同,那么结果就会不一样了。

注意这里是一个装饰器又被另外一个装饰器装饰,这样一层一层的嵌套。

能用类图:


 

场景:

1、需要动态扩展一个类的功能。(继承也可以扩展,就是改动比较多)

2、需要为一批兄弟类进行统一的扩展功能。

优点:

装饰类和被装饰的类分开发展,解耦。 动态扩展一个类的功能

继承关系的一种替代方案,一层一层的嵌套,返回的都是一个对象,好像动态生成了一个“链”

 

缺点:

多层的装饰比较复杂,层多了之后出现问题排序问题比较难。

在实际工作中很少用到。

 

 

jdk 中装饰器的使用:
1、FilterInputStream 类就是一个装饰器类。
写法:装饰器和要被装饰的类实现同样的接口,并且在装饰器中有一个接口的属性,用于接口实现的委派。在装饰器类中实现接口方法委派给接口的子类。

FilterInputStream 装修了InputStream 接口,那么所有的InputStream 的子类都可以通过这个装修器类来装饰,装饰后可以直接使用InputStream 接口方法调用。具体实现是InputStream 接口来实现的。

FilterInputStream 的每一个子类都是一个装饰器,对InputStream类的增强。


2、ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(filePath)));

ObjectInputStream 也是个装饰器,把FileInputStream 装饰成了ObjectInputStream 对象,从而把FileInputStream 实现增强为了对对象的流写入。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值