这次,我们来说说一个极其不常用到的模式——适配器模式。也并不是绝对极不常用,如果自个写框架之类的话,也许会变得很常用。怎么个常用法呢?在需要使用某个类时,其提供的接口并不是你所希望的,又或者说你还需处理接口返回的结果,你就可以用适配器模式解决此类问题。
当已存在的接口不满足需求时。
- //适配器接口
- public interface Target {
- void request(Map<String, String> boby);
- }
- //适配器
- public class Adapter implements Target {
-
- private Adaptee adaptee;
-
- public Adapter(Adaptee adaptee) {
- this.adaptee = adaptee;
- }
- //适配方法
- @Override
- public void request(Map<String, String> boby) {
- List<String> list = new ArrayList<String>();
- for(Entry<String, String> entry : boby.entrySet()) {
- list.add(entry.getKey() + "-" + entry.getValue());
- }
- adaptee.simpleRequest((String[]) list.toArray());
- }
-
- }
- //被适配
- public class Adaptee {
- public void simpleRequest(String[] boby) {}
- }
-
上述代码可见,Adaptee 的 simpleRequest(String[] boby) 并不满足 Map<String, String> 类型的参数,所以需要适配器 Adapter 的 request(Map<String, String> boby) 方法。 通常,我们并不会只针对某个子类做适配器,更多的是为一系列的子类(同一父类)做适配,例如上述代码 Adaptee 的子类们。
- public class FileInputStream extends InputStream {
-
- /* File Descriptor - handle to the open file */
- private final FileDescriptor fd;
- public FileInputStream(FileDescriptor fdObj) {
- // ...
- fd = fdObj;
- // ...
- }
- public FileInputStream(String name) throws FileNotFoundException {
- this(name != null ? new File(name) : null);
- }
- public FileInputStream(File file) throws FileNotFoundException {
- // ...
- fd = new FileDescriptor();
- // ...
- }
- public void close() throws IOException {
- synchronized (closeLock) {
- if (closed) {
- return;
- }
- closed = true;
- }
- if (channel != null) {
- /*
- * Decrement the FD use count associated with the channel
- * The use count is incremented whenever a new channel
- * is obtained from this stream.
- */
- fd.decrementAndGetUseCount();
- channel.close();
- }
-
- /*
- * Decrement the FD use count associated with this stream
- */
- int useCount = fd.decrementAndGetUseCount();
-
- /*
- * If FileDescriptor is still in use by another stream, the finalizer
- * will not close it.
- */
- if ((useCount <= 0) || !isRunningFinalize()) {
- close0();
- }
- }
- }
-
java.io.FileInputStream 已经是 FileDescriptor 的适配器,由三个构造方法可见,都需要传递或实例化 FileDescriptor 对象。
适配器模式的类与类间的代码结构,跟装饰者模式是相似的,但有一点不一样的是,适配器与被适配者没有亲戚关系。装饰者模式会在下一篇讲到!