Remote Proxy Pattern

Well, the time came for the third specialization I’m going to write about the proxy pattern, in this case is the remote proxy pattern.

It’s role is to provide the client the functionality to interact with an object that it might not be in the client machine, this proxy will inherit from the same interface than the remote object, but it wont have it’s own implementation, it will simply call the remote object. In short, it’s like the web services, when we make a web reference the wsdl file will be created, but it won’t be able to perform any concrete action, because the real object, is somewhere else.

The example will be like this, we will pretend to have a remote service, think about a WCF service, or even a web service, and we’re going to make our method calls to invoke the methods on the proxy, in fact, the proxy’s job is to stand between the real object and the client, not only this kind of proxy, but all. So we’re showing something to the client, but he doesn’t know that we’re calling the real object inside our proxy.

Here is the example, it’s by far the easiest and shortest one about this series of examples about the proxy design pattern.

Step 1: Add a service reference to our project, in this case I’m going to use a public web service, so we right-click our project and select ‘Add Service Reference…’ then we paste this url (http://soatest.parasoft.com/calculator.wsdl), and name our service ‘CalculatorService’.
Thanks to the Parasoft crew for publishing the service.

Step 2: We will code our main method

using System;

namespace Structural.Proxy.Remote
{
    class Program
    {
        static void Main(string[] args)
        {
            CalculatorService.ICalculator calculator = new CalculatorService.CalculatorClient();

            Console.WriteLine(calculator.add(7.3f,6.2f));

            Console.ReadKey();
        }
    }
}

It’s important to mention that we’re coding against a proxy, then the proxy will call the real service operation.

Hope it helps.

Best regards,
Esteban.

Authentication Proxy Pattern

Yet another variant of the proxy pattern, in this post I will cover the authentication proxy pattern which is used to check the access permissions for a request.

In this example I will show you how to implement this pattern in a banking-like application, it will have an account with three methods, get balance, deposit and withdraw, and the proxy will manage the authentication.

Step 1: The creation of our account interface (IAccount.cs)

using System;

namespace Structural.Proxy.Authentication.Base
{
    public interface IAccount
    {
        double GetBalance();
        double Withdraw(double amount);
        double Deposit(double amount);
    }
}

Step 2: Then we will create our account object (Account.cs) and it will acccess the data source.

using System;

using Structural.Proxy.Authentication.Base;

namespace Structural.Proxy.Authentication.Data
{
    public class Account : IAccount
    {
        int accountNumber;
        double accountBalance;

        public Account(int accountNumber)
        {
            this.accountNumber = accountNumber;

            //Pretend the account balance is coming from a data source
            accountBalance = 577.20;
        }

        public double GetBalance()
        {
            return accountBalance;
        }

        public double Withdraw(double amount)
        {
            if (accountBalance >= amount)
            {
                accountBalance -= amount;
                return accountBalance;
            }
            Console.WriteLine("Invalid amount for withdrawal.");
            return -1;
        }

        public double Deposit(double amount)
        {
            accountBalance += amount;
            return accountBalance;
        }
    }
}

Step 3: In this step we will create the account proxy object (AccountProxy.cs) this will stand between the client and the account itself.

using System;

using Structural.Proxy.Authentication.Base;
using Structural.Proxy.Authentication.Data;

namespace Structural.Proxy.Authentication.Proxy
{
    public class AccountProxy : IAccount
    {
        int accountNumber;
        string password;

        Account account;

        public AccountProxy(int accountNumber)
        {
            this.accountNumber = accountNumber;

            //Pretend the password is coming from a data source
            password = "secret";
        }

        public bool Authenticate(string password)
        {
            if (this.password == password)
            {
                account = new Account(accountNumber);
                Console.WriteLine("Authentication succeeded.");
                return true;
            }

            Console.WriteLine("Authentication failed.");
            return false;
        }

        public double GetBalance()
        {
            if (account != null)
                return account.GetBalance();
            else
            {
                Console.WriteLine("Authentication required.");
                return -2;
            }
        }

        public double Withdraw(double amount)
        {
            if (account != null)
                return account.Withdraw(amount);
            else
            {
                Console.WriteLine("Authentication required.");
                return -2;
            }
        }

        public double Deposit(double amount)
        {
            if (account != null)
                return account.Deposit(amount);
            else
            {
                Console.WriteLine("Authentication required.");
                return -2;
            }
        }
    }
}

Step 4: Now we code our main method like this.

using System;

using Structural.Proxy.Authentication.Proxy;

namespace Structural.Proxy.Authentication
{
    class Program
    {
        static void Main(string[] args)
        {
            AccountProxy accountProxy = new AccountProxy(123);

            Console.WriteLine(accountProxy.GetBalance());
            Console.WriteLine(accountProxy.Deposit(1));
            Console.WriteLine(accountProxy.Withdraw(1));

            accountProxy.Authenticate("444");

            accountProxy.Authenticate("secret");

            Console.WriteLine(accountProxy.Withdraw(15000));
            Console.WriteLine(accountProxy.GetBalance());
            Console.WriteLine(accountProxy.Deposit(500));
            Console.WriteLine(accountProxy.Withdraw(1000));

            Console.ReadKey();
        }
    }
}

Step 5: This is the output we receive.

Authentication required.
-2
Authentication required.
-2
Authentication required.
-2
Authentication failed.
Authentication succeeded.
Invalid amount for withdrawal.
-1
577.2
1077.2
77.2

Okay, that’s all for this proxy… I hope you find it useful.

Regards,
Esteban.

Virtual Proxy Pattern

As I said in an early post this is the first (of four) posts about the proxy design pattern, in this case I’m going to cover the virtual proxy.

Virtual Proxies
This kind of proxies are related to lazy loading, let’s suppose we have a photo album, which has photos – of course – in it, so we want to get the album without loading every picture, because if the album has thousands of pictures, we will filling up the memory with data we don’t need yet, so this is when we could implement a virtual proxy pattern.

In the following example, I have created a virtual proxy pattern which will load the pictures if needed when needed. The example goes like this.

Step 1: Create an interface for the photo object that will load the picture when needed (IPhoto.cs)

using System;

namespace Structural.Proxy.Virtual.Base
{
    public interface IPhoto
    {
        void Show();
    }
}

Step 2: We will need our real object, in our case, the photo object (Photo.cs)

using System;

using Structural.Proxy.Virtual.Base;

namespace Structural.Proxy.Virtual.Picture
{
    public class Photo : IPhoto
    {
        public string Name { get; private set; }

        public Photo(string name)
        {
            Name = name;
            Load();
        }

        public void Show()
        {
            Console.WriteLine("----> Displaying photo '{0}')", Name);
        }

        private void Load()
        {
            Console.WriteLine("------> Loading photo '{0}')", Name);
        }
    }
}

Step 3: Now we will create the proxy object (PhotoProxy.cs)

using System;

using Structural.Proxy.Virtual.Base;

namespace Structural.Proxy.Virtual.Picture
{
    public class PhotoProxy : IPhoto
    {
        IPhoto photo;

        public string Name { get; private set; }

        public PhotoProxy(string name)
        {
            Name = name;
        }

        public void Show()
        {
            Console.WriteLine("----> Displaying photo '{0}')", Name);
            if (photo == null)
            {
                photo = new Photo(Name);
            }
        }
    }
}

Step 4: Create our photo album (PhotoAlbum.cs) (How did you guess?)

using System;
using System.Collections.Generic;

using Structural.Proxy.Virtual.Base;

namespace Structural.Proxy.Virtual.Picture
{
    public class PhotoAlbum
    {
        List<IPhoto> photos;

        public string Name { get; private set; }

        public PhotoAlbum(string name)
        {
            Name = name;
            photos = new List<IPhoto>();
        }

        public void AddPhoto(IPhoto photo)
        {
            photos.Add(photo);
        }

        public void Slideshow()
        {
            Console.WriteLine("--> Starting '{0}' slideshow)", Name);
            foreach (IPhoto iPhoto in photos)
            {
                iPhoto.Show();
            }
            Console.WriteLine("--> Slideshow for '{0}' is finished)\n", Name);
        }
    }
}

Step 5: Now let’s create our fake data provider (DataProvider.cs)

using System;

using Structural.Proxy.Virtual.Picture;

namespace Structural.Proxy.Virtual.FakeProvider
{
    public static class DataProvider
    {
        public static PhotoAlbum GetData()
        {
            PhotoAlbum photoAlbum = new PhotoAlbum("Album 1");

            photoAlbum.AddPhoto(new Photo("Photo 1"));
            photoAlbum.AddPhoto(new Photo("Photo 2"));
            photoAlbum.AddPhoto(new Photo("Photo 3"));

            return photoAlbum;
        }

        public static PhotoAlbum GetProxyData()
        {
            PhotoAlbum photoAlbum = new PhotoAlbum("Album 2 (Proxy)");

            photoAlbum.AddPhoto(new PhotoProxy("Proxy Photo 1"));
            photoAlbum.AddPhoto(new PhotoProxy("Proxy Photo 2"));
            photoAlbum.AddPhoto(new PhotoProxy("Proxy Photo 3"));

            return photoAlbum;
        }
    }
}

Step 6: Finally we will implement our main method.

using System;
using System.Collections.Generic;

using Structural.Proxy.Virtual.FakeProvider;
using Structural.Proxy.Virtual.Picture;

namespace Structural.Proxy.Virtual
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("(Status: Step 1 - Getting data)\n");
            PhotoAlbum photoAlbum = DataProvider.GetData();
            PhotoAlbum photoAlbumProxy = DataProvider.GetProxyData();

            Console.WriteLine("\n(Status: Step 2 - Starting slideshows)\n");

            photoAlbum.Slideshow();
            photoAlbumProxy.Slideshow();

            Console.WriteLine("(Status: Finished)");

            Console.ReadKey();
        }
    }
}

Step 7: Press f5, and if you have time, sit back and watch the magic of the virtual proxy pattern.

(Status: Step 1 - Getting data)

------> Loading photo 'Photo 1')
------> Loading photo 'Photo 2')
------> Loading photo 'Photo 3')

(Status: Step 2 - Starting slideshows)

--> Starting 'Album 1' slideshow)
----> Displaying photo 'Photo 1')
----> Displaying photo 'Photo 2')
----> Displaying photo 'Photo 3')
--> Slideshow for 'Album 1' is finished)

--> Starting 'Album 2 (Proxy)' slideshow)
----> Displaying photo 'Proxy Photo 1')
------> Loading photo 'Proxy Photo 1')
----> Displaying photo 'Proxy Photo 2')
------> Loading photo 'Proxy Photo 2')
----> Displaying photo 'Proxy Photo 3')
------> Loading photo 'Proxy Photo 3')
--> Slideshow for 'Album 2 (Proxy)' is finished)

(Status: Finished)

Well that’s all as for the virtual proxy pattern, I really hope that this could help.

Rates and/or comments will be greatly appreciated ;)

Regards,
Esteban.

Follow

Get every new post delivered to your Inbox.