Various similar-looking questions exist but I could find none that responds to my query.The possibility of having the specified aggregation relationship while implementing an interface is an essential part of my question, which is not treated in other similar questions or their solutions.
My question concerns implementation of Design Patterns in Java. For the ease of explanation, I'm considering the Command design pattern as shown in this diagram.
Since this UML representation requires that "Invoker" should be an interface and that it should also have an N-ary aggregation relationship with the "Command" interface, it's not possible to implement it if I define Invoker as a Java interface because I can't declare non-static
non-final
attributes in a Java interface and I do need to define a non-final
Collection
of "Command" objects to establish that aggregation relationship between "Invoker" and "Command".
So, I went ahead and implemented Invoker as an abstract class, which lets me have the aggregation and also provides abstraction to the implementations of "Invoker" but I'm wondering if it is a good design practice because UML does have a stereotype <<abstract>>
but the UML class diagram for this pattern explicitly specifies using an interface rathern than an abstract class. I've also done the same for "Subject" interface of "Observer" pattern implementation in Java for a similar reason.
Please let me know if there's a way to keep "Invoker" as an interface in Java and still achieve the aggregation relationship with the specified multiplicity. If what I did is the best way to do it, please let me know if it may have some adverse effects on the structure of a program I build using the pattern this way.
Adding below the class diagram of a short Java implementation of Command Pattern that I put up for enhanced clarity of the question. I've configured "Controller" here as the "Invoker" interface that can be implemented in different ways, e.g. "InfraredRemote Controller" in this diagram. But the Design Pattern requirement of aggregation relationship between "Invoker" and "Command" interfaces made me configure "Controller" as an abstract class because I could not find any way to achieve the required multiplicity and relationship when I configured "Controller" as an interface.
Thanks to a good brainstorming session with @zapl and some more research on the web, I've found the answer through this article that makes reference to this page of a very interesting book.
“Program to an interface”, really means “Program to a supertype”. – Head First, Design Patterns
Apparently, the use of word 'Interface' in UML specifications of Design Patterns is more generic and only denotes abstraction, viz. supertype, which can be achieved in the Java implementation by using either an Interface or an abstract class. Although the stereotypes for <<abstract>>
classes exist in UML, they are rarely used to describe Design Patterns.
And as it's not possible to achieve the n-ary multiplicity between Java interfaces, the UML "Invoker" interface in the example I used in my question needs to be implemented using a Java interface that is implemented by an abstract class and by extending that abstract class with concrete Invoker subclasses. This would maintain malleability of the code while preserving the abstraction as shown in the implementation below:
Here the client "Implementer" uses the Java interface which is implemented by a Java abstract class to provide the multiplicity with "Command" interface and the access to that multiplicity to the concrete Invokers; these two together represent the "Invoker" interface in the UML specification of the Command Design Pattern.
I'm leaving my answer open for comments as of now, expecting comments on something I may have missed. If I don't get any, I'll accept my answer in, say, two days.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments