深入浅出设计模式(五):7.适配器模式

前面讲完了创建型模式,这里开始,我将讲下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,我们看下面的图:
这里写图片描述

7.适配器模式(Adapter)

当一个系统需要使用另一个系统提供的外部接口,而这个外部接口与目前系统使用的接口不兼容时,就需要使用适配器模式,适配器模式就是将一个系统的接口转换成另外一种形式,从而使原来不能直接使用的接口变得可以使用。

哪里会使用到适配器模式

比如:

  • 财务系统要使用人事系统的接口,而人事系统来不及写,财务系统又不能停下来等,这时两种解决办法:一种是双方事先定好要提供的接口方法,包括方法名、参数、返回值等;另一种是双方各自开发自己的程序,等将来提供了接口再进行整合,此时就需要适配器模式进行开发

  • 有时候需要使用外部购买的系统提供的接口,或者使用很久以前的接口(已经不再维护),或者系统对方不提供源代码,这时需适配器模式将购买的系统接口转成自己需要的接口

  • 如java的接口定义了8个方法,而一个客户端使用2个,另一个客户端只是用1个,如果将这8个方法都在实现类里覆写一遍,将会非常麻烦,此时可用适配器模式

适配器的实现原理

这里写图片描述

在模块的接口间使用适配器模式

比如目前人事系统接口返回Map,此时财务系统客户端要求Map,而供应链系统要求用List,所以就需要一个适配器将Map转换为List:

这里写图片描述

代码比较简单,就不在此贴出,全部放在项目中。

适配器模式的实际应用,源码剖析

适配器模式在StringReader, StringWriter, CharArrayReader, CharArrayWriter的实际应用

StringReader

import java.io.IOException;
import java.io.Reader;

public class StringReader extends Reader {

    private String str;
    private int length;
    private int next = 0;
    private int mark = 0;


    public StringReader(String s) {
        this.str = s;
        this.length = s.length();
    }

    //确认该流没有被关闭
    private void ensureOpen() throws IOException {
        if (str == null)
            throw new IOException("Stream closed");
    }

    // 读取字符
    public int read() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (next >= length)
                return -1;
            return str.charAt(next++);
        }
    }

    // 读取字符数组中的字符
    public int read(char cbuf[], int off, int len) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
            if (next >= length)
                return -1;
            int n = Math.min(length - next, len);
            str.getChars(next, next + n, cbuf, off);
            next += n;
            return n;
        }
    }

    // 跳转
    public long skip(long ns) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (next >= length)
                return 0;
            // Bound skip by beginning and end of the source
            long n = Math.min(length - next, ns);
            n = Math.max(-next, n);
            next += n;
            return n;
        }
    } 

    // 确认该字符是否已被读取
    public boolean ready() throws IOException {
        synchronized (lock) {
        ensureOpen();
        return true;
        }
    }

    // 是否支持mark操作
    public boolean markSupported() {
        return true;
    }

    //标识当前位置
    public void mark(int readAheadLimit) throws IOException {
        if (readAheadLimit < 0){
            throw new IllegalArgumentException("Read-ahead limit < 0");
        }
        synchronized (lock) {
            ensureOpen();
            mark = next;
        }
    }

    // 重置当前位置
    public void reset() throws IOException {
        synchronized (lock) {
            ensureOpen();
            next = mark;
        }
    }

    // 关闭流
    public void close() {
        str = null;
    }
}

StringWriter

import java.io.IOException;
import java.io.Writer;

public class StringWriter extends Writer {

    private StringBuffer buf;


    public StringWriter() {
        buf = new StringBuffer();
        lock = buf;
    }

    public StringWriter(int initialSize) {
        if (initialSize < 0) {
            throw new IllegalArgumentException("Negative buffer size");
        }
        buf = new StringBuffer(initialSize);
        lock = buf;
    }

    // 写入字符
    public void write(int c) {
        buf.append((char) c);
    }

