design patterns in java chapter 11 proxy
Skip this Video
Download Presentation
Design Patterns in Java Chapter 11 Proxy

Loading in 2 Seconds...

play fullscreen
1 / 70

Design Patterns in Java Chapter 11 Proxy - PowerPoint PPT Presentation

  • Uploaded on

Design Patterns in Java Chapter 11 Proxy. Summary prepared by Kirk Scott. The Introduction Before the Introduction. The chapter on the Proxy design pattern in the book is not ideal It is broken into four different parts 1. An illustration of the design pattern for image loading

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

PowerPoint Slideshow about 'Design Patterns in Java Chapter 11 Proxy' - mareo

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
design patterns in java chapter 11 proxy

Design Patterns in JavaChapter 11Proxy

Summary prepared by Kirk Scott

the introduction before the introduction
The Introduction Before the Introduction
  • The chapter on the Proxy design pattern in the book is not ideal
  • It is broken into four different parts
  • 1. An illustration of the design pattern for image loading
  • After explaining the example, the book states that although it illustrates the pattern, the resulting design is not desirable
2. The book then refactors the bad design into something it considers better.
  • It refers to this design as being a proxy in spirit but not in structure
  • As a consequence, it’s not clear whether the second example should stick in your mind as an illustration of the concepts involved or whether the first example is better because it is structurally closer
3. The book then considers the use of what it calls remote proxies
  • Proxies can definitely be useful in this environment
  • However, writing code that is distributed on different hardware platforms is beyond the scope of this course
  • Therefore, this section of the chapter will only be covered in passing
4. The last section of the chapter concerns dynamic proxies
  • This is also a useful application area for the design pattern
  • However, it is not necessarily a frequently occurring application
  • Like the previous section, this will only be covered in passing
beginning of book material
Beginning of Book Material
  • Customary apportionment of responsibility in a design means that every class is responsible for implementing the code necessary to support its public interface (interface in the generic, non-Java sense)
  • As with the other responsibility patterns, the Proxy design pattern is used in cases where the customary treatment of responsibility isn’t appropriate or can be improved upon
The book outlines three examples where this might be the case:
  • 1. When the base object might take too long to load
  • 2. When the base object is on another computer
  • 3. When you would like to intercept method calls to a base object so that you can wrap the underlying call to that object with code of your own
In those cases a software design might include a proxy class
  • A proxy object stands in for a base object
  • Calls are made to the proxy
  • The proxy then forwards those calls to the base object
Book definition:
  • The intent of the Proxy pattern is to control access to an object by providing a surrogate, or placeholder, for it.
a classic example image proxies
A Classic Example: Image Proxies
  • A proxy is a substitute or stand-in for a base object
  • As such, it is desirable for it to have an interface that is nearly identical to the interface of the base object
  • The proxy works by receiving the calls and “judiciously” or selectively forwarding the requests to the underlying object
A classic use of proxies is to avoid the waiting time associated with loading images in applications
  • Suppose the application contains graphical elements which hold the images
  • A proxy for a graphical element could take the step of displaying a small, temporary image, while the real image is being loaded in the background
In other words, a load() call is issued to the proxy
  • The proxy loads a temporary image and calls load() on the base object in the background
  • The real load() may be set to run in a separate thread
  • The user sees the temporary image quickly and can proceed using the application
  • The loading time of the real image doesn’t affect response time
The book admits up front that the following shortcomings may apply to a proxy design:
  • The resulting design may be brittle or fragile
  • By this the authors mean that maintenance and modification may be difficult
  • This is a bad sign for the application of a design pattern
The difficulty arises directly from the fact that the proxy is supposed to duplicate the interface of the underlying object
  • If that interface includes lots of methods, you have two choices, which you’ve seen before
  • Implement them all: This requires lots of work
  • Implement only some of them: This means that the proxy can only handle a subset of calls that the base object can handle
