You are here:   ArielOrtiz.com > Software Design and Architecture > Lab 8: Proxy Pattern

Lab 8: Proxy Pattern

Objectives

During this lab session:

This activity helps the student develop the following skills, values and attitudes: ability to analyze and synthesize, capacity for identifying and solving problems, and efficient use of computer systems.

Activity Description

During this lab, you will write a Caching Proxy. It's based on chapter 11 of [FREEMAN]. It can be developed individually or in pairs.

Make a new folder called chapter11. Place all the files you create in this folder.

  1. You have the following generic interface definition for operations that have to be cached.

    namespace Headfirst.Proxy {
        
        public interface IOperation<ReturnType, ParamType> {
            ReturnType Compute(ParamType value);	
            bool IsInCache(ParamType value);
        }
    }

    Write the class Headfirst.Proxy.OperationProxy<ReturnType, ParamType>, which implements the above interface. Its constructor must receive the real object that this proxy represents. When its method Compute gets called, it must first check its private cache in order to determine if the result corresponding to a specific parameter has already been computed. If so, it simply returns the value in the cache, otherwise it calls the original operation (through delegation) and stores the result in the cache.

    The IsInCache method is just a convenience operation that allows our tests to verify if certain value is already contained in the cache.

  2. Make sure the code that you write behaves exactly as expected by the following unit tests:

    namespace Headfirst.Proxy {
        
        using System;
        using NUnit.Framework;
            
        public class FactorialOperation: IOperation<int, int> {
            
            public int Compute(int value) {
                int result = 1;
                for (int i = 2; i <= value; i++) {
                    result *= i;
                }
                return result;
            }
            
            public bool IsInCache(int value) {
                return false;
            }
        }
        
        public class FibonacciOperation: IOperation<int, int> {
    
            public int Compute(int value) {
                if (value <= 1) {
                    return 1;
                } else {
                    return Compute(value - 1) + Compute(value - 2);
                }
            }
    
            public bool IsInCache(int value) {
                return false;
            }
        }
        
        public class BinaryOperation: IOperation<string, uint> {
            
            public string Compute(uint value) {
                return Convert.ToString(value, 2);            
            }
    
            public bool IsInCache(uint value) {
                return false;
            }
        }
        
        [TestFixture]
        public class TestOperation {
                    
            [Test]
            public void TestFactorial() {
                var fact = new OperationProxy<int, int>(new FactorialOperation());
                
                Assert.IsFalse(fact.IsInCache(5));
                Assert.AreEqual(120, fact.Compute(5));
                Assert.IsTrue(fact.IsInCache(5));
                Assert.AreEqual(120, fact.Compute(5));
        
                Assert.IsFalse(fact.IsInCache(10));
                Assert.AreEqual(3628800, fact.Compute(10));
                Assert.IsTrue(fact.IsInCache(10));
                Assert.AreEqual(3628800, fact.Compute(10));
        
                Assert.IsFalse(fact.IsInCache(12));
                Assert.AreEqual(479001600, fact.Compute(12));
                Assert.IsTrue(fact.IsInCache(12));
                Assert.AreEqual(479001600, fact.Compute(12));
            }
            
            [Test]
            public void TestFibonacci() {
                var fibo = new OperationProxy<int, int>(new FibonacciOperation());
                
                Assert.IsFalse(fibo.IsInCache(5));
                Assert.AreEqual(8, fibo.Compute(5));
                Assert.IsTrue(fibo.IsInCache(5));
                Assert.AreEqual(8, fibo.Compute(5));
        
                Assert.IsFalse(fibo.IsInCache(10));
                Assert.AreEqual(89, fibo.Compute(10));
                Assert.IsTrue(fibo.IsInCache(10));
                Assert.AreEqual(89, fibo.Compute(10));
        
                Assert.IsFalse(fibo.IsInCache(40));
                Assert.AreEqual(165580141, fibo.Compute(40));
                Assert.IsTrue(fibo.IsInCache(40));
                Assert.AreEqual(165580141, fibo.Compute(40));
            }
            
            [Test]
            public void TestBinary() {
                var bin = new OperationProxy<string, uint>(new BinaryOperation());
                
                Assert.IsFalse(bin.IsInCache(0));
                Assert.AreEqual("0", bin.Compute(0));
                Assert.IsTrue(bin.IsInCache(0));
                Assert.AreEqual("0", bin.Compute(0));
                
                Assert.IsFalse(bin.IsInCache(123));
                Assert.AreEqual("1111011", bin.Compute(123));
                Assert.IsTrue(bin.IsInCache(123));
                Assert.AreEqual("1111011", bin.Compute(123));
                
                Assert.IsFalse(bin.IsInCache(2000));
                Assert.AreEqual("11111010000", bin.Compute(2000));
                Assert.IsTrue(bin.IsInCache(2000));    
                Assert.AreEqual("11111010000", bin.Compute(2000));
            }
        }
    }

Deliverables

To hand in your lab work, follow these instructions:

Evaluation

This activity will be evaluated using the following criteria:

100 The code works as requested.
60-90 The code works, but has some flaws.
20-50 The code doesn't work, but it seams that some amount of time was spent on it.
DA The program was plagiarized.
© 1996-2009 by Ariel Ortiz (ariel.ortiz@itesm.mx)
Made with Django | Licensed under Creative Commons | Valid XHTML | Valid CSS