深入浅出设计模式(五):7.适配器模式
2016-01-12 18:55
609 查看
前面讲完了创建型模式,这里开始,我将讲下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,我们看下面的图:
![](http://img.my.csdn.net/uploads/201211/29/1354192484_5322.PNG)
财务系统要使用人事系统的接口,而人事系统来不及写,财务系统又不能停下来等,这时两种解决办法:一种是双方事先定好要提供的接口方法,包括方法名、参数、返回值等;另一种是双方各自开发自己的程序,等将来提供了接口再进行整合,此时就需要适配器模式进行开发
有时候需要使用外部购买的系统提供的接口,或者使用很久以前的接口(已经不再维护),或者系统对方不提供源代码,这时需适配器模式将购买的系统接口转成自己需要的接口
如java的接口定义了8个方法,而一个客户端使用2个,另一个客户端只是用1个,如果将这8个方法都在实现类里覆写一遍,将会非常麻烦,此时可用适配器模式
![](https://img-blog.csdn.net/20160112183501799)
![](https://img-blog.csdn.net/20160112185233148)
代码比较简单,就不在此贴出,全部放在项目中。
![](https://img-blog.csdn.net/20160113103613677)
在Spring的ORM包中,对于JPA的支持也是采用了适配器模式,首先定义了一个抽象类的JpaVendorAdapter,然后不同的持久层框架都继承了此类:
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 fe7a 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; } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序