1 / 122

Chapter 27 Decorator

Chapter 27 Decorator. Summary prepared by Kirk Scott. Muqarnas From Wikipedia, the free encyclopedia. ( Redirected from Muqarna ) Jump to: navigation , search For the magazine, see Muqarnas .

sherry
Télécharger la présentation

Chapter 27 Decorator

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 27Decorator Summary prepared by Kirk Scott

  2. MuqarnasFrom Wikipedia, the free encyclopedia • (Redirected from Muqarna)Jump to: navigation, searchFor the magazine, see Muqarnas. • Muqarnas (Arabic: مقرنص Persian: مقرنس) is a type of corbel employed as a decorative device in traditional Islamic and Persian architecture. The related mocárabe refers only to projecting elements that resemble stalactites, alveole.[1][2]

  3. Design Patterns in JavaChapter 27Decorator Summary prepared by Kirk Scott

  4. The Introduction Before the Introduction • Suppose you have a set of functionalities where you would like to mix and match the functionalities together • You would like to be able to create objects with various functionalities • This can be accomplished by repeated, wrapped construction (nested construction)

  5. Let one object be the result of one construction sequence • Calling a given method on that object results in one subset of functionalities • Let another object be the result of another construction sequence • Calling the same method on the other object results in a different subset of functionalities

  6. The book uses streams and writers from the Java API as the first example of the decorator pattern • It uses mathematical functions as the second example • This set of overheads will only cover the first example from the book • There will be another example that does not come from the book

  7. The book previews the definition of the pattern with observations along these lines: • When you think of adding functionality to an application you usually think of adding new classes or new methods to existing classes • The Decorator design pattern is a model for adding functionality to a code base in a way that leads to a specific result

  8. A certain set of methods/functionality will exist in various classes in the code base • If the pattern is used, there will be flexibility in making objects that have differing subsets of the existing functionality • At run time a program can varying sequences of construction to create objects that have differing functionality in them

  9. Book Definition of Pattern • Book definition: • The intent of Decorator is to let you compose new variations of an operation at runtime.

  10. A Classic Example: Streams and Writers • The Java API includes a set of classes that are related in such a way that they illustrate the Decorator design pattern • These are the stream and writer classes which are used for file I/O and other purposes • Let a generic FileReader or FileWriter be constructed in a program • It is connected to an external file

  11. It is possible to pass the generic reader or writer as a construction parameter when making a more specific kind of reader or writer • The new reader or writer adds I/O functionalities that don’t exist in the generic reader or writer • The book illustrates this idea in the code on the following overhead

  12. public class ShowDecorator • { • public static void main(String[] args) throws IOException • { • FileWriter file = new FileWriter("sample.txt"); • BufferedWriter writer = new BufferedWriter(file); • writer.write("a small amount of sample text"); • writer.newLine(); • writer.close(); • } • }

  13. This example illustrates nested construction • A FileWriter is constructed • It is then passed as a construction parameter when the BufferedWriter is constructed • The BufferedWriter can have FileWriter functionality since it contains a reference to FileWriter • The BufferedWriter can also add new functionality

  14. The FileWriter class and the BufferedWriter classes both have various write() methods that take various sets of parameters • The decorator pattern/nested construction opens up the possibility of overloading • This overloading can be accomplished by wrapping calls to a method of the same name on the object sent in at construction time and adding code around the calls

  15. The BufferedWriter write() method may take different parameters from the write() method in the FileWriter class • The point is that the write() method of BufferedWriter will have different functionality and calling it will give different results from calling write() on a FileWriter object • The BufferedWriter could also have entirely different methods with different functionality

  16. The PrintWriter class provides a simple, concrete illustration • An instance is constructed the same way as the book’s BufferedWriter example • FileWriter file = new FileWriter("sample.txt"); • PrintWriter writer = new PrintWriter(file); • The PrintWriter class has the methods print() and println() in addition to write(), which it shares with FileWriter

  17. From a print writer you gain the ability to write text to a file using the same method calls that you use to put text on the screen • So using the decorator pattern, not only can you overload methods; • You can also add new methods to the class with different functionality

  18. Applying the Pattern with Writers • Using the decorator pattern, programmers can write their own file I/O classes that build on the API classes • The book’s next example builds a hierarchy of classes that make it possible to format text before writing it to a file • The formatting will be simple things like making text upper case or lower case

  19. The book refers to these formatting classes as filter classes • Generically they might be referred to as decorator classes • The book begins the presentation of the topic with the UML diagram given on the next overhead • This will require a little explanation, which is given afterwards

  20. Both the Writer and FilterWriter abstract classes exist in the Java API • FilterWriter extends Writer • FilterWriter also contains an instance of Writer

  21. This illustrates the basic plan • A FilterWriter wraps an instance of its superclass, adding functionality that doesn’t exist in the superclass • A programmer can apply the pattern by extending the FilterWriter class • Structurally, the idea of a class with a reference to its superclass is already built into the Java API

  22. The Decorator and Proxy Patterns • You may recall that having a reference to a superclass object was the official design of the proxy pattern • In the proxy, the decision was ultimately made that a proxy in spirit was better • That meant just implementing a subclass without wrapping an instance of the superclass

  23. Because the structure is built into the Java API for writers, there is no avoiding it here • The Java API developers decided that this was the right structure for implementing the kind of flexible functionality that they wanted for writers • The question of the desirability of this structure will come up again when discussing the advantages of this pattern

  24. Java API Documentation of the Class FilterWriter • The Java API textual documentation for the FilterWriter class is given on the following overhead • When you read this documentation you realize that the API is preparing you to apply the Decorator design pattern if you want to

  25. FilterWriter API Documentation Snippet • Abstract class for writing filtered character streams. • The abstract class FilterWriter itself provides default methods that pass all requests to the contained stream. • Subclasses of FilterWriter should override some of these methods and may also provide additional methods and fields.

  26. Putting the OozinozFilter Class into the Hierarchy • The initial diagram for the book’s example is repeated on the next overhead • Because the OozinozFilter class is a subclass of the FileWriter class, it will contain an instance variable of type Writer • The user extends the FilterWriter class and works with the wrapped Writer • The OozinozFilter class is abstract, so concrete subclasses of it will be needed

  27. Adding Concrete Subclasses • Next, the book extends its example UML diagram • This is shown on the overhead following the next one • The diagram emphasizes that the OozinozFilter class contains a Writer (by inheritance from FilterWriter) by drawing the line directly from OozinozFilter to Writer

  28. The diagram also shows the OozinozFilter class’s concrete subclasses, which will be the actual filters in the example • Note again that the decorator structure of a subclass containing a reference to a superclass object is imposed at the top, in the Java API • The programmer makes use of the pattern by making a hierarchy of classes underneath that

  29. Each concrete filter will be constructed by passing in a writer • All concrete filters ultimately descend from the Writer class • Therefore, when constructing instances of a concrete filter, any other kind of filter can be passed in • This goes back to CS 202, where you learned that you can pass in a subclass object for a superclass formal parameter

  30. Implementing the Abstract Method in the Subclasses • OozinozFilter has an abstract write() method • This write() method takes a single int at a time as its input parameter, representing a character • The concrete, filter subclasses will have to implement this method • The filter classes are going to do their work, and differ, according to their implementation of that method

  31. The OozinozFilter class also has two concrete write() methods • The filter subclasses may simply inherit the write() methods • They may override them • They may also overload write()

  32. Code for the OozinozFilter Class • The code for the OozinozFilter class will be given on the overhead following the next one • It shows the declaration of the abstract write() method • It also shows the implementations of two concrete write() methods

  33. When looking at the code, note the following: • The first concrete write() method depends on the abstract method • The second concrete write() method depends on the first concrete method

  34. Much of the remaining explanation of how the pattern works will have to do with how method implementations depend on each other • In other words, understanding the pattern doesn’t just mean understanding nested construction • It means understanding how the methods are implemented

  35. public abstract class OozinozFilter extends FilterWriter • { • protected OozinozFilter(Writer out) • { • super(out); • } • public abstract void write(int c) throws IOException; • public void write(char cbuf[], int offset, int length) throws IOException • { • for (inti = 0; i < length; i++) • write(cbuf[offset + i]); • } • public void write(String s, int offset, int length) throws IOException • { • write(s.toCharArray(), offset, length); • } • }

  36. A Syntactical Note • In file I/O there is no effective difference between the char and int types • That means that you have a formal parameter of the one type and you can pass an actual parameter of the other type

  37. The First Concrete Method Depends on the Abstract Method • The first concrete write() method in OozinozFilter depends on the abstract write() method for its implementation • This is the call wrapped in the first concrete method: • write(cbuf[offset + i]); • That call is making use of this method: • public abstract void write(int c) throws IOException;

  38. The Second Concrete Method Depends on the First Concrete Method • The second concrete method in OozinozFilter takes a String as a parameter • This is the call wrapped in the second concrete method: • write(s.toCharArray(), offset, length); • It converts the string parameter to an array of characters and uses the first concrete method • Therefore, the second concrete method ultimately relies on the abstract write() method too

  39. Polymorphism and Dynamic Binding Trickery • The next couple of overheads will try to explain verbally how you get various versions of write in your subclasses • Let the scenario be trimmed down to one abstract superclass and one concrete subclass • Let the abstract superclass contain an abstract method • Let the abstract superclass also contain one concrete method that wraps a call to the abstract method

  40. You can’t call either method on an instance of the abstract class • There can’t be an instance of an abstract class • Both methods in the superclass affect the subclass • The subclass has to implement the abstract method • The subclass will inherit the concrete method

  41. So the subclass has a concrete implementation of the abstract method declared in the superclass • Suppose you call the inherited concrete method on a subclass object • When the code for that method is run, you encounter a call to the abstract method • Dynamic binding says that the version of the method defined in the subclass should be used

  42. An Example of a Filter • The code for the concrete LowerCaseFilter class is shown on the overhead following the next one • In it, the abstract method is implemented to change every character to lower case on output • As a result, when any write() method is called on a LowerCaseFilter object, the output will be in lowercase

  43. This happens directly if the simple write() method is called • Conversion to lowercase happens indirectly if either of the two inherited write() methods are called, since they ultimately depend on the implementation of simple write() in LowerCaseFilter • The code uses the toLowerCase() method in the Java Character class so it’s not necessary to manipulate Unicode values to get lower case

  44. public class LowerCaseFilter extends OozinozFilter • { • public LowerCaseFilter(Writer out) • { • super(out); • } • public void write(int c) throws IOException • { • out.write(Character.toLowerCase((char) c)); • } • }

More Related