【java io】io流中设计模式之装饰器模式和适配器模式

IO流中的设计模式

一、装饰器模式

装饰器(Decorator)定义
在不必改变原类情况下,动态的扩展一个对象的功能,他是通过创建一个包装对象,也就是装饰来包装真实的对象

(方式)继承来扩展功能:java中的继承单继承

1、装饰器特点

Component:为统一接口,也是装饰类和被装饰类的基本类型。
ConcreteComponent:为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类
Decorator:是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。
ConcreteDecorator:是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent
在这里插入图片描述
注意:装饰器类可以有很多的变化
1、被装饰器的统一的接口,可以是一个接口,也可以是抽象父类
2、装饰器类Decorator可以不需要

2、代码示例

a、首先,先创建一个统一的接口,也是装饰类和被装饰类的基本类型

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

b、创建一个装饰,实现接口

/**
 * Decorator
 * 是装饰类
 * 实现了Component接口
 */
public abstract  class Decorator implements Component {

    //内部维护一个ConcreteComponent实例
    protected Component component ;

    //通过构造函数实例化ConcreComponent实例
    public Decorator(Component component) {
        this.component = component;
    }

    //Component接口提供的方法
    @Override
    public void method() {
        component .method() ;

    }
}

c、创建具体实现类

public class ConcreteComponent implements Component  {

    @Override
    public void method() {
        System.out.println(" 原来的方法 ");
    }
}

/**
 * 具体装饰器类A
 * 继承自装饰器类
 */
public class ConcreteDecoratorA extends Decorator  {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void methodA(){
        System.out.println("装饰器A扩展的功能");
    }

     @Override
    public void method(){
         System.out.println("针对该方法添加一层A包装");
         super .method() ;
         System .out.println("A包装结束");
     }
}
/**
 * 具体装饰器类B
 * 继承自装饰器类
 */
public class ConcreteDecoratorB extends Decorator  {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void methodB(){
        System.out.println("装饰器B扩展的功能");
    }

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

三个具体实现类都继承装饰类,拓展原来的功能
d、TestDome

  public static void main(String[] args) {
        Component component =new ConcreteComponent() ;//原来的对象
        component .method() ;//原来的方法
        System.out.println("------------------------");
        ConcreteDecoratorA concreteDecoratorA =new ConcreteDecoratorA(component );//装饰成A
        concreteDecoratorA .method() ;
        concreteDecoratorA .methodA() ;//装饰成A以后新增的方法
        System.out.println("-------------------------");
        ConcreteDecoratorB concreteDecoratorB=new ConcreteDecoratorB(component );//装饰成B
        concreteDecoratorB .method() ;
        concreteDecoratorB .methodB() ;
        System.out.println("-------------------------");
        concreteDecoratorB =new ConcreteDecoratorB(concreteDecoratorA  );//装饰成A以后再装饰成B
        concreteDecoratorB .method() ;
        concreteDecoratorB .methodB() ;//装饰成B以后新增的方法
        System.out.println("----------------------");

    }

输出结果,由此可见可以扩展很多其他功能在这里插入图片描述

3、io流中的使用

举例:InputStream是一个抽象类,相当于统一接口(Component),是装饰类和被装饰类的基本类型
FileInputStream相当于原始的待装饰对象,为具体实现类,也是被装饰类,本身具有很多完整功能
BufferedInputStream是一个具体的装饰器类,扩展了特有的方法

import java.io.*;

public class IODecorator {
    public static void main(String[] args) throws IOException , FileNotFoundException  {
        final String filepath="F://a.txt";
        /**
         * InputStream相当于统一接口,是装饰类和被装饰类的基本类型(Component)
         * FileInputStream相当于原始的待装饰的对象,为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类
         *
         */
        InputStream inputStream =new FileInputStream(filepath );
        System.out.println("FileInputStream不支持mark和reset"+inputStream .markSupported() );
        System.out.println("-----------------------");
        /**
         * 下面展示一种装饰器的作用BufferedInputStream
         *
         * BufferedInputStream是一个具体的装饰器类
         * 其定义如下:
         * BufferedInputStream extends FilterInputStream
         *
         * FilterInputStream是装饰类,其继承自InputStream
         * 内部存在一个inputStream实例
         *
         * BufferedInputStream提供了特有的方法:
         */
        BufferedInputStream bufferedInputStream =new BufferedInputStream(inputStream ) ;
        System.out.println("bufferedInputStream支持mark和reset:"+bufferedInputStream .markSupported() );//提供实现自由的方法
        bufferedInputStream .mark(0);//标记一下
        char c=(char )bufferedInputStream .read() ;
        System.out.println("文件的第一个字符:"+c);
        bufferedInputStream .reset() ;//重置
        c=(char )bufferedInputStream .read() ;//再读
        System.out.println("重置以后再读一个字符,依然会是第一个字符:"+c);
        bufferedInputStream .reset() ;

    }
}

二、适配器模式

1、适配器介绍

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

实现方式:类适配器和对象适配器
1、使用继承(就是所谓的类适配器)需要适配的类
2、使用组合(所谓的对象适配器)通过在内部包装一个Adaptee对象,把源接口转换成目标接口

例如:家用电源220v,而手机只需要5v,这就是一个适配过程
适配器所涉及的角色有:
Target(目标接口):所要转换的所期待的接口(5V)
Adaptee(源角色):需要适配的类220V
Adapter(适配器):将源角色适配成目标接口,一般持有源接口的引用(或者继承源接口),且实现目标接口(220——5)
Client(客户类):通过目标角色获取服务
在这里插入图片描述

适配器的特点:
1)通过继承或者内部封装adaptee对象,完成适配
2)有更好的复用性。系统需要使用现有的类,但此类接口不符合系统需要,通过适配器模式让这些功能得到很好的复用