    // 写入数组中的字符
    public void write(char cbuf[], int off, int len) {
        if ((off < 0) || (off > cbuf.length) || (len < 0) ||
            ((off + len) > cbuf.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        buf.append(cbuf, off, len);
    }

    //写入字符串
    public void write(String str) {
        buf.append(str);
    }

    // 在指定位置写入字符串
    public void write(String str, int off, int len)  {
        buf.append(str.substring(off, off + len));
    }

    // 增加字符串序列
    public StringWriter append(CharSequence csq) {
        if (csq == null)
            write("null");
        else
            write(csq.toString());
        return this;
    }

    // 在指定位置增加字符串序列
    public StringWriter append(CharSequence csq, int start, int end) {
        CharSequence cs = (csq == null ? "null" : csq);
        write(cs.subSequence(start, end).toString());
        return this;
    }

    // 增加字符
    public StringWriter append(char c) {
        write(c);
        return this;
    }

    public String toString() {
        return buf.toString();
    }

    public StringBuffer getBuffer() {
        return buf;
    }

    public void flush() {
    }


    public void close() throws IOException {
    }
}

适配器模式在Spring的实际应用

在Spring中也有适配器的大量应用,在Spring的AOP中,由于Advisor需要的是MethodInterceptor对象,所有每一个Advisor中的Advice都要适配成对应的MethodInterceptor对象。
这里写图片描述

AdvisorAdapter

package org.springframework.aop.framework.adapter;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;

public abstract interface AdvisorAdapter
{
  public abstract boolean supportsAdvice(Advice paramAdvice);

  public abstract MethodInterceptor getInterceptor(Advisor paramAdvisor);
}
}

MethodBeforeAdviceAdapter

package org.springframework.aop.framework.adapter;

import java.io.Serializable;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.MethodBeforeAdvice;

class MethodBeforeAdviceAdapter
  implements AdvisorAdapter, Serializable
{
  public boolean supportsAdvice(Advice advice)
  {
    return advice instanceof MethodBeforeAdvice;
  }

  public MethodInterceptor getInterceptor(Advisor advisor)
  {
    MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice();
    return new MethodBeforeAdviceInterceptor(advice);
  }
}

在Spring的ORM包中,对于JPA的支持也是采用了适配器模式,首先定义了一个抽象类的JpaVendorAdapter,然后不同的持久层框架都继承了此类:

JpaVendorAdapter

package org.springframework.orm.jpa;

import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;

public abstract interface JpaVendorAdapter
{
  // 返回一个具体的持久层提供者
  public abstract PersistenceProvider getPersistenceProvider();

  // 返回持久层提供者的包名
  public abstract String getPersistenceProviderRootPackage();

  // 返回持久层提供者的属性
  public abstract Map<String, ?> getJpaPropertyMap();

  // 返回JpaDialect
  public abstract JpaDialect getJpaDialect();

  // 返回持久层管理器工厂
  public abstract Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface();

  // 返回持久层管理器
  public abstract Class<? extends EntityManager> getEntityManagerInterface();

