DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Double-Checked Locking Design Pattern in Java
  • Deadlock-Free Synchronization in Java
  • Mastering Thread-Local Variables in Java: Explanation and Issues
  • Unlocking Performance: Exploring Java 21 Virtual Threads [Video]

Trending

  • Transforming AI-Driven Data Analytics with DeepSeek: A New Era of Intelligent Insights
  • Kubeflow: Driving Scalable and Intelligent Machine Learning Systems
  • Performing and Managing Incremental Backups Using pg_basebackup in PostgreSQL 17
  • AI-Based Threat Detection in Cloud Security
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Using Proxy Design Pattern In Java

Using Proxy Design Pattern In Java

Today, I will discuss another structural design pattern - Proxy Design Pattern. Proxy means an object functioning as another object.

By 
Brijesh Saxena user avatar
Brijesh Saxena
DZone Core CORE ·
Oct. 20, 20 · Tutorial
Likes (13)
Comment
Save
Tweet
Share
12.4K Views

Join the DZone community and get the full member experience.

Join For Free

Today, I will discuss another structural design pattern - Proxy Design Pattern. Proxy means an object functioning as another object.

Proxy Design Pattern

  • The Proxy Design Pattern is a Structural Design Pattern and one of the Gang of Four design patterns. 
  • The Proxy Design Pattern gives a way to create a class that represents the functionality of another class.
  • The Proxy could interface to anything; a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.
  • The Proxy is like a wrapper object that is being called by the client to access the real serving object behind the scenes.
  • The Proxy object hides the original object and control access to it. 
  • The Proxy is used when we may like to create a class that can perform as an interface to something else.
  • The Proxy pattern allows us to create objects having an original object to interface their functionality to the client application. 
  • The Proxy is most commonly used in the implementation of the lazy loading of objects. I mean creating proxy objects in place of full real objects until it is actually needed.
  • The Proxy can also be used to add an additional layer of security around the real object. 
  • The Proxy hides the Real object by providing a virtual and customized implementation.
  • We can do proxy in many ways like:
    • Virtual Proxy - Do lazy loading of memory rich or heavy objects until it is needed.
    • Decorative Proxy - Add extra functionality to the existing objects just like we do in Decorator Design Pattern. 
    • Protective Proxy - Control access to the objects functionality.
    • Debugging Proxy - Add logs that may also be helpful in debugging.
    • Remote Proxy - provides a local representative for a remote object like stub objects in RMI/RPC or CORBA.
    • Smart Proxy - checking the lock on real object while updating, loading persistence object upon the first reference, managing real object reference, etc.
  • Client Application can use the proxy object similar to the real object because both implement the same interface.
  • Proxy Design Pattern uses three components to implement:
    • Subject - the interface which exposes the functionality.
    • Real Subject - the class implements the Subject and provides the concrete implementation of the interface. In this class, we hide behind the Proxy.
    • Proxy - the class implements the Subject so that it can substitute Real Subject objects. It maintains the reference of the Real Subject to the substituted Proxy object so that it can forward a request to the Real Subject whenever needed.


Let's take an example to understand the proxy.

Image Loading Application Using Proxy Design Pattern

Suppose we have an Image interface to load and operate images as below:

Java
 




x
17


 
1
package org.trishinfotech.proxy;
2

          
3
public interface Image {
4

          
5
    public void load();
6

          
7
    public void show();
8

          
9
    public void showSummary();
10

          
11
    public void resize();
12

          
13
    public void remove();
14

          
15
    public void close();
16
}
17

          


Now there is a concrete class named as RealImage to deal with local image files:

Java
 




xxxxxxxxxx
1
51


 
1
package org.trishinfotech.proxy;
2

          
3
public class RealImage implements Image {
4

          
5
    protected String fileNameWithPath;
6

          
7
    public RealImage(String fileNameWithPath) {
8
        this.fileNameWithPath = fileNameWithPath;
9
        load();
10
    }
11

          
12
    @Override
13
    public void load() {
14
        System.out.println("RealImage: Loading image: " + fileNameWithPath);
15
    }
16

          
17
    @Override
18
    public void show() {
19
        System.out.println("RealImage: Showing image: " + fileNameWithPath);
20
    }
21

          
22
    @Override
23
    public void showSummary() {
24
        System.out.println("RealImage: Showing Summary of image: " + fileNameWithPath);
25
    }
26

          
27
    @Override
28
    public void resize() {
29
        System.out.println("RealImage: Resizing image: " + fileNameWithPath);
30
    }
31

          
32
    @Override
33
    public void remove() {
34
        System.out.println("RealImage: Removing image: " + fileNameWithPath);
35
    }
36
    
37
    @Override
38
    public void close() {
39
        System.out.println("RealImage: Closing image: " + fileNameWithPath);
40
    }
41

          
42
    public String getFileNameWithPath() {
43
        return fileNameWithPath;
44
    }
45

          
46
    public void setFileNameWithPath(String fileNameWithPath) {
47
        this.fileNameWithPath = fileNameWithPath;
48
    }
49

          
50
}
51

          


