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

Structural Pattern Code Examples

Adapter

In this example, the PIM uses an API provided by a foreign source. Two files represent the interface into a purchased set of classes intended to represent contacts. The basic operations are defined in the interface called

Chovnatlh.

Example A.133 Chovnatlh.java

1.public interface Chovnatlh{

2.public String tlhapWa$DIchPong();

3.public String tlhapQavPong();

4.public String tlhapPatlh();

5.public String tlhapGhom();

6.

7.public void cherWa$DIchPong(String chu$wa$DIchPong);

8.public void cherQavPong(String chu$QavPong);

9.public void cherPatlh(String chu$patlh);

10.public void cherGhom(String chu$ghom);

11.}

The implementation for these methods is provided in the associated class, ChovnatlhImpl.

Example A.134 ChovnatlhImpl.java

1.// pong = name

2.// wa'DIch = first

3.// Qav = last

4.// patlh = rank (title)

5.// ghom = group (organization)

6.// tlhap = take (get)

7.// cher = set up (set)

8.// chu' = new

9.// chovnatlh = specimen (contact)

11.

 

 

 

Y

 

 

 

L

public class ChovnatlhImpl implements Chovnatlh{

12.

private String wa$DIchPong;

 

F

13.

private String QavPong;

 

 

14.

private String patlh;

 

 

15.

private String ghom;

E

M

16.

T

A

17.

public ChovnatlhImpl(){ }

 

 

 

18.

public ChovnatlhImpl(String chu$wa$DIchPong, String chu$QavPong,

19.

String chu$patlh, String chu$ghom){

20.

wa$DIchPong = chu$wa$DIchPong;

21.

QavPong = chu$QavPong;

 

 

22.

patlh = chu$patlh;

 

 

 

23.

ghom = chu$ghom;

 

 

 

24.

}

 

 

 

25.

 

 

 

 

26.public String tlhapWa$DIchPong(){ return wa$DIchPong; }

27.public String tlhapQavPong(){ return QavPong; }

28.public String tlhapPatlh(){ return patlh; }

29.public String tlhapGhom(){ return ghom; }

30.

31.public void cherWa$DIchPong(String chu$wa$DIchPong){ wa$DIchPong = chu$wa$DIchPong; }

32.public void cherQavPong(String chu$QavPong){ QavPong = chu$QavPong; }

33.public void cherPatlh(String chu$patlh){ patlh = chu$patlh; }

34.public void cherGhom(String chu$ghom){ ghom = chu$ghom; }

35.

36.public String toString(){

37.return wa$DIchPong + " " + QavPong + ": " + patlh + ", " + ghom;

38.}

39.}

With help from a translator, it is possible to match the methods to those found in the Contact interface. The ContactAdapter class performs this task by using a variable to hold an internal ChovnatlhImpl object. This object manages the information required to hold the Contact information: name, title, and organization.

Example A.135 Contact.java

1.

import

java.io.Serializable;

TEAM FLY PRESENTS

2.

public

interface Contact extends Serializable{

291

3.public static final String SPACE = " ";

4.public String getFirstName();

5.public String getLastName();

6.public String getTitle();

7.public String getOrganization();

8.

9.public void setFirstName(String newFirstName);

10.public void setLastName(String newLastName);

11.public void setTitle(String newTitle);

12.public void setOrganization(String newOrganization);

13.}

Example A.136 ContactAdapter.java

1.public class ContactAdapter implements Contact{

2.private Chovnatlh contact;

3.

4.public ContactAdapter(){

5.contact = new ChovnatlhImpl();

6.}

7.public ContactAdapter(Chovnatlh newContact){

8.contact = newContact;

9.}

10.

11.public String getFirstName(){

12.return contact.tlhapWa$DIchPong();

13.}

14.public String getLastName(){

15.return contact.tlhapQavPong();

16.}

17.public String getTitle(){

18.return contact.tlhapPatlh();

19.}

20.public String getOrganization(){

21.return contact.tlhapGhom();

22.}

23.

24.public void setContact(Chovnatlh newContact){

25.contact = newContact;

26.}

27.public void setFirstName(String newFirstName){

28.contact.cherWa$DIchPong(newFirstName);

29.}

30.public void setLastName(String newLastName){

31.contact.cherQavPong(newLastName);

32.}

33.public void setTitle(String newTitle){

34.contact.cherPatlh(newTitle);

35.}

36.public void setOrganization(String newOrganization){

37.contact.cherGhom(newOrganization);

38.}

39.

40.public String toString(){

41.return contact.toString();

42.}

43.}

