1 Proxy Design Pattern Intent –Provide a surrogate or placeholder for another object to control access to it. An example –Image handling in a web browser When a high-resolution image is embedded in an HTML file, –Only a bounding box (fake/virtual image) is drawn first, and coordinated with surrounding text. »because most users are not patient enough to keep watching blank browser windows until both text and image are downloaded. –Whenever the image is downloaded, the bounding box is replaced with the real image. –The image is gradually drawn from a lower to higher resolutions.
2 > Image ImageProxy ImageImpl draw() getExtent() ImageProxy() draw() drawBBox() getExtent() fetchImage() image 1 Browser extent draw() getExtent() extent
3 > Image ImageProxy ImageImpl draw() getExtent() ImageProxy() draw() drawBBox() getExtent() fetchImage() image 1 Browser extent draw() getExtent() extent Obtained from a HTML file (width=“100” height=“50”) Or, the default extent used. if( image == null){ drawBBox( getExtent() ); } else { image.draw(); } if( image == null){ return extent; } else { image.getExtent(); } Image img = new ImageProxy(…); img.draw(); Create a thread, and using the thread, start downloading a target image from a remote web site. Once it is done, instantiate Image and call draw() fetchImage(…);
4 Iterator Design Pattern Intent –Provides a uniform way to access/traverse the elements of an aggregate object (e.g., collection object) sequentially without exposing its underlying representation (data structure). A “uniform” access/traversal way for different types of aggregate objects –Abstract access mechanisms for collection types, and encapsulate that in the iterator. Separate collections from access mechanisms (i.e., how to access collections) Hide access mechanisms from collection users.
5 An Example in Java Collection collection = ….; java.util.Iterator iterator = collection.iterator(); while ( iterator.hasNext() ) { Object o = iterator.next(); System.out.print( o ); } –Different access mechanisms must be implemented for different collection types (e.g., list, bag, tree and table). –Collection users can use the the same/uniform way to access different collection types. There are so many collection types in Java.
6 Class Structure Client (or user) 《 interface 》 Iterator 《 interface 》 Collection LinkedListVectorListIteratorVectorIterator <-- createuse --> Users knows these two interfaces. Users do not have to know this level. This level is hidden from users. hasNext next() iterator() add() remove() …
7 What’s Hidden from Users? Client (or user) 《 interface 》 Iterator 《 interface 》 Collection LinkedListVectorListIteratorVectorIterator hasNext next() iterator() add() remove() … iterator() … return new VectorIterator(this); VectorIterator(Vector vec) hasNext() -vector 1 this.vector = vec; this.index = 0; this.size = vec.size(); if( size == index ) return false; return true; return vec.get( index ); index: int Size: int
8 Key Points User's point view –java.util.Iterator iterator = collection. iterator() ; –Iterator instances always implement the Iterator interface. –No need to know what specific implementation class is returned/used. In fact, VectorIterator does not exist in Java API. The API documentation provides no information about implementation classes. Simple contract: get an interator with iterator() and call next() on that –No need to change user code when implementation classes are changed. –Important Principle: Program to an interface, not an implementation
9 Collection developer’s point view –No need to change existing implementation classes (collection access mechanisms) when a new collection type is introduced. –Iterator and its implementation classes form the Strategy pattern. –iterator() is a factory method.
10 Factory Method a.k.a. –Virtual constructor A normal method that creates instances. Intent –Let a class (or interface) defer instantiation of subclasses (or implementation classes). At compile time, users do not need to determine and write what subclasses (impl classes) to instantiate. The decision can be deferred to runtime. –Separate class instantiation from users, and encapsulate that in a factory method. Hide instantiation from users of subclasses (impl classes)
11 Client (or user) 《 interface 》 Iterator 《 interface 》 Collection LinkedListVectorListIteratorVectorIterator hasNext next() iterator() iterator() add() remove() … iterator() … return new VectorIterator(this); VectorIterator(Vector vec) hasNext() -vector 1 this.vector = vec; this.index = 0; this.size = vec.size(); if( size == index ) return false; return vec.get( index ); index: int An Example: Iterator
12 Another Example: Proxy
13 Recap: Proxy Design Pattern > Image ImageProxy ImageImpl draw() getExtent() ImageProxy() draw() drawBBox() getExtent() fetchImage() image 1 Browser extent draw() getExtent() extent Obtained from a HTML file (width=“100” height=“50”) Or, the default extent used. if( image == null){ drawBBox( getExtent() ); } else { image.draw(); } if( image == null){ return extent; } else { image.getExtent(); } Image img = new ImageProxy(…); img.draw(); Create a thread, and using the thread, start downloading a target image from a remote web site. Once it is done, instantiate Image and call draw() fetchImage(…);
14 > Image > ImageProxy > AbstractImageImpl draw() getExtent() ImageProxy() draw() drawBBox() getExtent() fetchImage() image 1 Browser draw() getExtent() Factory Method in Proxy JpegImgProxySvgImgProxy JpegImageSvgImage
15 List imgList = htmlFile.getImages(); for each img of imgList { img.draw(); } > Image > ImageProxy > AbstractImageImpl draw() getExtent() ImageProxy() draw() drawBBox() getExtent() fetchImage() image 1 Browser draw() getExtent() JpegImgProxySvgImgProxy JpegImageSvgImage Factory method for impl classes of AbstractImageImpl
16 Other Examples Object pool –Connection pool –Thread pool Singleton
17 Singleton Design Pattern Guarantee that a class has only one instance. –public class Singleton{ private static Singleton instance = null; private Singleton(){} public static synchronized Singleton getInstance() { if( instance==null){ instance = new Singleton(); } return instance; } }
18Examples Object pools Cache
19 Colleague Colleague1Colleague2 Mediator mediator ConcreteMediator Mediator Design Pattern Intent –Define a class that encapsulates how a set of objects interact. –Control the interaction in a centralized (single) place –Promote loose-coupling among objects 1
20 OrderProcParticipant Faculty Mediator mediator OrderProcMediator 1 initOrderProc(f: OrderProcParticipant) getStatus(): OrderProcStatus OrderAccount orderInitiatororderaccount
21 OrderProcParticipant Faculty Mediator mediator OrderProcMediator 1 initOrderProc(f: OrderProcParticipant) initOrderProc(f: OrderProcParticipant, o: Order, a: Accout) getStatus(): OrderProcStatus OrderAccount orderInitiatororderaccount If( f’s type is not Faculty) throw an exception; orderInitiator = f; order = o; account = a; f is the owner of a? order.getItem().getCost() < account.balance()? status = OrderProcStatus.AUTHORIZED returns status; What if a more complicated business Process is implemented? Purchaser, supervisor, auditor, etc. etc.
22 IMParticipant PremiumUserRegularUser Mediator mediator ConfCallMediator 1 showMsg(msg: String) register(p: IMParticipant) sendMsg(msg: String) showAd(ad: Ad) pUsers rUsers register(p: IMParticipant) sendMsg(msg: String)
23 IMParticipant PremiumUserRegularUser Mediator mediator ConfCallMediator 1 showMsg(msg: String) register(p: IMParticipant) sendMsg(msg: String) showAd(ad: Ad) pUsers rUsers register(p: IMParticipant) sendMsg(msg: String) if( p’s type is PremiumUser ){ pUsers.add(p); p.log(); } if( p’s type is RegularUser) rUser.add(p); for each of pUsers { each.showMsg( msg ); } for each of rUsers { each.showAd( new Ad(…) ); each.showMsg( msg ); } The Strategy pattern used. What if new user types are added?
24 Code Reuse in OOP Three categories of code reuse –Inherit an existing class SSLServerSocket extends ServerSocket –Instantiate an existing class new Thread(new YourOwnRunnable() ) –Combine instances at runtime Decorator design pattern
25 When is Instance Combination Useful? class VisualString{ private String string; public void draw(){ // draw a string on the screen } } You want to draw a box around the string. –class BoxedString extends VisualString{ public void draw(){ // redefine how to draw a string } } You want to draw a string in color. –Class ColoredString extends VisualString{ public void draw(){ // redefine how to draw a string } } What if you want to draw a box around a colored string? What if you want to draw a box around an icon?
26 class Customer{ public double getAnnualFee(){ … } } class DomesticCustomer extends Customer{ public double getAnnualFee(){ … } } class InternationalCustomer extends Customer{ public double getAnnualFee(){ … } } What if you want to set up –domestic/international cooperate, individual and government customers –VIP discount rate employee discount rate? What if you want to change the status of a customer from non-VIP to VIP or domestic to international?
27 Decorator Design Pattern a.k.a. pluggable objects Customer CorporateDomestic Customer individualIntlVIP
28 Sample Code: Structure of Classes <<interface>>Entity getAnnualFee() Customer getAnnualFee() EntityDecorator{abstract} getAnnualFee() entity DomesticDecoratorIntlDecorator getAnnualFee() IndividualDecoratorCorporateDecorator getAnnualFee() VIPDecorator getAnnualFee() GovDecorator getAnnualFee()
29 Sample Code: Instance Combination Customer customer = new Customer(); customer.getAnnualFee(); --> Customer customer = new DomesticDecorator( new CorporateDecorator( new Customer() ) ); customer.getAnnualFee(); --> –The kernel + 2 skins (decorators) Customer CorporateDomestic Customer main() getAnnualFee() *
30 new InternationalDecorator( new GovernmentDecorator( new Customer() ) ); new VIPDecorator( new IndividualDecorator( new Customer() ) ); Customer GovIntl main() getAnnualFee() * * Customer IndividualVIP main() getAnnualFee() *0 0
31 Java I/O API InputStream and OutputStream –Abstract classes that represent input and output byte streams. Reader and Writer –Abstract classes to read and write character streams Many filters are defined to tailor specialized input/output streams and readers/writers. InputStream Filters ObjectsAudioFile Chars, etc. Filters Reader Byte steam Char steam Filters Writer OutputStream Filters CharactersCharacters ObjectsAudioFile Chars, etc.
32InputStream InputStream objects can be decorated with an arbitrary number of filters. InputStream classes –AudioInputStream –FileInputStream –ObjectInputStream –PipedInputStream –…etc. –SocketInputStream (hidden) FileInputStream InputStream Filters Files InputStream{abstract} read() close() FilterInputStream filters InputStreamclasses in AudioInputStream Audio ObjectInputStream Objects SocketInputStream Data from socket
33 Initialization of InputStream InputStream is = new FileInputStream(“foo.txt); InputStream is = new FileInputStream( System.in); fis.read(); Socket socket = new Socket(…); InputStream is = socket.getInputStream(); is.read(); –System.out.println(socket.getInputStream().toString() ); FileInputStream InputStream Filters Files SocketInputStream Data from socket
34 Some InputStream objects can be connected with each other. InputStream is = new AudioInputStream( new FileInputStream( “audiofile”) ); InputStream is = new AudioInputStream( socket.getInputSteam() ); InputStream is = new ObjectInputStream( new FileInputStream( “objectfile”) ); AudioInputStream Audio FileInputStream AudioInputStream Audio SocketInputStream ObjectInputStream Object FileInputStream
35 Filters of InputStream Filters –BufferedInputStream –CheckedInputStream (java.util.zip) –ZipInputStream (java.util.zip) –GZIPInputStream (java.util.zip) –JarInputStream (java.util.zip) –CipherInputStream (javax.crypto) –DifestInputStream (java.security) –…etc. A single InputStream object can be decorated with multiple filters. InputStream{abstract} read() close() FilterInputStream filters InputStreamclasses in FileInputStream InputStream Filters Files AudioInputStream Audio ObjectInputStream Objects SocketInputStream Data from socket
36 InputStream is = new Buffered( socket.getInputStream() ); is.read(); InputStream in = new ZipInputStream ( new FileInputStream(…) ); in.read(); InputStream in = new BufferredInputStream( new ZipInputStream( socket.getInputStream() )); in.read();
37OutputStream OutputStream objects can be decorated with an arbitrary number of filters. OutputStream classes –FileOutputStream –ObjectOutputStream –PipedOutputStream –…etc. –SocketOutputStream (hidden) OutputStream{abstract} write() close() FilterOutputStream filters OutputStreamclasses FileOutputStream OutputStream Filters Files ObjectOutputStream Objects SocketOutputStream Data from socket out
38 Initialization of OutputStream OutputStream os = new FileOutputStream(“foo.txt); OutputStream os = new FileOutputStream( System.in); fis.read(); Socket socket = new Socket(…); OutputStream os = socket.getOutputStream(); is.read(); –System.out.println(socket.getOutputStream().toString() ); FileOutputStream InputStream Filters Files SocketOutputStream Data from socket
39 Some OutputStream objects can be connected with each other. OutputStream os = new ObjectOutputStream( new FileOutputStream( “objectfile”) ); ObjectInputStream Object FileInputStream
40 Filters of OutputStream Filters –BufferedOutputStream –PrintStream –CheckedOutputStream (java.util.zip) –ZipOutputStream (java.util.zip) –GZIPOutputStream (java.util.zip) –JarOutputStream (java.util.zip) –CipherOutputStream (javax.crypto) –DifestOutputStream (java.security) –…etc. A single OutputStream object can be decorated with multiple filters. OutputStream{abstract} write() close() FilterOutputStream filters OutputStreamclasses out
41 OutputStream os = new ZipOutputStream( new FileOutputStream(…) ); os.write(); OutputStream os = new BufferredOutputStream( new ZipOutputStream( socket.getOutputStream() )); os.write(); OutputStream os = new PrintStream( socket.getOutputStream() ); os.write();
42 Readers, Writers and Utility Classes PrintWriter Scanner –A text scanner that can parse primitive types and strings using regular expressions. FileReader –Convenience class for reading character files. FileWriter –Convenience class for writing character files.