  // 自定义回调方法
  public abstract void postProcessEntityManagerFactory(EntityManagerFactory paramEntityManagerFactory);
}

AbstractJpaVendorAdapter

package org.springframework.orm.jpa.vendor;

import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.springframework.orm.jpa.JpaDialect;
import org.springframework.orm.jpa.JpaVendorAdapter;

public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter {
    private Database database; //定义数据库
    private String databasePlatform; //定义数据库的平台
    private boolean generateDdl; //是否生成ddl
    private boolean showSql; //是否显示sql

    public AbstractJpaVendorAdapter() {
        this.database = Database.DEFAULT;

        this.generateDdl = false;

        this.showSql = false;
    }

    /* 设定下列数据库
     * DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER,SYBASE
     */
    public void setDatabase(Database database) {
        this.database = database;
    }

    // 返回要操作的数据库
    protected Database getDatabase() {
        return this.database;
    }

    public void setDatabasePlatform(String databasePlatform) {
        this.databasePlatform = databasePlatform;
    }

    protected String getDatabasePlatform() {
        return this.databasePlatform;
    }

    public void setGenerateDdl(boolean generateDdl) {
        this.generateDdl = generateDdl;
    }

    protected boolean isGenerateDdl() {
        return this.generateDdl;
    }

    public void setShowSql(boolean showSql) {
        this.showSql = showSql;
    }

    protected boolean isShowSql() {
        return this.showSql;
    }

    public String getPersistenceProviderRootPackage() {
        return null;
    }

    public Map<String, ?> getJpaPropertyMap() {
        return null;
    }

    public JpaDialect getJpaDialect() {
        return null;
    }

    public Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface() {
        return EntityManagerFactory.class;
    }

    public Class<? extends EntityManager> getEntityManagerInterface() {
        return EntityManager.class;
    }

    // 设定emf,基于Eclipse的模型框架。它是Eclipse MDA(Model Driven Architecture)的一个重要组成部分
    public void postProcessEntityManagerFactory(EntityManagerFactory emf) {
    }
}

EclipseLinkJpaVendorAdapter

package org.springframework.orm.jpa.vendor;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import javax.persistence.EntityManager;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.springframework.orm.jpa.JpaDialect;

public class EclipseLinkJpaVendorAdapter extends AbstractJpaVendorAdapter {
    // 设定持久层提供者
    private final javax.persistence.spi.PersistenceProvider persistenceProvider;
    // 设定持久层方言
    private final JpaDialect jpaDialect;

    public EclipseLinkJpaVendorAdapter() {
        this.persistenceProvider = new org.eclipse.persistence.jpa.PersistenceProvider();

        this.jpaDialect = new EclipseLinkJpaDialect();
    }

    public javax.persistence.spi.PersistenceProvider getPersistenceProvider() {
        return this.persistenceProvider;
    }

    // 返回JPA的属性
    public Map<String, Object> getJpaPropertyMap() {
        Map jpaProperties = new HashMap();
        // 判断平台是否为空
        if (getDatabasePlatform() != null) {
            jpaProperties.put("eclipselink.target-database",
                    getDatabasePlatform());
        } else if (getDatabase() != null) {
            String targetDatabase = determineTargetDatabaseName(getDatabase());
            if (targetDatabase != null) {
                jpaProperties
                        .put("eclipselink.target-database", targetDatabase);
            }
        }
        // 判断是否生成ddl
        if (isGenerateDdl()) {
            jpaProperties.put("eclipselink.ddl-generation", "create-tables");

            jpaProperties.put("eclipselink.ddl-generation.output-mode",
                    "database");
        }

        if (isShowSql()) {
            jpaProperties.put("eclipselink.logging.level",
                    Level.FINE.toString());
        }

        return jpaProperties;
    }

    //设定数据库
    protected String determineTargetDatabaseName(Database database)    
    {     
        switch (1.$SwitchMap$org$springframework$orm$jpa$vendor$Database[database.ordinal()]) 
        {       
        case 1:                                                                                   
            return "DB2";                                                                            
        case 2:                                                                                    
          return "Derby";                                                                          
        case 3:                                                                                    
          return "HSQL";                                                                           
        case 4:                                                                                    
          return "Informix";                                                                       
        case 5:                                                                                    
          return "MySQL4";                                                                         
        case 6:                                                                                    
          return "Oracle";                                                                         
        case 7:                                                                                    
          return "PostgreSQL";                                                                     
        case 8:                                                                                    
          return "SQLServer";                                                                      
        case 9:                                                                                    
          return "Sybase"; 
        }                                                                       
        return null;  
    }   

    public JpaDialect getJpaDialect() {
        return this.jpaDialect;
    }