The next overhead illustrates the idea of a graphical placeholder
  • Initially an application would present the “Absent” icon
  • After pressing the “Load” button, the “Loading…” icon would be displayed as a stand-in
  • In the background, the loading of the real image would be started
From the standpoint of mechanics, the book proposes displaying .jpeg images as icons that are inserted into labels
  • This is the basic syntax:
  • ImageIcon icon = new ImageIcon(“images/fest.jpg”);
  • JLabel label = new JLabel(icon);
The idea now is to give the JLabel a proxy instead of the real icon
  • Then
    • The application makes use of the label
    • The label calls the proxy
    • And the proxy calls the base image/icon object
  • The following sequence diagram illustrates the idea
Aside from problems that the book admits to with the example, there is another complication
  • In the previous descriptions, reference was made to “loading an image in the background”
  • The question is, what does this mean?
In this example it will mean having the proxy implement the Runnable interface so that the proxy can load the image in a separate thread
  • If you’ve had CS 320 before or have encountered threads in some other setting, this might be meaningful
  • If not, don’t worry
  • Although central to this example, it is not central to the structure and intent of the design pattern
The overall plan of action for the proxy example is this:
  • There is a Java class, ImageIcon, which is the graphical item which is displayed in a JLabel
  • The proxy, ImageIconProxy is a subclass of the ImageIcon class
The ImageIconProxy class has three instance variables for images
  • A static ImageIcon variable for the Absent icon
  • A static ImageIcon variable for the Loading icon
  • And a non-static ImageIcon variable for whichever ImageIcon is currently displayed
The ImageIconProxy class has an instance variable to hold the String path name of the real image to load
  • The ImageIconProxy class also has an instance variable that holds a reference to the frame of the application that is using it
The ImageIconProxy class overrides a few of the many methods in the ImageIconclass
  • In particular it has a load() method that triggers the loading of an image
  • Because it implements Runnable, it also has a run() method
  • See the UML diagram on the following overhead
When an instance of the ImageIconProxy class is constructed, it takes in the String path name of an actual image to be loaded
  • The load() method takes in a reference to a frame as a parameter
  • When called, the load() method switches the current image to “Loading”
  • It then repaints the frame
  • After that, it starts a new thread for loading the actual image
The run() method basically just does the loading of the actual image
  • The code for the ImageIconProxy follows
  • There are a few blanks in the code for the challenge that comes afterwards
import java.awt.*;
  • import javax.swing.*;
  • public class ImageIconProxy extends ImageIcon implements Runnable
  • {
  • static final ImageIcon ABSENT = new ImageIcon(ClassLoader.getSystemResource("images/absent.jpg"));
  • static final ImageIcon LOADING = new ImageIcon(ClassLoader.getSystemResource("images/loading.jpg"));
  • ImageIcon current = ABSENT;
  • protected String filename;
  • protected JFramecallbackFrame;
public ImageIconProxy(String filename)
  • {
  • super(ABSENT.getImage());
  • this.filename = filename;
  • }
  • public void load(JFramecallbackFrame)
  • {
  • this.callbackFrame = callbackFrame;
  • current = LOADING;
  • callbackFrame.repaint();
  • new Thread(this).start();
  • }
  • public void run()
  • {
  • current = new ImageIcon(ClassLoader.getSystemResource(filename));
  • callbackFrame.pack();
  • }
public intgetIconHeight()
  • {
  • // Challenge!
  • }
  • public intgetIconWidth()
  • {
  • // Challenge!
  • }
  • public synchronized void paintIcon(Component c, Graphics g, int x, int y)
  • {
  • // Challenge!
  • }
  • }
Challenge 11.1
  • An ImageIconProxy object accepts three image display calls that it must pass on to the current image. Write the code for getIconHeight(), getIconWidth(), and paintIcon() for the ImageIconProxy class.
Solution 11.1
  • One solutions is:
  • [See next overhead.]
