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");
    }
只要两装饰器顺序不同,那么结果就会不一样了。

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

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

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


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

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

猜你喜欢

转载自blog.csdn.net/convict_eva/article/details/79208352