Polluted Interfaces and Adapter Pattern.

Started by
7 comments, last by Emmanuel Deloget 16 years, 9 months ago
I am confused on how the Adapter pattern is supposed to work. I just don't get it. I have an interfaces that manages some data like: interface DataManager { void save(); void delete(); void update(); ... } and a bunch of implementors: Implementer1 implements DataManager { void save() { doSomething(); ... } /* Implementer 1 doesn't need to implement these so they become dummy functions. */ void delete() { } ; void update() { }; } I think my interface here is "polluted" but I'm not sure how to go about fixing it. I have a UI class that accepts an object that implements DataManager that calls whatever functions are necessary for the type of data it's displaying. I've read that the Adapter pattern can fix this but I have no idea on how it works. What's the responsibility of the adapter? How would I go about defining it? Do I create distinct adapter classes for each type of data that I have to manage or somehow have only 1 adapter class that magically handles all types? HELP!
Advertisement
The Adapter pattern simply implements an interface with empty method stubs. Obviously, this only applies to methods which return nothing (i.e., void methods). With your example, one could write a DataManagerAdapter like this:

class DataManagerAdapter implements DataManager{   public void save()   {}   public void delete() {}   public void update() {}}


Then you could make Implementer1 extend DataManagerAdapter rather than implement DataManager directly:

class Implementer1 extends DataManagerAdapter{   public void save()   {      doSomething();   }}


Hope this helps!

- Rob
I think you're mis-understanding the Adapter pattern. See here for more details.

I think the answer here is The Interface-Segregation Principle, which you can read about in the link in my sig. Basically, it seems like your interface is "fat", and you need to break it up into several smaller, more-focused interfaces.
Quote:Original post by ironlungs
I am confused on how the Adapter pattern is supposed to work.

The Adapter pattern does not work, that's why you can't get it to work.
Ok, that was a bit criptic - sorry for that.

The goal of the adapter pattern is to adapt an interface to something that a client class is expecting. It is implemented by encapsulating the behavior using a contract which is known to the client.

For example, imagine you have to port a game written for DirectX to Linux. The games make heavy use of DirectX, and you just can't remove that. Since your only hardware interface is OpenGL, what you're going to do is an encapsulation of OpenGL inside a DirectX interface. Result: your DirectX-to-OpenGL layer is an Adapter.

Consequence: the adapter pattern has nothing to do with inheritance (God should remove that Wikipedia article). And it has nothing to do with your question as well :)

HTH
Quote:
Original post by Emmanuel Deloget
The Adapter pattern does not work, that's why you can't get it to work.
Ok, that was a bit criptic - sorry for that.

The goal of the adapter pattern is to adapt an interface to something that a client class is expecting. It is implemented by encapsulating the behavior using a contract which is known to the client.

For example, imagine you have to port a game written for DirectX to Linux. The games make heavy use of DirectX, and you just can't remove that. Since your only hardware interface is OpenGL, what you're going to do is an encapsulation of OpenGL inside a DirectX interface. Result: your DirectX-to-OpenGL layer is an Adapter.

Consequence: the adapter pattern has nothing to do with inheritance (God should remove that Wikipedia article). And it has nothing to do with your question as well :)


Erm... So why doesn't it work?
Quote:Original post by Emmanuel Deloget
Consequence: the adapter pattern has nothing to do with inheritance (God should remove that Wikipedia article). And it has nothing to do with your question as well :)


While I agree that Adapter does not apply to the OP's situation, the Gang of Four does give two options of implementing the Adapter pattern, one of which uses multiple inheritance, just as the Wikipedia article describes it. I fail to find any significant differences between Design Patterns and the Wikipedia article.
Emmanuel, thanks for clearing that up for me. The adapter pattern makes a lot more sense to me now. I am going use RobAU78's and Gage64's suggestions to split up my interfaces. Thanks all!
Quote:Original post by Gage64
Quote:
Original post by Emmanuel Deloget
The Adapter pattern does not work, that's why you can't get it to work.


Erm... So why doesn't it work?


Well, mostly because software doesn't work - I work, and this results in the execution of the software [smile]

(Yeah, I know, that's a lame joke).

Quote:Original post by Ezbez
Quote:Original post by Emmanuel Deloget
Consequence: the adapter pattern has nothing to do with inheritance (God should remove that Wikipedia article). And it has nothing to do with your question as well :)


While I agree that Adapter does not apply to the OP's situation, the Gang of Four does give two options of implementing the Adapter pattern, one of which uses multiple inheritance, just as the Wikipedia article describes it. I fail to find any significant differences between Design Patterns and the Wikipedia article.

That doesn't mean that the GoF is right in that case - the books has many shortcomming, and this may be one of them.

<find book, search page, read article...>

OK, got it - the book (and the Wiki article) introduces the concept of a class adapter, vs. an object adapter (I suspect that the wikipedia article is strongly inspired by the GoF, maybe indirectly). The object adapter is using composition to do the job (and still inherit an interface) while the class adapter inherit both the interface and the class it adapts (something that, IMHO, breaks encapsulation as it exposes the implementation details (the adapted class) to the client).

My personnal advice would be to use only the so-called object adapter, and to forget about the class adapter - there's no reason to have both interfaces on the same class. Requiring to have both interface would mean that the object is to be used with its new interface in some part of the module and with its old interface in another part of the module - and that just doesn't make much sense. Furthermore, the GoF also says that the class adapter allows you to modify the behavior of the adaptee - because you can redefine the behavior of the virtual functions of the adaptee. This is IMHO a no-no. More exactly, this is a deliberate throw out of the Liskov substitution principle - the adapter is NOT a subtype of the adaptee, so it shall not try to act like if it was a subtype. This is better to implement that kind of behavior by using a strategy or the bridge pattern (strangely enough, the book states that the object adapter "makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself" - which is quite fun since the next pattern in the book is the bridge pattern, whose purpose is exactly to help in that situation).

The book and Wikipedia has an interesting difference when they describe the object adapter: the book inherit from an adapter interface, while the wikipedia article doesn't. These are both valid proposal - sometimes, you don't have an interface to inherit from.

This topic is closed to new replies.

Advertisement