public intgetIconHeight()
  • {
  • return current.getIconHeight();
  • }
  • public intgetIconWidth()
  • {
  • return current.getIconWidth();
  • }
  • public synchronized void paintIcon(Component c, Graphics g, int x, int y)
  • {
  • current.paintIcon(c, g, x, y);
  • }
  • }
Before moving on with the book’s discussion, I would simply like to illustrate exactly how their example of a proxy works structurally
  • The ImageIconProxy class has an instance variable which is a reference to an ImageIcon, the current image
  • The situation can be diagrammed as shown on the following overhead
Recall that the ImageIconProxy class is a subclass of the ImageIcon class
  • It also implements the Runnable interface
  • Combining the previous diagram with the diagram that the book gave of the inheritance and interface relationships gives the diagram on the following overhead
  • I don’t claim that this is a generic picture of the structure of a proxy
  • It is, however, a more complete picture of what the book has done to create this proxy class
Challenge 11.2
  • The ImageIconProxy class is not a well-designed, reusable component. Point out two problems with the design.
Solution 11.2
  • Problems with the design include the following:
  • 1. Forwarding only a subset of calls to an underlying ImageIcon object is dangerous.
  • The ImageIconProxy class inherits a dozen fields and at least 25 methods from the ImageIcon class.
To be a true proxy, the ImageIconProxy object needs to forward most or all of these calls.
  • Thorough forwarding would require many potentially erroneous methods, and this code would require maintenance as the ImageIcon class and its superclasses change over time.
  • [Note that when the authors say erroneous, what the apparently mean is that trying to completely duplicate the interface would be error prone.]
2. You might question whether the “Absent” image and the desired image are in the right places in the design.
  • It might make more sense to have the images passed in rather than making the class responsible for finding them.
  • [This seems like a relatively minor criticism. In their second, improved design the authors don’t really change this.]
In summary, the software design presented so far does include the Proxy design pattern
  • However, the design that results from using this pattern is apparently NOT so good
  • Whenever you apply a pattern, it’s not sufficient to justify its use on the grounds that it’s a pattern
Its use has to lead to a better design
  • That said, even though this design may be poor, it may also be the clearest illustration of the use of the Proxy design pattern that is presented in this chapter
image proxies reconsidered
Image Proxies Reconsidered
  • Preliminary comment mode on:
  • What the authors do next is quite simple
  • I’m not sure their explanation really makes it clear what’s happening because it’s so simple
  • To give a preview, what they do is stop trying to make a proxy
  • Instead, they solve their design problem with a subclass with no pretenses to being a proxy
The key point is this:
  • With a proxy, you are either committed to reproducing the whole interface
  • Or you decide to do a subset
  • With the subclass solution you rely on all of the inherited methods of the superclass
  • Plus you add a few selected methods needed for the application
The book now replaces the ImageIconProxy class with a LoadingImageIcon class which is a subclass of ImageIcon
  • The LoadingImageIcon class has two methods in it, load() and run()
  • The ImageIconProxy class had a few more methods in it, in particular paintIcon()
The key idea is that fundamentally the ImageIcon class contains an instance of the Image class
  • The ImageIcon class contains all the methods needed for manipulating the image
  • It is much cleaner to simply let the LoadingImageIcon class inherit and use these methods rather than trying to duplicate them
  • A UML diagram of the new solution is given on the following overhead
The code for the LoadImageIcon class follows
  • The basic idea behind load() and run() is similar to before
  • However, the code is simpler because it relies more directly on the ImageIcon class
  • There are a few blanks in the code for the challenge that comes afterwards
