Reputation: 1661
On a project I have seen some code which was written by a former employee. The person has named it as an implementation of Adaptor pattern but I am not sure. Here is the code:
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
}
The way I see it the class RowSetAdaptor
is restricting access to CachedRowSet
interface as not all methods of CachedRowSet
interface are available in RowSetAdaptor
class. Is it really an Adaptor pattern? If not then which design pattern is being used here?
Thanks @JB Nizet , @Fuhrmanator , @Günther Franke , @vikingsteve and @Giovanni Botta for your answers.
What if I make following modifications to make it an Adapter pattern?
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
Upvotes: 3
Views: 766
Reputation: 12882
The best way to see if something's an implementation of a pattern is to map the roles/methods in the GoF definition to the implementation.
GoF Adapter has two variants (class and object adapter) which have different structures. Class adapters use multiple inheritance:
You have a class RowSetAdaptor
, which would make it a candidate for the Adapter
class in this diagram. However, RowSetAdaptor
implements only Serializable
, so I thinking it can't be this form of the Adapter pattern.
The second variant is the object adapter:
Again, RowSetAdaptor
would be the Adapter
class in this diagram. It does appear that javax.sql.rowset.CachedRowSet
would be the adaptee, since it's using that class inside of some of its methods. However, the purest GoF Adapter must implement some Target
interface and probably wrap an object Adaptee
in its constructor (CachedRowSet
is hard-coded). Some might say Serializable
is the Target
interface, but that would imply it would adapt those request()
methods. RowSetAdaptor
doesn't override anything in Serializable
that I can see.
Finally, if it's really the GoF Adapter pattern, I'd expect there to be more than one Adapter. Generally, Target
interface is designed because there is some common functionality that is implemented by different adapters (it makes little sense to have an interface with only one implementation).
Another noteworthy point is that Client
shouldn't know it's using a RowSetAdaptor
; Client
only sees an object of the Target
type. It's hard to justify using an interface with a client if the client is just going to access the implementation directly.
Perhaps you can check the code for the Client class or other adapters.
My conclusion is that based on the code you presented, it's not a convincing example of GoF Adapter pattern.
See more real examples of adapters at https://stackoverflow.com/a/13323703/1168342
Upvotes: 1
Reputation: 40378
Yes, it is still the Adapter pattern.
An adapter enables two incompatible interfaces to work together.
From the java world, we are used to seeing Adapters
(e.g. MouseAdapter
and MouseListener
) that are not actually adapters in the true sense (so please be aware of that).
In your example however, the adapter seems to have the intention to reduce the size and complexity of the interface of CachedRowSet
into a new interface named RowSetAdapter
that is also Serializable
.
The fact that the example uses composition rather than inheritance does not exclude it from being an Adapter
pattern, I think it is a good Adapter
example in fact, although you could also argue it also represents the Proxy
pattern.
Upvotes: 1
Reputation: 237
If the class RowSetAdaptor
adapts the CachedRowSet
interface in any way then RowSetAdaptor
can be seen as an implementation of the Adapter design pattern (object adapter).
But in your example listing I can't see any adaptation - operations are simply forwarded to the cachedRowSet
object - so that clients can access the
CachedRowSet
interface directly.
RowSetAdaptor
introduces an additional level of indirection, which
complicates design and costs performance.
It should only be used if clients can't or shouldn't access the CachedRowSet
interface directly.
"A design pattern should only be applied when the flexibility it affords is actually needed."
[GoF book, page 31]
Note:
The Adapter design pattern (object adapter) suggests that clients refer to an interface (Target) to make them independent of a concrete implementation class (Adapter).
In your example, clients refer to (and depend on) the concrete RowSetAdaptor
class.
For further discussion see the GoF Design Patterns Memory / Adapter design pattern at http://w3sdesign.com.
Upvotes: 2
Reputation: 9816
Well the class does implement Serializable
(it relies on the fact that CachedRowSetImpl
is Serializable
), so technically it is an adapter. The reason why this is necessary can be found here.
As far as whether this is a good idea or not, that's a whole other can of worms (the result set can be huge, it would make more sense to serialize using a different format, e.g., json, protobuf, etc.).
Upvotes: 0