You are here:   ArielOrtiz.com > Software Design and Architecture > Lab 9: Prototype Pattern

Lab 9: Prototype 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

This lab can be developed individually or in pairs.

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

  1. Read section 5.1 of [BISHOP] in order to understand what the Prototype Pattern is, and how it can be correctly implemented using C#.
  2. You are given the following definition, which represents a Clone Trooper class from the Star Wars saga:

    namespace PrototypePattern {
        
        using System;
        using System.Collections;
        using System.Collections.Generic;
        
        [Serializable()]
        public class CloneTrooper: IEquatable<CloneTrooper>,
                IEnumerable<CloneTrooper> {
            
            List<CloneTrooper> list = new List<CloneTrooper>();
            public string Name { get; set; }
            
            public CloneTrooper(string name) {
                Name = name;
            }
            
            public override string ToString() {
                return Name;        
            }
            
            public override bool Equals(object other) {
                if (!(other is CloneTrooper)) {
                    return false;
                } 
                return Equals((CloneTrooper) other);
            }
            
            public bool Equals(CloneTrooper other) {
                return Name.Equals(other.Name);
            }
            
            public override int GetHashCode() {
                return Name.GetHashCode();
            }
            
            public void AddSubordinate(CloneTrooper cloneTrooper) {
                list.Add(cloneTrooper);                
            }
            
            public IEnumerator<CloneTrooper> GetEnumerator() {
                return list.GetEnumerator();
            }
            
            IEnumerator IEnumerable.GetEnumerator() {
                return GetEnumerator();
            }                
        }    
    }

    Modify the above code in whatever way you deem necessary so that the CloneTrooper class supports the Prototype design pattern via two methods: Clone and DeepClone.

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

    namespace PrototypePattern {
        using NUnit.Framework;
        
        [TestFixture]
        public class TestPrototype {
            
            CloneTrooper ct1, ct2, ct3, ct4;
                   
            [SetUp]
            public void Init() {
                ct1 = new CloneTrooper("Cody");
                ct2 = new CloneTrooper("Bly");
                ct3 = new CloneTrooper("Thire");
                ct4 = new CloneTrooper("Keller");            
                ct1.AddSubordinate(ct2);
                ct1.AddSubordinate(ct3);
                ct1.AddSubordinate(ct4);
                ct4.AddSubordinate(ct1);  // OMG, a circular reference!
            }
            
            [Test]
            public void TestCloneTrooperSimple() {
                
                Assert.AreEqual("Cody", ct1.Name);
                Assert.AreEqual("Bly", ct2.Name);
                Assert.AreEqual("Cody", ct1.ToString());
                Assert.AreEqual("Bly", ct2.ToString());
                
                Assert.AreEqual(ct1, ct1);             
                Assert.AreSame(ct1, ct1);
    
                var other = new CloneTrooper("Cody");
                            
                Assert.AreEqual(ct1, other);
                Assert.AreEqual(ct1.GetHashCode(), other.GetHashCode());
                Assert.AreNotSame(ct1, other);
                Assert.AreNotEqual(ct1, ct2);
                Assert.AreNotEqual(ct1, "Cody");            
            }
            
            [Test]
            public void TestCloneTrooperClone() {
                
                var clone = ct1.Clone();
                
                Assert.AreEqual(ct1, clone);
                Assert.AreNotSame(ct1, clone);
                
                var enum1 = clone.GetEnumerator();
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreSame(ct2, enum1.Current);
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreSame(ct3, enum1.Current);
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreSame(ct4, enum1.Current);
                
                var enum2 = enum1.Current.GetEnumerator();
                                     
                Assert.IsTrue(enum2.MoveNext());
                Assert.AreSame(ct1, enum2.Current);
                
                Assert.IsFalse(enum2.MoveNext());
                Assert.IsFalse(enum1.MoveNext());
            }
            
            [Test]
            public void TestCloneTrooperDeepCopy() {
                
                var clone = ct1.DeepCopy();
                
                Assert.AreEqual(ct1, clone);
                Assert.AreNotSame(ct1, clone);
                
                var enum1 = clone.GetEnumerator();
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreEqual(ct2, enum1.Current);
                Assert.AreNotSame(ct2, enum1.Current);
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreEqual(ct3, enum1.Current);
                Assert.AreNotSame(ct3, enum1.Current);
                
                Assert.IsTrue(enum1.MoveNext());
                Assert.AreEqual(ct4, enum1.Current);
                Assert.AreNotSame(ct4, enum1.Current);
                
                var enum2 = enum1.Current.GetEnumerator();
                
                Assert.IsTrue(enum2.MoveNext());
                Assert.AreEqual(ct1, enum2.Current);
                Assert.AreNotSame(ct1, enum2.Current);
                Assert.AreSame(clone, enum2.Current);
                
                Assert.IsFalse(enum2.MoveNext());
                Assert.IsFalse(enum1.MoveNext());
            }
        }    
    }

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