设计模式系列-javaIO流与装饰模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lovely9862/article/details/68950219

装饰模式是结构型模式之一,定义为:动态地给一个对象添加一些额外的方法,就增加功能来说,装饰模式相比增加子类更加灵活。所以,装饰模式是为基础类添加功能的!

如果不用装饰模式,当然可以通过继承原有的类完成功能的添加,在子类上添加一些方法,但是却变得耦合性大,灵活性变低和可维护性变大,中间类一旦有方法添加,子类也要跟着添加。如果使继承体系变为2个分支,分为功能类,和装饰类,就可以动态的添加功能而不影响原有的类。

装饰模式的结构如下:


抽象组件Component,具体组件ConcreteComponent,抽象装饰器Decorator继承自Component并组合入一个Component,暴露了与组件相同的方法operate(),两个具体的装饰类ConcreteDecorator1和ConcreteDecorator1,在基础的operate()方法上面增加了一些功能。

具体代码如下:

abstract class Component{
	public abstract void operate();
}

class ConcreteComponent extends Component{

	@Override
	public void operate() {
		System.out.println("执行操作");
		
	}
}

abstract class Decorator extends Component{
	
	private Component component;
	
	Decorator(Component component){
		this.component = component;
	}
	public void operate(){
		component.operate();
	}
}

class ConcreteDecorator1 extends Decorator{
	ConcreteDecorator1(Component component) {
		super(component);
	}

	private void decorate1(){
		System.out.println("decorate1");
	}
	
	public void operate(){
		super.operate();
		decorate1();
	}
}

class ConcreteDecorator2 extends Decorator{
	ConcreteDecorator2(Component component) {
		super(component);
	}

	private void decorate2(){
		System.out.println("decorate2");
	}
	
	public void operate(){
		super.operate();
		decorate2();
	}
}

测试类:

public class DecoratorTest {
	public static void main(String[] args) {
		Component c = new ConcreteComponent();
		Decorator d1 = new ConcreteDecorator1(c);
		d1.operate();
		Decorator d2 = new ConcreteDecorator2(c);
		d2.operate();
	}
}


测试结果:

执行操作
decorate1
执行操作
decorate2


以上,说明了装饰模式的具体用法。

在java中,最典型的装饰模式的运用当属javaIO体系结构,再次笔者简单的用eclipse的继承分析工具看一下继承关系:


InputStream为一个输入流,它是个抽象类,提供了read(byte b[])、read(byte b[], int off, int len)等方法;FilterInputStream就是个抽象装饰器,它是一个抽象类,继承了InputStream并且组合入一个InputStream,BufferedInputStream是具体的装饰类,看一下它的read方法:

    private int read1(byte[] b, int off, int len) throws IOException {
        int avail = count - pos;
        if (avail <= 0) {
            /* If the requested length is at least as large as the buffer, and
               if there is no mark/reset activity, do not bother to copy the
               bytes into the local buffer.  In this way buffered streams will
               cascade harmlessly. */
            if (len >= getBufIfOpen().length && markpos < 0) {
                return getInIfOpen().read(b, off, len);
            }
            fill();
            avail = count - pos;
            if (avail <= 0) return -1;
        }
        int cnt = (avail < len) ? avail : len;
        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
        pos += cnt;
        return cnt;
    }

在基本的读操作上提供了缓冲的功能。

笔者水平有限,如有错误欢迎指正与探讨。


阅读更多

没有更多推荐了,返回首页