Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
204
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

Implementation – The Implementation interface represents the underlying functionality used by the

Abstraction instances.

ConcreteImplementation – ConcreteImplementation implements the Implementation interface. It provides

the behavior and structure for Implementation classes.

Benefits and Drawbacks

The Bridge offers the potential to share underlying implementation objects among multiple abstraction objects. It provides greater flexibility when changing implementations, and the changes can occur without any action required on the part of the client.

When designing an application that uses the Bridge pattern, it is important to properly define which responsibilities belong to the functional abstraction and which belong to the internal implementation class. Likewise, you must carefully consider what represents the true base model for your implementation of the Bridge pattern. A common problem you might experience when using the Bridge stems from developing the pattern implementation around one or two possible variations. The danger is that future development of the pattern will reveal that some of the assumed elements of core behavior actually represented specific variations based on the abstraction and/or implementation.

Like many of the distributed object patterns, you might also need to consider what the concept of equality really means for the Bridge. Does the abstraction or the implementation, or both, represent the important object for comparison?

Pattern Variants

Pattern variants include the following:

Automatic Bridges – Some Bridge pattern implementations are made to vary their implementation without any action by the end user, relying instead on information provided from the application or operating platform to customize themselves.

Shared implementations – Some implementation classes, especially stateless ones (classes that do not maintain an internal state), can be shared among multiple application objects. Depending on how widely they can be shared, such classes can potentially be implemented as an interface.

Single implementation – Sometimes there is only a single implementation class, which services multiple abstraction classes. If there is only a single implementation, it is probably not necessary to define a base class for the implementation part of a Bridge.

Related Patterns

Related patterns include the following:

Adapter (page 142) – The Bridge and the Adapter pattern are very similar in structure but differ in their intent. The Bridge pattern separates the abstraction and the implementation to allow both to change independently, and is an upfront design choice. The Adapter pattern enables use of an object whose interface would otherwise be incompatible.

Singleton (page 34) – As mentioned in the variants section the Singleton pattern can be used when “ implementation ” classes can be shared.

Flyweight (page 183) – When the tree structure becomes large, applying the Flyweight pattern can help reduce the number of objects managed by the tree.

Example

Note:

For a full working example of this code example, with additional supporting classes and/or a RunPattern class, see “ Bridge ” on page 448 of the “ Full Code Examples ” appendix.

105

This example shows how to use the Bridge pattern to extend the functionality of a To Do list for the PIM. The To Do list is fairly straightforward—simply a list with the ability to add and remove Strings.

For the Bridge pattern, an element is defined in two parts: an abstraction and an implementation. The implementation is the class that does all the real work—in this case, it stores and retrieves list entries. The general behavior for the PIM list is defined in the ListImpl interface.

Example 3.5 ListImpl.java

1.public interface ListImpl{

2.public void addItem(String item);

3.public void addItem(String item, int position);

4.public void removeItem(String item);

5.public int getNumberOfItems();

6.public String getItem(int index);

7.public boolean supportsOrdering();

8.}

The OrderedListImpl class implements ListImpl, and stores list entries in an internal ArrayList object.

Example 3.6 OrderedListImpl.java

1.import java.util.ArrayList;

2.public class OrderedListImpl implements ListImpl{

3.private ArrayList items = new ArrayList();

4.

5.public void addItem(String item){

6.if (!items.contains(item)){

7. items.add(item);

8.}

9.}

10.public void addItem(String item, int position){

11.if (!items.contains(item)){

12. items.add(position, item);

13.}

14.}

16.public void removeItem(String item){

17.if (items.contains(item)){

18. items.remove(items.indexOf(item));

19.}

20.}

22.public boolean supportsOrdering(){

23.return true;

24.}

25.

26.public int getNumberOfItems(){

27.return items.size();

28.}

29.

30.public String getItem(int index){

31.if (index < items.size()){

32. return (String)items.get(index);

33.}

34.return null;

35.}

36.}

The abstraction represents the operations on the list that are available to the outside world. The BaseList class provides general list capabilities.

Example 3.7 BaseList.java

1.public class BaseList{

2.protected ListImpl implementor;

4.public void setImplementor(ListImpl impl){

5.implementor = impl;

6.}

7.

8.public void add(String item){

9.implementor.addItem(item);

10.}

11.public void add(String item, int position){

106

12.if (implementor.supportsOrdering()){

13. implementor.addItem(item, position);

14.}

15.}

17.public void remove(String item){

18.implementor.removeItem(item);

19.}

20.

21.public String get(int index){

22.return implementor.getItem(index);

23.}

24.

25.public int count(){

26.return implementor.getNumberOfItems();

27.}

28.}

Note that all the operations are delegated to the implementer variable, which represents the list implementation. Whenever operations are requested of the List, they are actually delegated “across the bridge” to the associated

ListImpl object.

It’s easy to extend the features provided by the BaseList —you subclass the BaseList and add additional functionality. The NumberedList class demonstrates the power of the Bridge; by overriding the get method, the class is able to provide numbering of the items on the list.

Example 3.8 NumberedList.java

1.public class NumberedList extends BaseList{

2.public String get(int index){

3.return (index + 1) + ". " + super.get(index);

4.}

5.}

107