import javax.swing.ImageIcon;
  • import javax.swing.JFrame;
  • public class LoadingImageIcon extends ImageIcon implements Runnable
  • {
  • static final ImageIcon ABSENT = new ImageIcon(ClassLoader.getSystemResource("images/absent.jpg"));
  • static final ImageIcon LOADING = new ImageIcon(ClassLoader.getSystemResource("images/loading.jpg"));
  • protected String filename;
  • protected JFramecallbackFrame;
public LoadingImageIcon(String filename)
  • {
  • super(ABSENT.getImage());
  • this.filename = filename;
  • }
  • public void load(JFramecallbackFrame)
  • {
  • // Challenge!
  • }
  • public void run()
  • {
  • // Challenge!
  • }
  • }
Challenge 11.3
  • Fill in the code for load() and run() in LoadingImageIcon.
Solution 11.3
  • The load() method sets the image to Loading…, whereas the run() method, executing in a separate thread, loads the desired image:
  • [See next overhead.]
public void load(JFramecallbackFrame) {
  • this.callbackFrame = callbackFrame;
  • setImage(LOADING.getImage());
  • callbackFrame.repaint();
  • new Thread(this).start();
  • }
  • public void run() {
  • setImage(new ImageIcon(ClassLoader.getSystemResource(filename)).getImage());
  • callbackFrame.pack();
  • }
  • }
remote proxies
Remote Proxies
  • As stated at the beginning of this set of overheads, code running on remote machines is beyond the scope of this course
  • However, it is worth noting how the idea of a proxy might be useful
  • The proxy runs on the local machine and local code calls it
  • The proxy does what it can to satisfy the request locally while forwarding calls to the remote object
This model is useful because remote calls can be time-consuming and they use resources (network, computing) beyond the local machine
  • That is the extent to which this topic will be covered in this course
  • Figures 11.5, 11.6, and B.14 have been tipped in below for future reference, but they can be ignored
  • The next topic to be covered will be dynamic proxies
dynamic proxies
Dynamic Proxies
  • The full treatment of dynamic proxies, like remote proxies, is beyond the scope of this course
  • As presented in the book, dynamic proxies rely on Java reflection, which is a large and relatively complicated topic
You encountered the tip of the iceberg in CS 202 when you saw methods that were coded using calls like getClass() rather than hardcoding a class or using the instanceof operator to establish what class an object was an instance of
  • One way of limiting the number of methods a proxy has to implement is to have the proxy only apply to a given interface that a class implements
This is significant in the reflection context because, just as there is a method that returns the class an object belongs to, there are methods that will return the interfaces a class implements
  • In other words, it’s possible to dynamically find out what methods a class implements as a result of implementing a given interface
Although it is not useful to consider the full complexity of dynamic proxies, the intent of these proxies as explained by the authors is worth considering
  • The scenario is this:
  • Suppose you want to instrument code
  • This means that you would like to insert debugging or testing statements, for example, into the code
Rather than inserting those statements directly into a base class, you can write a proxy class
  • The methods of the proxy class would wrap calls to the corresponding methods in the base class
  • Keep in mind that you are not necessarily committed to doing this for all methods
  • In general, you will probably be doing testing on a class for some role it plays based on an interface it implements
  • Then it’s only necessary to have modified versions of the methods belonging to the interface
Both before and after the wrapped calls, any other code or calls could be inserted
  • The debugging or testing can be conducted on the proxy rather than messing up the base class
  • When doing this without the reflection machinery, it would involve a considerable amount of code duplication
  • If you master reflection, the process of creating and calling dynamic proxies can be largely automated
  • A proxy is a placeholder object that manages access to a target object
  • A proxy can insulate clients from various aspects of target object code, like the time taken to load a graphics object
  • A proxy can also wrap calls to the target’s methods, allowing the insertion of other code before and after
The Proxy design pattern is responsibility based
  • A proxy assumes responsibility for the target when the client makes a call
  • The very nature of the proxy leads to its weakness as a design pattern
  • The proxy is tightly coupled with the target
A choice has to be made between trying to implement the whole interface of the target and implementing only part
  • Implementing it all is a lot of work
  • Implementing part potentially means “gaps” in what can be done with the proxy
  • Either way, the proxy is heavily dependent on the target class and any changes made to it