IO流中的设计模式

装饰器模式:Decorator

装饰器模式介绍

装饰器模式在不必改变原类文件和不使用继承的情况下,动态的扩展一个对象的功能。它通过创建一个包装对象,用来包装真实的对象

注意:

不改变原类文件

不使用继承

动态扩展

装饰器模式类图UML:

image.png

存在四个角色:

Component:为统一接口,也是装饰类和被装饰类的基本类型

ConcreteComponent:为具体实现类,被装饰类,本身是具有完整功能的类

Decorator:装饰类,在内部维护了一个ConcreteComponent的具体实例对象,他一般是父类,仅仅是一个声明,需要的具体的装饰类是其的子类,而子类再装饰具体的产品类

ConcreteDecorator:具体的装饰器类,每一个装饰器类都具有自身特有的装饰效果

代码示例:

/**
 * 统一接口,是被装饰类和装饰类的基本类型
 */
public interface Component {
    public void service();
}

/**
 * 被装饰的原始类,是Component具体实现类
 */
public class ConcreteComponent implements Component {
    @Override
    public void service() {
        System.out.println("原始类具体实现");
    }
}

/**
 * 装饰器的父类
 */
public class Decorator implements Component {
    //持有Component对象引用
    private Component component;

    //通过构造函数传入Component对象
    public Decorator(Component component) {
        this.component = component;
    }


    @Override
    public void service() {
        this.component.service();
    }
}

/**
 * 具体装饰器类
 * 继承自Decorator
 */
public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    public void serviceA() {
        System.out.println("特有功能serviceA");
    }

    @Override
    public void service() {
        System.out.println("serviceA针对该方法添加一层包装");
        super.service();
        System.out.println("serviceA包装结束");
    }
}

/**
 * 具体装饰器类
 * 继承自Decorator
 */
public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }
    public void serviceB() {
        System.out.println("特有功能serviceB");
    }

    @Override
    public void service() {
        System.out.println("serviceB针对该方法添加一层包装");
        super.service();
        System.out.println("serviceB包装结束");
    }
}

测试代码

public static void main(String[] args) {
        ConcreteConponent concreteConponent = new ConcreteConponent();
        concreteConponent.service();
        System.out.println("-----------------");

        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(concreteConponent);
        concreteDecoratorA.service();//调用原有的方法
        concreteDecoratorA.serviceA(); //扩展新的功能
        System.out.println("------------------");

        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(concreteConponent);
        concreteDecoratorB.service();//调用原有的方法
        concreteDecoratorB.serviceB();//扩展新的功能
    }
}

执行结果:

image.png

通过上述代码可知:分别对装饰器类进行的原方法的装饰和新功能的增加,methodA和methodB都是新功能,这些都是装饰器可以做的,至少包含其中的一种功能需求,否则失去了装饰器的意义

IO流中装饰器的作用

public static void main(String[] args) throws IOException {
        String path="E:\\java\\IO\\IOTest\\test4.txt";
        /**
         * InputStream相当于统一的接口即Component,是装饰器类和被装饰器类的基本类型
         * FileInputStream相当于原始实现类,对InputStream中的抽象类进行实现
         */
        InputStream inputStream = new FileInputStream(path);

        /**
         *缓冲流
         * BufferedInputStream相当于具体的装饰器类
         * 对原有的方法进行装饰,比如read,read(byte[])等,增加了缓冲区功能
         *
         * class FilterInputStream extends InputStream
         * FilterInputStream继承自InputStream ,内部持有InputStream 实例对象引用
         *
         * BufferedInputStream extends FilterInputStream
         * FilterInputStream相当于装饰器类的父类Decorator
         */
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        bufferedInputStream.read(new byte[1024]);

        //转换流
        /**
         * InputStreamReader是具体的装饰器类
         * 新的功能是进行字节流和字符流的转换
         */
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
    }

InputStream就相当于上述的Component接口,只不过这里是一个抽象类,是被装饰器类和装饰器类基本类型

FileInputStream相当于ConcreteComponent,即待装饰的具体对象,它并不是JAVA的IO结构中的一个装饰器类,因为它无法修饰InputStream