    public Class<? extends EntityManager> getEntityManagerInterface() {
        return JpaEntityManager.class;
    }
}

HibernateJpaVendorAdapter

package org.springframework.orm.jpa.vendor;

import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.InformixDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle9iDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.ejb.HibernateEntityManager;
import org.hibernate.ejb.HibernateEntityManagerFactory;
import org.hibernate.ejb.HibernatePersistence;
import org.springframework.orm.jpa.JpaDialect;

public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
    //设定持久层提供者
    private final PersistenceProvider persistenceProvider;
    //设定持久层方言
    private final JpaDialect jpaDialect;

    public HibernateJpaVendorAdapter() {
        this.persistenceProvider = new HibernatePersistence();
        this.jpaDialect = new HibernateJpaDialect();
    }

    //返回持久层方言
    public PersistenceProvider getPersistenceProvider() {
        return this.persistenceProvider;
    }

    //返回持久层提供者
    public String getPersistenceProviderRootPackage() {
        return "org.hibernate";
    }

    //返回JPA的属性
    public Map<String, Object> getJpaPropertyMap() {
        Map jpaProperties = new HashMap();

        if (getDatabasePlatform() != null) {
            jpaProperties.put("hibernate.dialect", getDatabasePlatform());
        } else if (getDatabase() != null) {
            Class databaseDialectClass = determineDatabaseDialectClass(getDatabase());
            if (databaseDialectClass != null) {
                jpaProperties.put("hibernate.dialect",
                        databaseDialectClass.getName());
            }
        }

        if (isGenerateDdl()) {
            jpaProperties.put("hibernate.hbm2ddl.auto", "update");
        }
        if (isShowSql()) {
            jpaProperties.put("hibernate.show_sql", "true");
        }

        return jpaProperties;
    }

    //设定数据库
    protected Class determineDatabaseDialectClass(Database database)     
    {                                                                                       
        switch (1.$SwitchMap$org$springframework$orm$jpa$vendor$Database[database.ordinal()]) 
        {                                                                                     
        case 1:                                                                             
          return DB2Dialect.class;                                                            
        case 2:                                                                               
          return DerbyDialect.class;                                                          
        case 3:                                                                               
          return H2Dialect.class;                                                             
        case 4:                                                                               
          return HSQLDialect.class;                                                           
        case 5:                                                                               
          return InformixDialect.class;                                                       
        case 6:                                                                               
          return MySQLDialect.class;                                                          
        case 7:                                                                               
          return Oracle9iDialect.class;                                                       
        case 8:                                                                               
          return PostgreSQLDialect.class;                                                     
        case 9:                                                                               
          return SQLServerDialect.class;                                                      
        case 10:                                                                              
          return SybaseDialect.class; }                                                       
        return null;              
    }

    //返回JPA方言
    public JpaDialect getJpaDialect() {
        return this.jpaDialect;
    }

    //返回JPA实体管理器工厂
    public Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface() {
        return HibernateEntityManagerFactory.class;
    }

    //返回JPA实体管理器
    public Class<? extends EntityManager> getEntityManagerInterface() {
        return HibernateEntityManager.class;
    }
}

适配器模式在JUnit中的实际应用

通俗而言,就是要适配成TestCase类。这里重点看TestCase的runTest()方法:

protected void runTest() throws Throwable {
        assertNotNull("TestCase.fName cannot be null", this.fName);
        Method runMethod = null;
        try {
            //获取要测试的方法
            runMethod = getClass().getMethod(this.fName, (Class[]) null);
        } 
        catch (NoSuchMethodException e) {
            fail("Method \"" + this.fName + "\" not found");
        }
        //判断要测试的方法是否为公用方法
        if (!Modifier.isPublic(runMethod.getModifiers())) {
            fail("Method \"" + this.fName + "\" should be public");
        }
        //java反射机制
        try {
            runMethod.invoke(this, new Object[0]);
        } 
        catch (InvocationTargetException e) {
            e.fillInStackTrace();
            throw e.getTargetException();
        } 
        catch (IllegalAccessException e) {
            e.fillInStackTrace();
            throw e;
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值