Presentation is loading. Please wait.

Presentation is loading. Please wait.

COMP 121 Week 12: Decorator and Adapter Design Patterns.

Similar presentations


Presentation on theme: "COMP 121 Week 12: Decorator and Adapter Design Patterns."— Presentation transcript:

1 COMP 121 Week 12: Decorator and Adapter Design Patterns

2 Decorator Design Pattern Intent: augment objects with new responsibilities Use when: –Extension by subclassing is impractical (want to add responsibilities to individual objects, not an entire class) –Responsibilities can be withdrawn Decorator implements the same interface as the object it decorates A "shell" or "wrapper" around an object –Requests that come in to the decorator are "forwarded" to the object it decorates

3 Decorator Design Pattern (cont’d) The key to a successful Decorator is to have a set of objects defined by an interface Decorator implements the interface and takes an object of that interface type as a parameter of its constructor, which it saves internally When a method is called on the decorator: –May do some pre-processing before calling the same method on the decorated object –May do some post-processing on the results returned from the same method in the decorated object

4 Why Use a Decorator Pattern More flexibility than inheritance –Responsibilities can be added or removed at runtime) Avoids feature-laded classes high up in the hierarchy A "pay-as-you-go" approach to adding responsibilities –Can define a simple class –Add functionality incrementally with decorators

5 Decorator Example 1: Sunglasses People “decorate” themselves in many different ways (for example clothing, makeup, jewelry, glasses) Sunglasses intercept incoming light and provide modified light to the eyes –The eyes still get basically the same type of input (stream of light into the eyes) –Input (light) is transformed by the sunglasses, but is still a form of light (not converted into sound or smell) Eyes take in light whether or not the decorator (pair of sunglasses) is present –This “transparent” property of Decorator is what allows Decorators to be chained together –Person may wear contact lenses AND sunglasses

6 Decorator Example 2: Audio Enhancers/Filters Electronic devices or software can be used to enhance, morph, or disguise your voice –Change vocal pitch and timbre or apply other effects such as volume or vibrato Filter changes the audio stream –Input is an audio stream –Output is an audio stream Audio may be passed through a series of filters to get the sound qualities desired –Chain of decorators Used with musical instruments, too

7 Decorator Example 3: Java File I/O Basic I/O classes are InputStream, OutputStream, Reader and Writer Need to add behaviors to the stream to get the desired results –BufferedInputStream adds buffering for performance –DataInputStream adds input of primitive data types FileInputStream in = new FileInputStream("test.dat"); BufferedInputStream bin = new BufferedInputStream(in); DataInputStream dbin = new DataInputStream(bin);

8 Decorator Example 4: Unmodifiable Collection List products = new ArrayList (); products.add(new Product("Book")); products.add(new Product("Game")); Collection readOnlyProducts = new UnmodifiableCollection (products); new UnmodifiableCollection (products); Product p = readOnlyProducts.get(1); // returns Game readOnlyProducts.add(new Product(...)); // Throws exception products.add(new Product("Puzzle")); int numProducts = readOnlyProducts.size(); // returns 3

