在一个项目中,我看到一些由前雇员编写的代码。该人将其命名为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
接口的所有方法。它真的是一个适配器模式吗?如果不是,那么这里使用的是哪种设计模式?
感谢@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
答案 0 :(得分:2)
如果类RowSetAdaptor
以任何方式调整CachedRowSet
接口,则RowSetAdaptor
可视为适配器设计模式(对象适配器)的实现
但是在你的示例列表中我看不到任何改编 - 操作只是转发到cachedRowSet
对象 - 以便客户端可以访问
CachedRowSet
直接接口。
RowSetAdaptor
引入了一个额外的间接层,即
使设计和成本绩效复杂化。
只有在客户端不能或不应该直接访问CachedRowSet
接口时才应该使用它。
“只有在实际需要灵活性时才应用设计模式。” [GoF一书,第31页]
注意:
Adapter 设计模式(对象适配器)建议客户端引用接口(Target)使它们独立于具体的实现类(Adapter)。
在您的示例中,客户端引用(并依赖于)具体的RowSetAdaptor
类。
有关进一步讨论,请参阅http://w3sdesign.com处的GoF设计模式内存/适配器设计模式。
答案 1 :(得分:1)
是的,它仍然是 Adapter 模式。
适配器使两个不兼容的接口能够协同工作。
在java世界中,我们习惯于看到Adapters
(例如MouseAdapter
和MouseListener
),它们实际上并不是真正意义上的适配器(所以请注意这一点)。
但是,在您的示例中,适配器似乎打算将CachedRowSet
接口的大小和复杂性降低到名为RowSetAdapter
的新接口Serializable
。< / p>
该示例使用组合而不是继承这一事实不会将其排除在Adapter
模式之外,我认为它实际上是一个很好的Adapter
示例,尽管您也可以认为它也代表它Proxy
模式。
答案 2 :(得分:1)
查看某个模式实现的最佳方法是将GoF定义中的角色/方法映射到实现。
GoF Adapter有两个变体(类和对象适配器),它们具有不同的结构。类适配器使用多重继承:
您有一个类RowSetAdaptor
,这将使其成为此图中Adapter
类的候选者。但是,RowSetAdaptor
仅实现Serializable
,因此我认为它不能是适配器模式的这种形式。
第二个变体是对象适配器:
同样,RowSetAdaptor
将是此图中的Adapter
类。确实javax.sql.rowset.CachedRowSet
似乎是适应者,因为它在其某些方法中使用了该类。但是,最纯粹的GoF适配器必须实现一些Target
接口,并且可能在其构造函数中包装对象Adaptee
(CachedRowSet
是硬编码的)。有些人可能会说Serializable
是Target
接口,但这意味着它会调整那些request()
方法。 RowSetAdaptor
不会覆盖Serializable
中我能看到的任何内容。
最后,如果它真的是GoF适配器模式,我希望有多个适配器。通常,设计Target
接口是因为有一些通用功能由不同的适配器实现(只有一个实现的接口没有意义)。
另一个值得注意的问题是,Client
不应该知道它使用RowSetAdaptor
; Client
只能看到Target
类型的对象。如果客户端只是直接访问实现,那么很难证明使用与客户端的接口是合理的。
也许您可以检查Client类或其他适配器的代码。
我的结论是,基于您提供的代码,它不是GoF适配器模式的令人信服的例子。
查看适配器的更多实际示例答案 3 :(得分:0)
该类确实实现了Serializable
(它依赖于CachedRowSetImpl
为Serializable
)的事实,因此技术上它是一个适配器。必要的原因可以是here。
至于这是否是一个好主意,这是另一种蠕虫(结果集可能很大,使用不同的格式序列化更有意义,例如,json,protobuf等等。)。