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