类适配器模式/对象适配器模式和装饰器

来源:互联网 发布:舞祭组 知乎 编辑:程序博客网 时间:2024/06/05 10:48

类适配器模式

类结构:


ConcreteTarget可以不用管,是当前系统正常的接口,我们需要的将Adaptee转化为能与ConcreteTarget类似的系统标准接口。

从图中也可以看到,此时适配器Adapter是需要继承被适配的类

被适配的类--拥有特殊的功能,但是接口和当前系统接口不匹配伪装成标准接口(通常api接口是指应用程序编程接口,不是interface)

package edu.jxnu.demo.adapter;public class Adaptee {public void specificApiForCurrentSystem(){System.out.println("源角色:需要被适配的类,具有特殊功能。。。");}}
目标接口---需要将特殊类匹配到这种接口所定义的标准系统接口上

package edu.jxnu.demo.adapter;public interface TargetInterface {public void standardApiForCurrentSystem();//为当前系统提供标准的api}
适配器---使用被适配类(源角色类)的特殊功能,继承了了源角色,所以可以使用父类的非私有方法,但是这样不能再能继承其他类,java类是单继承


package edu.jxnu.demo.adapter;public class Adapter extends Adaptee implements TargetInterface{@Overridepublic void standardApiForCurrentSystem() {super.specificApiForCurrentSystem();//使用源类的特殊功能,加以包装} //// 适配器类,继承了被适配类,同时实现标准接口}
测试

package edu.jxnu.demo.adapter;public class DemoTest {/** * 当前client 可以通过TargetInterface使用Adaptee (Adapter实现了TargetInterface * ,并在自己内部使用了特殊方法) * */public static void main(String[] args) {TargetInterface adapter = new Adapter();adapter.standardApiForCurrentSystem();//使用标准api}}

对象适配器

JAVA I/O模型就是这种适配器,常用的InputStreamReader继承自Reader,并关联了StreamDecoder就是对象关联,通过构造器注入StreamDecoder,这里StreamDecoder

便关联了InputStream. 以实现字符和字节流的解码

类结构:


目标接口:

package edu.jxnu.demo.objectadapter;public interface TargetInterface {public void standardApiForCurrentSystem();//为当前系统提供标准的api}
标准api当然一样的。

适配器

package edu.jxnu.demo.objectadapter;import edu.jxnu.demo.adapter.Adaptee;//不再使用继承,使用关联关系,避免多继承public class Adapter implements TargetInterface{Adaptee adaptee ;// 直接关联被适配类public Adapter(Adaptee adaptee){/// 可以通过构造函数传入具体需要适配的被适配类对象this.adaptee=adaptee;}public void standardApiForCurrentSystem(){// 这里是使用委托的方式完成特殊功能this.adaptee.specificApiForCurrentSystem();}}
可以看到,Adapter只需要实现一个接口,大大降低了耦合,少用继承多用关联。

但是这里需要传入构造器参数。

装饰器模式

类结构图:


其中Component:抽象组件角色,定义一直抽象的接口,规定被装饰组件有什么功能

ConcreteComponent:实现了抽象组件的所有功能

Decorator:装饰器角色,持有一个Component对象的实例引用,定义一个与抽象组件一致的接口

ConcreteDecorator:具体的装饰器实现者,负责实现装饰器角色定义的功能。

Java I/O也用到了装饰器

毕竟装饰器是赋予被装饰的类更加多的功能,最常见的就是InputStream被装饰成BufferedInputStream,其中FilterInputStream类就是装饰器角色,它实现了InputStream,并持有Inputstream的引用,对应上图就是Decorator持有了Component,且实现了它的接口

抽象组件:

package edu.jxnu.demo.decorator;public interface Component {    public void methodA();//需要被装饰的组件的抽象接口}
具体组件:

package edu.jxnu.demo.decorator;public class ConcreteComponent implements Component {     @Override    public void methodA() {        System.out.println("被装饰类,实现了抽象组件的功能");    }} 
装饰器角色接口:


package edu.jxnu.demo.decorator;public abstract class Decorator implements Component {     private Component instance;//持有Component的引用,通过构造器注入    public Decorator() {    }    public Decorator(Component inst) {        this.instance = inst;    }       public Component getInstance(){        return this.instance;    }   }
装饰器的实现者:

package edu.jxnu.demo.decorator;public class ConcreteDecorator extends Decorator {  //实现了抽象装饰器定义的功能   public ConcreteDecorator() {        super();    }   /**    * //构造传入组件,  super(inst);    *  public Decorator(Component inst) {        this.instance = inst;    }    *     * */    public ConcreteDecorator(Component inst) {        super(inst);            }    @Override    public void methodA() {        this.getInstance().methodA();        this.doAdditionalResponsibility();        //在原有组件功能上,添加功能,在外界看来,就想使用了methodA方法所做的事情更多了,接口没有变,与适配器的区别    }     private void doAdditionalResponsibility(){        System.out.println("被包装的功能");    }} 
测试:

package edu.jxnu.demo.decorator;public class TestDecorator {       public static void main(String[] args) {        Component inst = new ConcreteComponent();//实例化一个具体组件        inst.methodA();//使用原本的功能        System.out.println("装饰后的功能");        //仍是Component,所以接口没有改变        Component instDecorator = new ConcreteDecorator(inst);//经过装饰之后的功能        instDecorator.methodA();    }} 

适配器模式和装饰器都是一种包装模式,看似是包装对象或类,适配器的意义在于要将一个接口转化为另一个接口,通过改变接口来达到重复使用的目的,而装饰器不改变源接口,而是保持,并增强原接口的功能,或者改变实现方法,以提示性能。
这两种java IO很常见

参考《深入分析javaweb》


原创粉丝点击