它真的是一个适配器模式吗?

时间:2015-02-02 17:14:47

标签: java design-patterns adaptor

在一个项目中,我看到一些由前雇员编写的代码。该人将其命名为Adapter模式的实现,但我不确定。这是代码:

public class RowSetAdaptor implements java.io.Serializable {
    private javax.sql.rowset.CachedRowSet cachedRowSet;

    public RowSetAdaptor() throw SQLException {
        cachedRowSet = new com.sun.rowset.CachedRowSetImpl();
    }

    public void populate(ResultSet resultSet) throw SQLException {
        cachedRowSet.populate(resultSet);
    }

    public boolean next() throw SQLException {
        cachedRowSet.next();
    }

    .... // different methods all using cachedRowSet
} 

我认为类RowSetAdaptor的方式限制了对CachedRowSet接口的访问,因为CachedRowSet类中并未提供RowSetAdaptor接口的所有方法。它真的是一个适配器模式吗?如果不是,那么这里使用的是哪种设计模式?

更新[2015年2月24日]

感谢@JB Nizet,@ Fuhrmanator,@GüntherFranke,@ vikingsteve和@Giovanni Botta的回答。

如果我进行以下修改以使其成为适配器模式怎么办?

public interface RowSetI {
    public boolean next() throws SQLException;
    ...
}

public class CachedRowSetAdapter implements RowSetI {
    private javax.sql.rowset.CachedRowSet cachedRowSet;

    public CachedRowSetAdapter() throw SQLException {
        cachedRowSet = new com.sun.rowset.CachedRowSetImpl();
    }

    public void populate(ResultSet resultSet) throw SQLException {
        cachedRowSet.populate(resultSet);
    }

    public boolean next() throw SQLException {
        cachedRowSet.next();
    }
    ...
}

public class JdbcRowSetAdapter implements RowSetI {
    private javax.sql.rowset.JdbcRowSet jdbcRowSet;

    public JdbcRowSetAdapter() throw SQLException {
        jdbcRowSet = new com.sun.rowset.JdbcRowSetImpl();
    }

    public void populate(ResultSet resultSet) throw SQLException {
        jdbcRowSet.populate(resultSet);
    }

    public boolean next() throw SQLException {
        jdbcRowSet.next();
    }
    ...
}

TIA

4 个答案:

答案 0 :(得分:2)

如果类RowSetAdaptor以任何方式调整CachedRowSet接口,则RowSetAdaptor可视为适配器设计模式(对象适配器)的实现

但是在你的示例列表中我看不到任何改编 - 操作只是转发到cachedRowSet对象 - 以便客户端可以访问 CachedRowSet直接接口。

RowSetAdaptor引入了一个额外的间接层,即 使设计和成本绩效复杂化。 只有在客户端不能或不应该直接访问CachedRowSet接口时才应该使用它。

  

“只有在实际需要灵活性时才应用设计模式。”   [GoF一书,第31页]

注意: Adapter 设计模式(对象适配器)建议客户端引用接口(Target)使它们独立于具体的实现类(Adapter)。
在您的示例中,客户端引用(并依赖于)具体的RowSetAdaptor类。

有关进一步讨论,请参阅http://w3sdesign.com处的GoF设计模式内存/适配器设计模式。

答案 1 :(得分:1)

是的,它仍然是 Adapter 模式。

适配器使两个不兼容的接口能够协同工作。

在java世界中,我们习惯于看到Adapters(例如MouseAdapterMouseListener),它们实际上并不是真正意义上的适配器(所以请注意这一点)。

但是,在您的示例中,适配器似乎打算将CachedRowSet接口的大小和复杂性降低到名为RowSetAdapter的新接口Serializable。< / p>

该示例使用组合而不是继承这一事实不会将其排除在Adapter模式之外,我认为它实际上是一个很好的Adapter示例,尽管您也可以认为它也代表它Proxy模式。

答案 2 :(得分:1)

查看某个模式实现的最佳方法是将GoF定义中的角色/方法映射到实现。

GoF Adapter有两个变体(类和对象适配器),它们具有不同的结构。类适配器使用多重继承:

Class adapter

您有一个类RowSetAdaptor,这将使其成为此图中Adapter类的候选者。但是,RowSetAdaptor仅实现Serializable,因此我认为它不能是适配器模式的这种形式。

第二个变体是对象适配器:

Object Adapter

同样,RowSetAdaptor将是此图中的Adapter类。确实javax.sql.rowset.CachedRowSet似乎是适应者,因为它在其某些方法中使用了该类。但是,最纯粹的GoF适配器必须实现一些Target接口,并且可能在其构造函数中包装对象AdapteeCachedRowSet是硬编码的)。有些人可能会说SerializableTarget接口,但这意味着它会调整那些request()方法。 RowSetAdaptor不会覆盖Serializable中我能看到的任何内容。

最后,如果它真的是GoF适配器模式,我希望有多个适配器。通常,设计Target接口是因为有一些通用功能由不同的适配器实现(只有一个实现的接口没有意义)。

另一个值得注意的问题是,Client不应该知道它使用RowSetAdaptor; Client只能看到Target类型的对象。如果客户端只是直接访问实现,那么很难证明使用与客户端的接口是合理的。

也许您可以检查Client类或其他适配器的代码。

我的结论是,基于您提供的代码,它不是GoF适配器模式的令人信服的例子。

https://stackoverflow.com/a/13323703/1168342

查看适配器的更多实际示例

答案 3 :(得分:0)

该类确实实现了Serializable(它依赖于CachedRowSetImplSerializable)的事实,因此技术上是一个适配器。必要的原因可以是here

至于这是否是一个好主意,这是另一种蠕虫(结果集可能很大,使用不同的格式序列化更有意义,例如,json,protobuf等等。)。