Skip to main content

Command Palette

Search for a command to run...

Prototype - Design Pattern

Software Architecture Simplified

Published
3 min readView as Markdown
Prototype - Design Pattern
V

I am a software engineer with over 10 years of experience in a huge variety of projects and architectures, some simple others considerably complex.

Some of my main skills include Software Architecture, Web Development, ASP.NET Core, React.js, Entity Framework Core, Javascript, SQL and Web Services.

I consider myself passionate about coding as I really fell excited about learning technologies and using them to automate and improve processes.

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 🎲

https://github.com/VictorLins/DesignPatterns