What is Proxy Design Pattern?

Provide a surrogate or placeholder for another object. This Place holder object provides some advantages, few are as below.

#1. to Access Remote Object.
#2. to control access of few methods of original object.
#3. it may be costly(consumes more memory or time) to use original object.
…and many more.

Below is an example, of using place holder object of VideoProxy instead of original Video object.

As shown in example below, object of Video class loads video file, even to display thumb nail. As known it consumes more memory to load multiple video thumb nails, in a single screen.

To keep memory consumption minimal, ProxyVideo has been implemented, which displays an Image to display thumb nail. And the video file is loaded, only when user want to play the video, that too only the specific video file which the user opted to view, will be loaded to play.

public interface IVideo {
   void displayThumbnail();
   void playVideo();
}

public class Video implements Image {

   private String fileName;

   public Video(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void displayThumbnail() {
      loadVideoFromStorage();
      System.out.println("Displaying Thumbnail of " + fileName);
   }

   private void loadVideoFromStorage(){
      System.out.println("Loading actual video... " + fileName);
   }

   @override
   public void playVideo()
   {
      loadVideoFromStorage();
   }
}

public class ProxyVideo implements IVideo{

   private Video objVideo;
   private String fileName;

   public Video(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void displayThumbnail() {
      String thumbnail_name = fileName+"_thumbnail.jpg";
      System.out.println("Display Thumbnail Image..."+thumbnail_name);
   }

   @Override
   public void playVideo() {
      objVideo = new Video(fileName);
      objVideo.playVideo();
   }
}

In this example, Aggregation is used(Read more on Composition and Aggregation), instead inheritance can be used here.

Difference between Proxy and Adapter Pattern

Adapter Pattern is to change the interface of class A to the expectations of another class B. The typical implementation is a wrapper class or set of classes.

Proxy Pattern is similar, but the purpose is different. The purpose of the proxy pattern is to create a stand-in for a real resource. As already briefed, this stand-in is required as the actual object is remotely located or it is expensive to create actual object or you want to give controlled access to methods of actual class, etc…

You may also like to read:
What is Factory Design Pattern
How to implement Singleton Design Pattern
Can Adapter Pattern use Composition
Adapter Pattern using Inheritance

Difference between Composition and Aggregation

In Object oriented languages, Composition, Aggregation and Inheritance are the most common relationships exist between classes.

Composition in Java

Composition is has-a relationship. Also sometimes referred as non-separable part of the whole.
Composition is more stronger relationship compared to Aggregation. Here composed object cannot exist without composing object, and both objects have same life time.

As shown in below code snippet, object of B(i..e obj) cannot exist without object of B. Object of B gets created only along with object of A. Also obj1 does not continue to exist, after object of A gets destroyed.

class A{
B obj;
//… other data members and methods, of class A
}

Aggregation

Aggregation is also a has-a relationship. Also sometimes referred as separable part to whole.
Aggregation is a weaker relationship compared to Composition.
As shown in below code snippet, object of D(i..e obj1) can exist even before object of C gets created. Also obj1 may continue to exist even after object of C is destroyed.

class C{
D obj1;
//… other data members and methods, of class C
}
Composition is Strong Has-A relationship Aggregation is a Weak Has-A relationship.

To understand difference between Composition and Aggregation, lets us take an example of a College with few Departments, and each Department with Lecturers.

aggregation and composition
aggregation and composition

Relationship between College and Department is Composition, and relationship between Department and Lecturer is Aggregation.

class College
{
  private List depts;

  public College()
  {
    depts.add(new Department("Computer Dept"));
    depts.add(new Department("Electrical Dept"));
    depts.add(new Department("Electronics Dept"));
  }

  //...other methods in College class
}

A Department cannot exist without College, hence difference between them is Strong and hence Composition.
When College no more exist, Department cannot exist.

Relationship between Department and Lecturer can be Aggregation, as it is weaker. A Lecturer can exist, even before Department exist. And Lecturer may continue to exist even after Department gets destroyed.

class Department
{
  private Lecturer my_obj;

  public void setLecturer(Lecturer lect)
  {
    my_obj = lect;
  }
  //...other methods in Department class
}

Adapter Pattern with Composition

Adapter pattern makes two incompatible interfaces to work together. These Incompatible interfaces are not designed and developed for one another, and assuming they have evolved separately.

Adapter Pattern can be implemented using any of the below.

  1. Inheritance
  2. Composition

Implementing Adapter pattern with Composition

In below example NewArithmetic and Arithmetic are classes, which are incompatible. And they have been designed separately, and one is not designed for another.

Now ArithmeticAdapter is implemented to make NewArithmetic and Arithmetic classes, compatible with each other.

Here ArithmeticAdapter contains Adaptee, i..e NewArithmetic

public class NewArithmetic
{
    public float add_values(float val1, float val2)
    {
        return val1+val2;
    }

    public float sub_values(float val1, float val2)
    {
        return val1-val2;
    }
}

public class ArithmeticAdapter{
    private NewArithmetic obj;

    public ArithmeticAdapter()
    {
        obj = new NewArithmetic();
    }

    public int add_adptr(int val1, int val2)
    {
        return (int)obj.add_values(val1,val2);
    }

    public int sub_adptr(float val1, float val2)
    {
        return (int)obj.sub_values(val1,val2);
    }
}

public class Arithmetic
{
    public void add(int val1,int val2)
    {
        System.out.println("Added Result:"+new ArithmeticAdapter().add_adptr(val1, val2));
    }

    public void sub(int val1,int val2)
    {
        System.out.println("Subtraction Result:"+new ArithmeticAdapter().sub_adptr(val1, val2));
    }
}

public class AdapterComposition {
    public static void main(String[] args) {
        Arithmetic obj = new Arithmetic();

        obj.add(23, 42);
        obj.sub(46, 21);
    }

}

Output:
Added Result:65
Subtraction Result:25

You may also like to read: Adapter Pattern with Inheritance

Adapter Pattern with Inheritance

Adapter pattern makes two incompatible interfaces to work together. These Incompatible interfaces are not designed and developed for one another, and assuming they have evolved separately.

Adapter Pattern can be implemented using any of the below.

  1. Inheritance
  2. Composition

Implementing Adapter pattern with Inheritance

In below example NewArithmetic and Arithmetic are classes, which are incompatible. And they have been designed separately, and one is not designed for another.

Now ArithmeticAdapter is implemented to make NewArithmetic and Arithmetic classes, compatible with each other.

Here ArithmeticAdapter inherits from Adaptee, i..e NewArithmetic

public class NewArithmetic
{
    public float add_values(float val1, float val2)
    {
        return val1+val2;
    }

    public float sub_values(float val1, float val2)
    {
        return val1-val2;
    }
}

public class ArithmeticAdapter extends NewArithmetic{
    public int add_adptr(int val1, int val2)
    {
        return (int)add_values(val1,val2);
    }

    public int sub_adptr(float val1, float val2)
    {
        return (int)sub_values(val1,val2);
    }
}

public class Arithmetic
{
    public void add(int val1,int val2)
    {
        System.out.println("Added Result:"+new ArithmeticAdapter().add_adptr(val1, val2));
    }

    public void sub(int val1,int val2)
    {
        System.out.println("Subtraction Result:"+new ArithmeticAdapter().sub_adptr(val1, val2));
    }
}

public class AdapterPattern {
    public static void main(String[] args) {
        Arithmetic obj = new Arithmetic();

        obj.add(23, 42);
        obj.sub(46, 21);
    }

}

Output:
Added Result:65
Subtraction Result:25

You may also like to read: Adapter Pattern with Composition