The RunPattern class demonstrates the use of the adapter by creating a ContactAdapter, then using it to create a sample Contact. The ChovnatlhImpl object stores the actual information and makes it available to

RunPattern when the toString method is called on the ContactAdapter.

Example A.137 Contact.java

1.import java.io.Serializable;

2.public interface Contact extends Serializable{

3.public static final String SPACE = " ";

4.public String getFirstName();

5.public String getLastName();

6.public String getTitle();

7.public String getOrganization();

8.

9.public void setFirstName(String newFirstName);

10.public void setLastName(String newLastName);

11.public void setTitle(String newTitle);

12.public void setOrganization(String newOrganization);

13.}

292

Bridge

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 A.138 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 A.139 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 A.140 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){

293

9.implementor.addItem(item);

10.}

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

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 A.141 NumberedList.java

1.public class NumberedList extends BaseList{

2.public String get(int index){

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

4.}

5.}

The OrnamentedList class shows another abstraction. In this case, the extension allows each list item to be prepended with a designated symbol, such as an asterisk or other character.

Example A.142 OrnamentedList.java

1.public class OrnamentedList extends BaseList{

2.private char itemType;

3.

4.public char getItemType(){ return itemType; }

5.public void setItemType(char newItemType){

6.if (newItemType > ' '){

7. itemType = newItemType;

8.}

9.}

11.public String get(int index){

12.return itemType + " " + super.get(index);

13.}

14.}

RunPattern demonstrates this example in action. The main method creates an OrderedListImpl object and populates it with items. Next, it associates the implementation with three different abstraction objects, and prints the list contents. This illustrates two important principles: that the same implementation can be used with multiple

abstractions, and that each abstraction can modify the appearance of the underlying data.

Example A.143 RunPattern.java

1.public class RunPattern{

2.public static void main(String [] arguments){

3.System.out.println("Example for the Bridge pattern");

4.System.out.println();

5.System.out.println("This example divides complex behavior among two");

6.System.out.println(" classes - the abstraction and the implementation.");

7.System.out.println();

8.System.out.println("In this case, there are two classes which can provide the");

9.System.out.println(" abstraction - BaseList and OrnamentedList. The BaseList");

10.System.out.println(" provides core funtionality, while the OrnamentedList");

11.System.out.println(" expands on the model by adding a list character.");

294

12.System.out.println();

13.System.out.println("The OrderedListImpl class provides the underlying storage");

14.System.out.println(" capability for the list, and can be flexibly paired with");

15.System.out.println(" either of the classes which provide the abstraction.");

16.

17.System.out.println("Creating the OrderedListImpl object.");

18.ListImpl implementation = new OrderedListImpl();

19.

20.System.out.println("Creating the BaseList object.");

21.BaseList listOne = new BaseList();

22.listOne.setImplementor(implementation);

23.System.out.println();

24.

25.System.out.println("Adding elements to the list.");

26.listOne.add("One");

27.listOne.add("Two");

28.listOne.add("Three");

29.listOne.add("Four");

30.System.out.println();

31.

32.System.out.println("Creating an OrnamentedList object.");

33.OrnamentedList listTwo = new OrnamentedList();

34.listTwo.setImplementor(implementation);

35.listTwo.setItemType('+');

36.System.out.println();

37.

38.System.out.println("Creating an NumberedList object.");

39.NumberedList listThree = new NumberedList();

40.listThree.setImplementor(implementation);

41.System.out.println();

42.

43.System.out.println("Printing out first list (BaseList)");

44.for (int i = 0; i < listOne.count(); i++){

45. System.out.println("\t" + listOne.get(i));

46.}

47.System.out.println();

49.System.out.println("Printing out second list (OrnamentedList)");

50.for (int i = 0; i < listTwo.count(); i++){

51. System.out.println("\t" + listTwo.get(i));

52.}

53.System.out.println();

55.System.out.println("Printing our third list (NumberedList)");

56.for (int i = 0; i < listThree.count(); i++){

57. System.out.println("\t" + listThree.get(i));

58.}

59.}

60.}

295