Search code examples
design-patternsproxymediator

What is difference between proxy design pattern and mediator?


I'm learning design patterns from refactoring.guru. before mediator design pattern, i learned proxy design pattern. Now I am completely confused, what exactly is the difference between these two design patterns?


Solution

  • The goal of Mediator pattern is to remove coupling between two objects. These two objects should communicate only through some another object. Let's call this object as mediator.

    A real life example can be a guitar pick. Player use a guitar pick to play. Fingers of player does not touch guitar strings. Fingers just touch a guitar pick. In this example, we have three objects such as player, guitar and mediator between them is guitar pick.

    Let me show an example of code from wiki of Mediator pattern:

    public delegate void MessageReceivedEventHandler(string message, string sender);
    
    public class Mediator
    {
        public event MessageReceivedEventHandler MessageReceived;
    
        public void Send(string message, string sender)
        {
            if (MessageReceived != null)
            {
                Console.WriteLine("Sending '{0}' from {1}", message, sender);
                MessageReceived(message, sender);
            }
        }
    }
    

    and:

    public class Person
    {
        private Mediator _mediator;
    
        public string Name { get; set; }
    
        public Person(Mediator mediator, string name)
        {
            Name = name;
            _mediator = mediator;
            _mediator.MessageReceived += new MessageReceivedEventHandler(Receive);
        }
    
        private void Receive(string message, string sender)
        {
            if (sender != Name)
                Console.WriteLine("{0} received '{1}' from {2}", Name, message, sender);
        }
    
        public void Send(string message)
        {
            _mediator.Send(message, Name);
        }
    }
    

    Proxy

    The goal of Proxy pattern is:

    The intent of this pattern is to provide a Placeholder for an object to control references to it.

    Let me quote this beautiful words from the above link:

    Consider for example an image viewer program. An image viewer program must be able to list and display high resolution photo objects that are in a folder, but how often do someone open a folder and view all the images inside. Sometimes you will be looking for a particular photo, sometimes you will only want to see an image name. The image viewer must be able to list all photo objects, but the photo objects must not be loaded into memory until they are required to be rendered.

    And code of proxy wolud like this:

    /**  * Proxy     */
    public class ImageProxy implements Image {
    
        /**
         * Private Proxy data 
         */
        private String imageFilePath;
        
        /**
         * Reference to RealSubject
         */
        private Image proxifiedImage;
        
        
        public ImageProxy(String imageFilePath) {
            this.imageFilePath= imageFilePath;  
        }
        
        @Override
        public void showImage() {
    
            // create the Image Object only when the image is required to be shown
            
            proxifiedImage = new HighResolutionImage(imageFilePath);
            
            // now call showImage on realSubject
            proxifiedImage.showImage();         
        }
    }
    

    The code below displays the RealSubject Implementation, which is the concrete and heavyweight implementation of the image interface. The High resolution image, loads a high resolution image from disk, and renders it to screen when showImage() is called.

    /**  * RealSubject */
    public class HighResolutionImage implements Image {
    
        public HighResolutionImage(String imageFilePath) {
            
            loadImage(imageFilePath);
        }
    
        private void loadImage(String imageFilePath) {
    
            // load Image from disk into memory
            // this is heavy and costly operation
        }
    
        @Override
        public void showImage() {
    
            // Actual Image rendering logic
    
        }
    }