150 likes | 171 Views
Learn about decorators, dynamic object responsibilities, avoiding subclassing, and practical Java examples including UML and code snippets.
E N D
Decorator Josh Voils and Ralph Rodkey
GoF Definition of Intent • Attach additional responsibilities to an object dynamically • Provide an alternative to subclassing for extending functionality
aBorderDecorator aScrollDecorator component component GoF Example • We want to add a border and a scroll bar to a TextView object • Let’s use a decorator! aTextView Instance diagram for our example
VisualComponent Draw() component TextView Decorator component->Draw() Decorator::Draw() DrawBorder() Draw() Draw() ScrollDecorator BorderDecorator Draw() ScrollTo() scrollPosition Draw() DrawBorder() borderWidth The UML
Challenge A • Why use a Decorator instead of subclassing?
Streams • Java Streams are an example of a decorator • Challenge B: • Draw an analogy between the OutputStream hierarchy and the TextView hierarchy
Oozinoz Writer • A writer is a stream that reads characters • Java Provides the filterWriter class to facilitate the creation of new filters • Here Metsker uses a FilterWriter to create an OozinozFilter
OozinozFilter Code package com.oozinoz.io; import java.io.*; public abstract class OozinozFilter extends FilterWriter { protected OozinozFilter(Writer out) { super(out); } public void write(char cbuf[], int off, int len) throws IOException { for (int i = 0; i < len; i++) { write(cbuf[i]); } } public abstract void write(int c) throws IOException; public void write(String s, int off, int len) throws IOException { write(s.toCharArray(), off, len); } }
O.W. (cont) • From the abstract OozinozFilter he creates some custom filters package com.oozinoz.io; import java.io.*; public class UpperCaseFilter extends OozinozFilter { public UpperCaseFilter(Writer out) { super(out); } public void write(int c) throws IOException { out.write(Character.toUpperCase((char) c)); } }
Application of Filters package com.oozinoz.applications; import java.io.*; import com.oozinoz.io.*; public class ShowFilters { public static void main(String args[]) throws IOException { BufferedReader in = new BufferedReader(new FileReader(args[0])); Writer out = new FileWriter(args[1]); out = new WrapFilter(new BufferedWriter(out), 40); out = new TitleCaseFilter(out); while (true) { String s = in.readLine(); if (s == null) { break; } out.write(s + "\n"); } out.close(); in.close(); } } This program line-wraps text in an input file and puts it in title case
Challenge 27.1 If you want to direct output to System.out instead of to a file, you can create a Writer object that directs its output to System.out: Writer out = new PrintWriter(System.out); Write a snippet of code to define a Writer object that wraps text at 15 characters, centers the text, sets the text to random casing, and directs the output to System.out.
Challenge 27.1 Answer One answer is: Writer out = new PrintWriter(System.out); out = new WrapFilter(new BufferedWriter(out), 15); ((WrapFilter) out).setCenter(true); out = new RandomCaseFilter(out); Alternatively: WrapFilter out = new WrapFilter( new BufferedWriter( new RandomCaseFilter( new PrintWriter(System.out))), 15); out.setCenter(true);
Challenge 27.5 (sorta) package com.oozinoz.applications; import javax.swing.*; import javax.swing.border.*; import java.awt.*; import com.oozinoz.ui.*; public class ShowBorders { protected static JButton createButton(String label) { JButton b = new JButton(label); b.setFont(SwingFacade.getStandardFont()); b.setFocusPainted(false); return b; } public static void main(String[] args) { JButton ignite = createButton("Ignite"); JButton launch = createButton("Launch"); launch.setBorder( new CompoundBorder( new LineBorder(Color.black, 4), new CompoundBorder( new BevelBorder(BevelBorder.RAISED), new EmptyBorder(10, 10, 10, 10)))); JPanel p = new JPanel(); p.add(ignite); p.add(launch); SwingFacade.launch(p, " Borders"); } } • Why are swing borders not decorators?