9 public class CollectionDecorator implements Collection { protected Collection coll; protected Collection coll; public CollectionDecorator(Collection c) { public CollectionDecorator(Collection c) { coll = c; coll = c; } public boolean add(E obj) { public boolean add(E obj) { return coll.add(obj); return coll.add(obj); } public int size() { public int size() { return coll.size(); return coll.size(); } // Other methods similar // Other methods similar}

10 public class IteratorDecorator implements Iterator { protected Iterator iter; protected Iterator iter; public IteratorDecorator(Iterator it) { public IteratorDecorator(Iterator it) { iter = it; iter = it; } public boolean hasNext() { public boolean hasNext() { return iter.hasNext(); return iter.hasNext(); } public E next() { public E next() { return iter.next(); return iter.next(); } public void remove() { public void remove() { iter.remove(); iter.remove(); }}

11 public class UnmodifiableCollection extends CollectionDecorator { public UnmodifiableCollection(Collection coll) { public UnmodifiableCollection(Collection coll) { super(coll); super(coll); } public boolean add(E obj) { public boolean add(E obj) { throw new UnsupportedOperationException("add not supported"); throw new UnsupportedOperationException("add not supported"); } // Similar implementation for all methods that would change contents // Similar implementation for all methods that would change contents public Iterator iterator() { public Iterator iterator() { return new UnmodifiableIterator (coll.iterator()); return new UnmodifiableIterator (coll.iterator()); }}

12 public class UnmodifiableIterator extends IteratorDecorator { public UnmodifiableIterator(Iterator iter) { public UnmodifiableIterator(Iterator iter) { super(iter); super(iter); } @Override @Override public void remove() { public void remove() { throw new UnsupportedOperationException("remove not supported"); throw new UnsupportedOperationException("remove not supported"); }}

13 Question: How does the Decorator design pattern differ from the Strategy design pattern?

14 Answer: The Decorator pattern changes the “skin” of an object –The decorator is a wrapper or outer layer that changes the behavior of an object –The object doesn’t know about its decorators The Strategy pattern changes the “guts” –The strategy is changed by using a different strategy object that alters or extends the behavior of an object –The object knows about the available strategies

15 Adapter Design Pattern Intent: –Convert the interface of a class into another interface that the clients expect –Lets classes work together that otherwise couldn't because of incompatible interfaces Use when: –You want to use an existing class and its interface doesn't match the one you need –You want to create a reusable class that cooperates with unrelated or unforeseen classes (classes that don't have compatible interfaces) Another type of “shell” or “wrapper” around an object –Requests that come in to the adapter are forwarded to the object being adapted, but the actual method being called is different

16 Adapter Example 1: Socket Wrench A socket attaches to a ratchet, provided that the size of the drive is the same Typical drive sizes in the United States are 1/2" and 1/4“ –A 1/2" drive ratchet will not fit into a 1/4" drive socket unless an adapter is used –A 1/2" to 1/4" adapter has a 1/2" female connection to fit on the 1/2" drive ratchet, and a 1/4" male connection to fit in the 1/4" drive socket

17 Adapter Example 2: Travel Adapter Kits In different parts of the world, different wattages and outlet types make it impossible to use personal appliances (shavers, hair dryers, etc.) without modification A travel adapter kit allows you to: –Plug your appliance into a converter to convert the wattage –Plug the converter into the wall outlet by adapting the plug type

18 Adapter Example 3: Replacing Legacy or 3rd Party Software The adapter pattern is commonly used in applications where some third party software is being replaced with some other software Rather than rewrite the application to use the new software interface, use an adapter to adapt the old interface to the new interface: –The application code calls the old interface, but is now making those requests via the adapter –The adapter converts the requests to requests that are compatible with the new software –The adapter may do some pre- or post-processing in order to adapt request

19 Adapter Code Example public class Product { public Sku getSku() { public Sku getSku() { return sku; return sku; } public void setSku(Sku sku) { public void setSku(Sku sku) { this.sku = sku; this.sku = sku; } public Money getCost() { public Money getCost() { return cost; return cost; } public void setCost(Money cost) { public void setCost(Money cost) { this.cost = cost; this.cost = cost; } public Money calculatePrice() { … } public Money calculatePrice() { … } public Money calculateMarkup() { … } public Money calculateMarkup() { … }}

20 // We want to use this existing class in place of Product public class InventoryItem { private String barCode; private String barCode; private String itemName; private String itemName; private double purchasePrice; private double purchasePrice; private double salePrice; private double salePrice; public double sellsFor() { public double sellsFor() { return salesPrice; return salesPrice; } public String getBarCode() { public String getBarCode() { return barCode; return barCode; } // More methods here // More methods here}

21 public interface Product { Sku getSku(); Sku getSku(); void setSku(Sku sku); void setSku(Sku sku); Money getCost(); Money getCost(); void setCost(Money cost); void setCost(Money cost); Money calculatePrice(); Money calculatePrice(); Money calculateMarkup(); Money calculateMarkup(); // More methods… // More methods…}

22 public class InventoryItemToProductAdapter { private InventoryItem item; private InventoryItem item; public InventoryItemToProductAdapter(InventoryItem i) { public InventoryItemToProductAdapter(InventoryItem i) { item = i; item = i; } public void setCost(Money cost) { public void setCost(Money cost) { item.setPurchasePrice(cost); item.setPurchasePrice(cost); } public Money calculatePrice() { public Money calculatePrice() { return new Money(item.sellsFor()); return new Money(item.sellsFor()); } // More methods… // More methods…}

23 /* /* * Now that we have the adapter, we can add InventoryItem * Now that we have the adapter, we can add InventoryItem * objects to a list of products and treat them like any * objects to a list of products and treat them like any * other product * other product */ */ List products = new ArrayList (); List products = new ArrayList (); InventoryItem item = new InventoryItem(…); InventoryItem item = new InventoryItem(…); products.add(new InventoryItemToProductAdapter(item)); products.add(new InventoryItemToProductAdapter(item)); … // Having a half-off sale // Having a half-off sale for(Product product : products) { for(Product product : products) { product.setCost(product.getCost().div(2)); product.setCost(product.getCost().div(2)); }

24 Question? How does the Adapter design pattern differ from the Decorator design pattern?

25 Answer: The Decorator pattern only changes the object’s responsibilities, not its interface The Adapter pattern changes the object’s interface, often without changing its responsibilities

26 Questions?


Download ppt "COMP 121 Week 12: Decorator and Adapter Design Patterns."

Similar presentations


Ads by Google