Flylib.com

Books Software

 
 
 

Related Patterns

[Previous] [Next]

Related Patterns

The Bridge (Chapter 5), the Smart Proxy (Chapter 6), and the Event Service (Chapter 13) design patterns are all basically adapters, because they provide interfaces expected by clients that wrap different implementations that were otherwise incompatible (and not intended to be used by the client in question). However, each of these patterns is a solution for a specific problem domain and should be applied according to the problem it addresses.

[Previous] [Next]

Chapter 5

Bridge

As defined in Chapter 2, interface inheritance is the means by which you obtain reusability in Microsoft Visual Basic. Different classes can inherit the same interface. Each class can then define a unique implementation for that interface. An object exposes the interfaces supported by the class the object is based on. Communication with an object is possible only through the interfaces it exposes.

For this reason, a Visual Basic object-oriented developer programs to an interface rather than to a class. As a result, an ideal system is said to exist when the consumer code , which initiates interaction with one or more interfaces, is written only once. The objects that are bound to the interfaces used by the consumer can easily be replaced by other objects of different classes, so long as those classes support the same interfaces. Binding to a different object results in different behavior of the consumer for the same interfaces, which leads to polymorphism. As you'll recall from Chapter 2, polymorphism is the ability to dynamically bind an interface to an object that supports it.

As you'll also recall from Chapter 2, reusing an interface requires you to use the keyword Implements , followed by the interface name , in a given class module. The class must then implement all the properties and methods defined in that interface. This is the conventional way to reuse an interface, but the Bridge design pattern accomplishes the same end while providing benefits not realized with interface inheritance.

[Previous] [Next]

Purpose

The Bridge design pattern breaks the direct and permanent link between the interface and the implementation formed by conventional language features, which results in the plug-and-play capability of either the interface or the implementation of the interface.

[Previous] [Next]

Utilization

The Bridge design pattern is useful in the following circumstances:

  • The client referencing an interface defined in an ActiveX component is written in a language that doesn't support inheritance. For example, interfaces defined in an ActiveX DLL that has been written in Visual Basic cannot be used in Microsoft Excel 97 because Microsoft Excel 97 Visual Basic for Applications (VBA) does not support interface inheritance.
  • Statically binding an interface to a class is too restrictive . For instance, you might want to do any of the following:
    • Implement only part of an interface.
    • Provide an implementation that is not restricted to one class module.
    • Dynamically assign an implementation to an object at run time.
    • Modify, extend, or replace an interface without having to retrofit those changes in all classes that inherit the interface.
    • Reuse a single implementation with multiple interfaces.
[Previous] [Next]

Scenario

Your MIS manager has come to the realization that all application systems developed and supported by your department should retain personal configurations for each user . The main reason for this idea is that not all users use a system in the same way. While providing a single approach to configuring all systems might be consistent, it might also be too rigid. Consequently, some users will love the system, some will hate it, and still others will have mixed feelings about it. When users are not pleased with a system, it sometimes reflects negatively on the department. If users have a choice, they might opt to not use the system at all. Hey, who said life was fair?

In an effort to minimize the possibility that this situation might occur, your manager pitches an idea of maintaining user profiles for system elements such as user interface (UI) settings (such as window positions , toolbar selections, and color settings), the name of the most recently used system host, and so forth. Your manager points out that no one system is similar to another in functionality, user interface, or infrastructure, so you really have two choices: you can either solve the problem on a system-by-system basis, or you can build a user profile framework that is reusable in all systems. In keeping with the primary theme of this book, which is how to create reusable solutions, you will opt for the latter alternative.

You will be building a User Profile Service framework—packaged in an ActiveX DLL—that creates and stores user profile objects and retrieves those objects upon request from a given user profile repository. (See Chapter 11, "Repository," for more on this type of design pattern.) The User Profile Service framework takes into account the list of possible attributes that could be stored in a user profile by defining one UserProfile class that is flexible enough to contain any number of attributes of any given type. In addition, the User Profile Service framework defines a UserProfileRepository interface, which provides a uniform interface for concrete implementations for creating, storing, and retrieving user profiles from Microsoft SQL Server and Microsoft Access. Your framework is extensible because a consumer of your framework can define its own concrete repository classes for other data sources, such as the Windows Registry and ASCII text files, by inheriting the UserProfileRepository interface in a class module.

Exposing the UserProfileRepository interface to consumers of your User Profile Service framework might seem sufficient for making your framework reusable and extensible. But you must not forget that your framework exists in an ActiveX component; therefore, the benefits of your framework are not limited to just Visual Basic consumers. Any programming language that supports ActiveX can profit in the same manner—however, not all programming languages are created equal.

For instance, let's assume you have applications in your department that are add-ins to Excel 97. (If you've upgraded to Excel 2000, you don't need to worry about this because Excel 2000 supports interface inheritance.) It's important to your manager that these applications retain user profiles. You're in luck because Excel 97 supports the use of ActiveX technologies, such as the ActiveX DLL where the User Profile Service framework resides. With the assistance of Excel's robust macro language technology (which was completely revamped based on VBA), you can easily write framework consumer code in Excel that is almost identical to the same code in Visual Basic. Excel VBA and Visual Basic are so similar that the untrained eye can barely differentiate between the two. In spite of this fact, Excel 97 VBA does not support interface inheritance, which by convention is the only way possible to extend the User Profile Service framework. Besides, you have discovered that these Excel 97 applications currently do not interact with SQL Server or Access. Adding this dependency to gain the benefits of retaining user profile settings is not an acceptable solution within the context of your situation. The desired solution is to implement a UserProfileRepository interface that retains user profile settings in an Excel 97 workbook.

Incorporating a Bridge design pattern in your User Profile Service framework will allow Excel 97 VBA programmers to extend your framework to support an Excel 97 workbook repository without any disruption to the framework code. As illustrated in the class diagram in Figure 5-1, the Bridge design pattern is implemented as a concrete class that inherits the UserProfileRepository interface, similar to the way in which the SQL Server and Access repository classes inherit an interface. The difference is that the implementation of the Bridge class does not persist user profiles to a data source like the other concrete repository classes do.

{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

click to view at full size.

Figure 5-1. Class diagram of the User Profile Service framework.

For each method defined in the UserProfileRepository interface, the Bridge class defines an analogous event that can be captured by event handlers defined in other classes. In this scenario, the consumer of these events is an Excel 97 workbook repository class defined in an Excel 97 add-in. (See Figure 5-2.) This particular implementation of the Bridge design pattern delegates method invocations from the UserProfileRepository interface to any class object that subscribes to the event.

click to view at full size.

Figure 5-2. Class diagram showing the relationship between the UserProfileRepository interface and the implementation of that interface defined in the Excel 97 workbook repository class.