As you can see that the class loads the image while we create the object (early loading).

Now there is another concrete class named as RemoteImage to deal with images stored in the shared drive on the network.

Java
 




xxxxxxxxxx
1
61


 
1
package org.trishinfotech.proxy;
2

          
3
public class RemoteImage implements Image {
4

          
5
    private String remoteHost;
6
    protected String fileNameWithPath;
7

          
8
    public RemoteImage(String remoteHost, String fileNameWithPath) {
9
        this.remoteHost = remoteHost;
10
        this.fileNameWithPath = fileNameWithPath;
11
        load();
12
    }
13

          
14
    @Override
15
    public void load() {
16
        System.out.printf("RemoteImage: Loading image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
17
    }
18

          
19
    @Override
20
    public void show() {
21
        System.out.printf("RemoteImage: Showing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
22
    }
23

          
24
    @Override
25
    public void showSummary() {
26
        System.out.printf("RemoteImage: Showing Summary of image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
27
    }
28

          
29
    @Override
30
    public void resize() {
31
        System.out.printf("RemoteImage: Resizing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
32
    }
33

          
34
    @Override
35
    public void remove() {
36
        System.out.printf("RemoteImage: Removing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
37
    }
38
    
39
    @Override
40
    public void close() {
41
        System.out.printf("RemoteImage: Closing image: 'smb:\\\\%s\\%s'.\n", remoteHost, fileNameWithPath);
42
    }
43

          
44
    public String getRemoteHost() {
45
        return remoteHost;
46
    }
47

          
48
    public void setRemoteHost(String remoteHost) {
49
        this.remoteHost = remoteHost;
50
    }
51

          
52
    public String getFileNameWithPath() {
53
        return fileNameWithPath;
54
    }
55

          
56
    public void setFileNameWithPath(String fileNameWithPath) {
57
        this.fileNameWithPath = fileNameWithPath;
58
    }
59

          
60
}
61

          


Please note that both class are sub-class of Image interface.

Now lets create a proxy class to address:

  • Lazy loading of image.
  • Adding security layer for resize and remove of the image.
  • Adding logs and error statements while dealing with images.

Since I have two concrete classes of Image interface, I am writing a common proxy class named ProxyImage to deal with both. We can write separate proxies as well. As I mentioned already, Proxy class we make sub-class of same interface or class. i.e. Image in this case.

Java
 




xxxxxxxxxx
1
99


 
1
package org.trishinfotech.proxy;
2

          
3
public class ProxyImage implements Image {
4

          
5
    protected String remoteHost;
6
    protected String fileNameWithPath;
7
    private Image image;
8
    protected boolean isAdmin;
9

          
10
    public ProxyImage(String fileNameWithPath, boolean isAdmin) {
11
        super();
12
        this.fileNameWithPath = fileNameWithPath;
13
        this.isAdmin = isAdmin;
14
    }
15

          
16
    public ProxyImage(String remoteHost, String fileNameWithPath, boolean isAdmin) {
17
        this(fileNameWithPath, isAdmin);
18
        this.remoteHost = remoteHost;
19
    }
20

          
21
    @Override
22
    public void load() {
23
        if (image == null) {
24
            if (remoteHost != null) {
25
                image = new RemoteImage(remoteHost, fileNameWithPath);
26
            } else {
27
                image = new RealImage(fileNameWithPath);
28
            }
29
        } else {
30
            System.err.printf("ImageProxy: Already loaded image: '%s'.\n", fileNameWithPath);
31
        }
32
    }
33

          
34
    @Override
35
    public void show() {
36
        load();
37
        image.show();
38
    }
39

          
40
    @Override
41
    public void showSummary() {
42
        System.err.printf("ImageProxy: Showing Summary of image: '%s'.\n", fileNameWithPath);
43
    }
44

          
45
    @Override
46
    public void resize() {
47
        if (isAdmin) {
48
            load();
49
            image.resize();
50
        } else {
51
            System.err.printf("ImageProxy: Only Admin can resize image: '%s'.\n", fileNameWithPath);
52
        }
53
    }
54

          
55
    @Override
56
    public void remove() {
57
        if (isAdmin) {
58
            load();
59
            image.resize();
60
        } else {
61
            System.err.printf("ImageProxy: Only Admin can remove image: '%s'.\n", fileNameWithPath);
62
        }
63
    }
64

          
65
    @Override
66
    public void close() {
67
        if (image != null) {
68
            image.close();
69
        } else {
70
            System.err.printf("ImageProxy: Already closed image: " + fileNameWithPath);
71
        }
72
    }
73

          
74
    public String getRemoteHost() {
75
        return remoteHost;
76
    }
77

          
78
    public void setRemoteHost(String remoteHost) {
79
        this.remoteHost = remoteHost;
80
    }
81

          
82
    public String getFileNameWithPath() {
83
        return fileNameWithPath;
84
    }
85

          
86
    public void setFileNameWithPath(String fileNameWithPath) {
87
        this.fileNameWithPath = fileNameWithPath;
88
    }
89

          
90
    public boolean isAdmin() {
91
        return isAdmin;
92
    }
93

          
94
    public void setAdmin(boolean isAdmin) {
95
        this.isAdmin = isAdmin;
96
    }
97

          
98
}
99

          


 Now lets write a Main class to execute and test our code:

Java
 




xxxxxxxxxx
1
45


 
1
package org.trishinfotech.proxy;
2

          
3
public class Main {
4

          
5
    public static void main(String[] args) {
6
        System.out.println("Using Real Image class...");
7
        Image image1 = new RealImage("ABC.jpg");
8
        image1.showSummary();
9
        image1.load();
10
        image1.show();
11
        image1.resize();
12
        image1.close();
13
        image1.remove();
14
        System.out.println("------------------------------------------------");
15
        System.out.println("Using Proxy Image class...");
16
        Image image2 = new ProxyImage("ABC.jpg", true);
17
        image2.showSummary();
18
        image2.load();
19
        image2.show();
20
        image2.resize();
21
        image2.close();
22
        image2.remove();
23
        System.out.println("------------------------------------------------");
24
        System.out.println("Using Remote Image class...");
25
        Image image3 = new RemoteImage("192.168.0.1", "ABC.jpg");
26
        image3.showSummary();
27
        image3.load();
28
        image3.show();
29
        image3.resize();
30
        image3.close();
31
        image3.remove();
32
        System.out.println("------------------------------------------------");
33
        System.out.println("Using Proxy Image class...");
34
        Image image4 = new ProxyImage("192.168.0.1", "ABC.jpg", false);
35
        image4.showSummary();
36
        image4.load();
37
        image4.show();
38
        image4.resize();
39
        image4.close();
40
        image4.remove();
41
        System.out.println("------------------------------------------------");
42
    }
43

          
44
}
45

          


 And below is the output of the program:

Java
 




xxxxxxxxxx
1
39


 
1
Using Real Image class...
2
RealImage: Loading image: ABC.jpg
3
RealImage: Showing Summary of image: ABC.jpg
4
RealImage: Loading image: ABC.jpg
5
RealImage: Showing image: ABC.jpg
6
RealImage: Resizing image: ABC.jpg
7
RealImage: Closing image: ABC.jpg
8
RealImage: Removing image: ABC.jpg
9
------------------------------------------------
10
Using Proxy Image class...
11
ImageProxy: Showing Summary of image: 'ABC.jpg'.
12
RealImage: Loading image: ABC.jpg
13
ImageProxy: Already loaded image: 'ABC.jpg'.
14
ImageProxy: Already loaded image: 'ABC.jpg'.
15
ImageProxy: Already loaded image: 'ABC.jpg'.
16
RealImage: Showing image: ABC.jpg
17
RealImage: Resizing image: ABC.jpg
18
RealImage: Closing image: ABC.jpg
19
RealImage: Resizing image: ABC.jpg
20
------------------------------------------------
21
Using Remote Image class...
22
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
23
RemoteImage: Showing Summary of image: 'smb:\\192.168.0.1\ABC.jpg'.
24
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
25
RemoteImage: Showing image: 'smb:\\192.168.0.1\ABC.jpg'.
26
RemoteImage: Resizing image: 'smb:\\192.168.0.1\ABC.jpg'.
27
RemoteImage: Closing image: 'smb:\\192.168.0.1\ABC.jpg'.
28
RemoteImage: Removing image: 'smb:\\192.168.0.1\ABC.jpg'.
29
------------------------------------------------
30
Using Proxy Image class...
31
ImageProxy: Showing Summary of image: 'ABC.jpg'.
32
RemoteImage: Loading image: 'smb:\\192.168.0.1\ABC.jpg'.
33
ImageProxy: Already loaded image: 'ABC.jpg'.
34
RemoteImage: Showing image: 'smb:\\192.168.0.1\ABC.jpg'.
35
ImageProxy: Only Admin can resize image: 'ABC.jpg'.
36
RemoteImage: Closing image: 'smb:\\192.168.0.1\ABC.jpg'.
37
ImageProxy: Only Admin can remove image: 'ABC.jpg'.
38
------------------------------------------------
39

          


The Source Code can be found here: Proxy-Design-Pattern-Sample-Code

I hope this tutorial demonstrates the use of the proxy design pattern.

Liked the article? Please don't forget to press that like button. Happy coding!

Need more articles, please visit my profile: Brijesh Saxena

Design Threading Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Double-Checked Locking Design Pattern in Java
  • Deadlock-Free Synchronization in Java
  • Mastering Thread-Local Variables in Java: Explanation and Issues
  • Unlocking Performance: Exploring Java 21 Virtual Threads [Video]

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!