Follow

Follow
Prototype - Design Pattern

Prototype - Design Pattern

Software Architecture Simplified

Victor Campos Lins's photo
Victor Campos Lins
·Jul 19, 2022·

3 min read

Table of contents

  • Objective 🎯
  • Notes 📝
  • Type ✅
  • UML 📐
  • Participants 🔗
  • Sample Code 🎮
  • Source Code 🎲

Objective 🎯

Allow to create an object from cloning another object (Prototype), to hide the complexity of making new instances and to avoid costly operations.

Notes 📝

• When 2 objects have the same reference it means that they are sharing the same space in memory and any change in one object will reflect in the other.

Normal Copy process preserves the reference of the original object including the objects inside it.

image.png

Shallow Copy process does not preserve the reference of the original object but keep the reference of the objects inside it.

image.png

Deep Copy process does not preserve the reference of the original object or the reference of the objects inside it.

image.png

Type

Behavioral: Describes how objects interact/communicate between themselves.

✔️Creational: Describes how to instantiate an object without large and complex.

Structural: Describes how objects/classes are composed to form larger structures.

UML 📐

image.png

Participants 🔗

• Prototype:

  • Declares an interface for cloning itself

• ConcretePrototype:

  • Implements an operation for cloning itself

• Client:

  • Creates new object by asking a prototype object to clone itself

Sample Code 🎮

Structural Example 🏛️

image.png

public static class PrototypeStructural
    {
        public static void Execute()
        {
            ConcretePrototype1 lConcretePrototype1 = new ConcretePrototype1("1");
            ConcretePrototype1 lCloneConcretePrototype = (ConcretePrototype1)lConcretePrototype1.Clone();
            Console.WriteLine($"Cloned {lConcretePrototype1.GetType().Name}");

            ConcretePrototype2 lConcretePrototype2 = new ConcretePrototype2("2");
            ConcretePrototype2 lCloneConcretePrototype2 = (ConcretePrototype2)lConcretePrototype2.Clone();
            Console.WriteLine($"Cloned {lCloneConcretePrototype2.GetType().Name}");
        }
    }

    public abstract class Prototype
    {
        public string _Id { get; set; }

        public Prototype(string prId)
        {
            _Id = prId;
        }

        public abstract Prototype Clone();
    }

    public class ConcretePrototype1 : Prototype
    {
        public ConcretePrototype1(string prId)
            : base(prId) { }

        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }

    public class ConcretePrototype2 : Prototype
    {
        public ConcretePrototype2(string prId)
            : base(prId) { }

        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }

Output

image.png

Real-world Example 🔥

image.png

public static class PrototypePractical
    {
        public static void Execute()
        {
            ShapeHelper lShapeHelper = new ShapeHelper();
            lShapeHelper.CreateShapes("Square", 2);
            lShapeHelper.CreateShapes("Circle", 3);
            lShapeHelper.CreateShapes("Triangle", 4);

            Console.WriteLine($"\n\rCreated {lShapeHelper._Shapes.Count} objects in total");
        }
    }

    public class ShapeHelper
    {
        public List<Shape> _Shapes = new List<Shape>();

        public void CreateShapes(string prType, int prQuantity)
        {
            Shape lOriginalShape = null;
            switch (prType)
            {
                case ("Circle"): lOriginalShape = new Circle("#1"); break;
                case ("Square"): lOriginalShape = new Square("#1"); break;
                case ("Triangle"): lOriginalShape = new Triangle("#1"); break;
                default: break;
            }

            if (lOriginalShape != null)
            {
                Console.WriteLine($"• Creating {prQuantity} {lOriginalShape.GetType().Name}s...");
                Console.WriteLine($"    Created object {lOriginalShape.GetType().Name} - Id: {lOriginalShape._Id}");

                _Shapes.Add(lOriginalShape);
                for (int i = 1; i < prQuantity; i++)
                {
                    _Shapes.Add(lOriginalShape.Clone());
                    Console.WriteLine($"      Clonned object {lOriginalShape.GetType().Name} - Id: {lOriginalShape._Id}");
                }
            }
        }
    }

    public abstract class Shape
    {
        public string _Id { get; set; }
        public string _Type { get; set; }

        public Shape(string prId, string prType)
        {
            _Id = prId;
            _Type = prType;
        }

        public virtual Shape Clone()
        {
            // To "Clone" an object can be done either by using Shallow Copy or Deep Copy approach
            // In the below example Shallow Copy approach is used
            return (Shape)this.MemberwiseClone();
        }
    }

    public class Circle : Shape
    {
        public Circle(string prId)
            : base(prId, "Circle") { }

    }

    public class Square : Shape
    {
        public Square(string prId)
            : base(prId, "Square") { }

    }

    public class Triangle : Shape
    {
        public Triangle(string prId)
            : base(prId, "Triangle") { }

    }

Output

image.png

Source Code 🎲

github.com/VictorLins/DesignPatterns

Did you find this article valuable?

Support Victor Campos Lins by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this