2、代码实现

a、首先建立一个客户需要的目标接口

/**
 * TypeC接口
 * 即需要的目标接口(客户希望)
 */
public interface TypeC {
     void isTypeC();
}

b、然后创建一个类可以实现客户希望的功能

/**
 *
 * 存在一个USB充电口
 * 该充电口已经实现其特定的USB接口的能力
 */
public class USB {
    void isUSB(){
        System.out.println("use充电口");
    }
}

c、第一种方式类适配器
将USB适配成TypeC

/**
 * 类适配器
 * 核心类:将USB适配成TypeC
 */
public class ClassAdapter extends USB implements TypeC {
    @Override
    public void isTypeC() {
        //TypeC接口的实现是通过适配USB实现的
        super .isUSB() ;
    }
}

d、第二种方式对象适配器
将适配器的对象作为适配器的属性,通过构造函数获取实例

/**
 * 对象适配器
 * 将被适配的对象作为适配器的属性,通过构造函数获取实例
 */
public class ObjectAdapter implements TypeC  {
    private USB usb ;
    public ObjectAdapter(USB usb){
        this.usb=usb;
    }

    @Override
    public void isTypeC() {
        usb .isUSB() ;

    }
}

d、Dome,应用

public class Client {
    public static void main(String[] args) {
        //类适配器的实现
        TypeC typeC =new ClassAdapter() ;
        //通过TypeC提供服务
        typeC .isTypeC() ;

        //对象适配器的实现
        USB usb =new USB() ;
        TypeC typeC1 =new ObjectAdapter(usb ) ;
        typeC1 .isTypeC() ;
    }
}

3、适配器在IO流中的使用

例如:
适配器角色就是InputStreamReader,(220——5)
被适配角色是InputStream类代的实例对象adaptee(220v)
目标接口是Reader类(5)

//目标类
public abstract class Reader implements Readable,Closeable

//需要适配的类
public abstract class InputStream implements Closeable

//转换流 适配器类
//InputStreamReader 操作字节
public class InputStreamReader extends Reader{
//解码类
private final StreamDecoder sd;

 public InputStreamReader(InputStream in){
    super(in);
    try{
       sd=StreamDecoder.forInputStreamReader(in,this,(String)null);
    }catch(UnsupportedEncodingException e){
       throw new Error(e);
    }
 }

 int read(char cbuf[],int offset,int length) throws IOException{
      return sd.read(cbuf,offset,length);
 }

}

举例:(和对象适配器的用法相同)

File file =new File("hello.txt");
FileInputStream in=new FileInputStream(file);
//将FileInputStream适配成InputStreamReader,即输入的字节流转换成字符流
Reader inReader = new InputStreamReader(in);

三、装饰器和适配器的异同点

装饰器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的不相同
适配器模式:是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的
装饰器模式:不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能
或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值