Jump to content

Interface pattern

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by 195.115.177.41 (talk) at 14:04, 21 December 2007 (added an eiffel example). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

In computer science, the interface pattern isn't a specific pattern amongst design patterns. It's a general method for structuring programs so that they're simpler to understand. In general, an interface is a class which provides the programmer with the information what operations can be performed on an instance of a class that implements this interface, as opposed to how those operations are internally implemented.

An interface could contain a set of objects and provide simpler, higher-level functions to the programmer (for example, the Façade_pattern); it could provide a cleaner or more specific way of using complicated classes (a "wrapper" class); it could be used to act as the "glue" between two different APIs (the adapter pattern); and much more.

Other kinds of interface patterns are: delegation pattern, composite pattern, and bridge pattern.

Implementation

C++

In opposite to Java, where interfaces are common, this pattern is not very often used in C++. But sometimes it can help to reduce dependencies. For libraries using a facade class to hide the internal implementation to a component the interface pattern can increase the readability of the code.

As the facade class is an interface to the library its header file needs to be available from outside of the library. So it has to be placed in the include directory of the library. But this facade class perhaps needs attributes of other classes of the library. So its header file has to include the header files of the other classes. So these header files also need to be trackable and therefor they have to be placed also in the include directory of the library. Now the strategy, that only the interfaces of the library are defined in its include directory is violated. This problem could be solved by the usage of the interface pattern.

To implement an interface to a class A an interface class A_Interface has to be created, defining the interface methods of class A as abstract functions. Class A has to be derived from this class A_Interface.

Attention! Do not forget to define the destructor of class A_Interface to be virtual!

Then the header file of class A can reside in the source directory of the library while the header file of class A_Interface stays as the interface in the include directory.

As the interface class is abstract and the implementation class is unknown from outside of the library, a factory is needed to create objects of class A. It makes sense to create a class method in the interface class A_Interface to work as a factory method.

 class A_Interface {
  public:
   static A_Interface* create_A();
   virtual ~A_Interface() {}
   virtual do_something() = 0;
 };

 class A : public A_Interface {
  public:
   do_something();
 };

Eiffel

The Eiffel programming language supports multiple inheritance so it doesn't need the Java concept of Interface. Insteed, any class that is deferred acts like an interface. The deferred classes are the classes that have deferred features. At the opposite of Java, these features can express contracts and have default bodies.

The following example shows the interface for some URI getter.

 deferred class URI_GETTER feature
    uri: URI
    is_loaded: BOOLEAN is deferred end
    content: STRING is require is_loaded deferred ensure content/=Void end
    header: URI_GETTER_HEADER is require is_loaded deferred ensure header/=Void end
    clean is deferred ensure not is_loaded end
    load is deferred ensure is_loaded end
    reload is require is_loaded do load end
  end

 class URI_GETTER_FTP inherit URI_GETTER creation make feature
    make(a_uri: URI) is
       require a_uri.method.equals(once "ftp") do
          uri:=a_uri; create {URI_GETTER_HEADER_FTP} header end
    is_loaded: BOOLEAN is do Result := content/=Void end
    content: STRING
    header: URI_GETTER_HEADER_FTP
    clean is do content:=Void end
    load is do ... end
 end