FilterInputStream就是一个Decorator,是装饰器的父类

BufferedInputStream就是一个装饰器类

InputStreamReader也是一个装饰器类

 在类图上标注了各个类负责的角色,并且使用背景颜色将InputStream和Reader体系分开,其中左半部分就是InputStream的装饰体系,右半部分就是Reader的装饰体系,并且他们之间的桥梁是InputStreamReader,他们每一个装饰体系都与上面标准的装饰器模式类图极其相似

总之:装饰器模式就是一个可以非常灵活的动态扩展类功能的设计模式,它采用组合的方式取代继承,使得各个功能的扩展更加独立和灵活

适配器模式:Adapter

适配器模式介绍

将一个类的接口转化成客户希望的另外的一个接口,Adapter模式是原本由于接口不兼容不能一起工作的类可以一起使用

适配器模式分为两种:类适配器和对象适配器

使用继承的形式使用类适配器

使用组合的形式使用对象适配器

适配器的类图UML:

image.png

角色有三种:

Adaptee:源角色,实际真正提供服务的类,需要进行适配的类

Target:目标角色,客户所期望的接口

Adapter: 适配器角色,将源角色适配成目标角色,在内部持有一个源角色的引用


/**
 * 目标角色
 * 客户期望的接口
 */
public interface E6V {
    public void use6V();
}

/**
 * 适配器
 * 类适配器,通过继承形式实现
 */
public class ClassAdapter extends E220V implements E6V {
    //适配过程
    @Override
    public void use6V() {
        use220V();
    }
}

/**
 * 适配器
 * 对象适配器,使用组合形式
 */
public class ObjectAdapter implements E6V {
    //持有源角色对象引用
    private E220V e220V;

    //通过构造函数来实例化属性
    public ObjectAdapter(E220V e220V) {
        this.e220V = e220V;
    }

    @Override
    public void use6V() {
        this.e220V.use220V();
    }
}

测试代码:

    public static void main(String[] args) {
        //期望是6V
        //通过类适配器实现
        ClassAdapter classAdapter = new ClassAdapter();
        classAdapter.use6V();

        //通过对象适配器实现
        E220V e220V = new E220V();
        ObjectAdapter objectAdapter = new ObjectAdapter(e220V);
        objectAdapter.use6V();
    }

适配器特点:

1.适配器的对象实现目标接口

2.类适配器需要继承自源角色类

3.对象适配器需要持有一个对象的引用,并通过构造函数传递参数

优点:

1.有更好的复用

2.有更好的扩展性,实现了适配器,可以调用自己开发的功能

缺点:

代码的可读性变差

IO流中适配器的使用

适配器角色就是InputStreamReader

被适配的角色是InputStream类的实例对象

目标接口是Reader类

InputStrteamReader实现了Reader接口,并且持有InputStream的引用,这里是通过StreamDecoder类间接持有的,因为从byte到char要经过编码

/******************InputStreamReader类(适配器类)******************/

public class InputStreamReader extends Reader {

    private final StreamDecoder sd;

    //持有对被适配对象的引用

    public InputStreamReader(InputStream in) {

        super(in);

        try {

            //通过StreamDecoder类间接引用被适配的对象

            sd = StreamDecoder.forInputStreamReader(in, this, (String)null);

        } catch (UnsupportedEncodingException e) {

            // The default encoding should always be available

            throw new Error(e);

        }

    }

    //…(省略的代码)

 }

 /******************InputStream类(被适配类)******************/

 public abstract class InputStream implements Closeable {

 //代码省略

}

使用Demo 

File file = new File("hello.txt");

FileInputStream in = new FileInputStream(file);

// 将FileInputStream适配成InputStreamReader,即输入的字节流转换成字符流

InputStreamReader inReader = new InputStreamReader(in);

装饰器和适配器异同点:

同:

装饰器和适配器都可以叫做包装模型,都是对原有的类进行包装成新的类或者对象

异:

适配器:将一个接口转化成另一个接口,通过改变接口来达到重复使用的目的

装饰器:不是要改变被装饰对象的接口,而是保持原有的接口,但是新增原有对象不具有的功能,或者改变原有的对象的处理方式而提升性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值