The proxy pattern

The second pattern that we will talk about in this chapter is the proxy pattern. It is often used for security or optimization purposes.

Roles

The objective of the proxy pattern is to substitute an object (the subject) with another one that will control its access. The object that substitutes the subject shares the same interface, so it is transparent from the consumer's perspective. The proxy is often a small (public) object that stands in for a more complex (private) object that is activated once certain circumstances are clear. The proxy adds a level of indirection by accepting requests from a client object and passing them to the real subject as necessary.

The proxy pattern is used in object-oriented programming. There are several types of proxies, which are as follows:

  • A virtual proxy: This allows you to create a "big" object at the appropriate time (used when the creation process is slow)
  • A remote proxy: This allows you to access an object that is available on another environment (such as on a multiplayer game server)
  • An authentication proxy: This check whether the access permission for a request is correct or not

Design

The following class diagram is quite simple; we have an interface that defines our subject, both the proxy and RealSubject implement this interface.

The client will call the proxy, not the RealSubject object himself. The proxy contains a reference to the RealSubject object. When the proxy receives a request, it can analyze it, and if the request is considered to be valid, it can be rerouted to the RealSubject.request() method. The proxy can decide when to create, or not, the RealSubject object avoiding to have to manage too big object in memory if useless. The following figure represent the generic class diagram of the proxy pattern:

Design

Participants

There are only three participants in this pattern:

  • ISubject: This is the common interface of the Proxy and RealSubject object
  • RealSubject: This is the object that is controlled and manipulated by the proxy.
  • Proxy: This is the object that substitutes RealSubject. It has the same interface of the RealSubject object (the ISubject interface). It creates, controls, enhances, and authenticates access to a RealSubject object.

Collaboration

The proxy receives the incoming request from a client instead of the RealSubject. If necessary, the message is then delegated to the RealSubject object. In this case, prior to the delegation, the proxy creates the RealSubject object if it has not already been done.

Illustration

We are developing a new software; this software presents a video catalog in a list. For each video in the list, we have a placeholder for the video and a description. The placeholder of the video first displays a screenshot of the video. If we click on this image, the video will be launched.

The video catalog contains videos, so it will be too heavy to have all of these videos in memory and transferring them through the network will take too long. The proxy pattern will help us organize all of this. We will create the subject only when we will need it, once the screenshot is clicked.

The two advantages are as follows:

  • The list is loaded quickly, mainly if it is downloaded from the network
  • Only videos that we want to watch are created, loaded, and played

The Screenshot class that represents the video is called the proxy of the Video subject. The proxy substitutes the Video subject for the display. The Screenshot class implements the same interface as the Video subject (the RealSubject object).

In our example, the proxy pattern design is as follows:

Illustration

When the proxy receives the display() message, it will display the video if this one already exists. If it receives the click() message, it will first create the Video subject and then load the video.

Implementation

We will first define the interface that will be used by our proxy and real subject.

When we simulate the real behavior of these methods with Playground, these methods return a string, telling us what the code is expected to do. We can ensure what we are coding is correct by checking the message returned by Playground.

The interface will have only two methods: click() and display():

protocol IAnimation{
  func display() -> String
  func click() -> String
}

The RealSubject object is represented here with the video class. We implement the interface and display the message according to the action:

class Video:IAnimation{
  func click() -> String{
    return ""
  }
  
  func display()->String{
    return "Display the video"
  }
  
  func load()->String{
    return "Loading the video"
  }
  
  func play()->String{
    return "Playing the video"
  }
}

The proxy now implements the same interface as the RealSubject object: the IAnimation interface but has the intelligence to create the RealSubject object, here the video object, when needed in the click method:

class ScreenShot:IAnimation{
  var video:Video?
  
  func click() -> String {
    if let video = video {
      return video.play()
    } else {
      video = Video()
      return video!.load()
    }
  }
  
  func display() -> String {
    if let video = video {
      return video.display()
    } else {
      return "Display the screenshot of the video"
    }
  }
}

Usage

The cool part is to simulate the client.

We first create a new proxy, Screenshot, and then we simulate the operation. We call display from the proxy. As the video is not created or loaded, it is the screenshot that will be displayed.

Then, we simulate a click. We can see that when we call the click method, the video gets loaded. As the video is created and loaded, we call the display method, which informs us that the video is now playing (instead of the screenshot of the video):

var animation = ScreenShot()
animation.display()
animation.click()
animation.display()

The result in Playground is as follows:

Usage

Note

Use the proxy pattern when you have objects, which are as follows:

  • Expensive to create
  • Need access control
  • Access remote sites
  • Need to perform some actions whenever they are accessed

Also, use the proxy pattern when you want to:

  • Create objects only when their operations are requested
  • Perform checks or housekeeping on objects whenever accessed
  • Have a local object that will refer to a remote object
  • Implement access rights on objects when their operations are requested
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset