As usual, we speak about pattern using example. I don’t want to copy examples from books, because it may be some difficult for first reading and has extra data. I want to understand pattern using simple example and then tell about this piece of knowledge in my blog. Let’s start.

We have Document class, that has several parts. Some of this parts are similar for specific document types. We have Order documents, that has 3 tags: Human resources, Office, Rules. And also we have Special document, that has 2 tags: Security and Secret.

        [Serializable]
        public class Document
        {
            public Document(string num, DateTime date, string content, List<string> tags)
            {
                Num = num;
                Date = date;
                Content = content;
                Tags = tags;
            }

            public string Num { get; set; }
            public DateTime Date { get; set; }
            public string Content { get; set; }
            public List<string> Tags { get; set; }
            public override string ToString()
            {
                return $"Num: {Num}; Date: {Date}; Content: {Content}; TagList: {string.Join(" ",Tags)}";
            }
        }

How we can get a copy of object? For example, we can add Copy method for our class and it will create copy of our object. But if our main class will be more complicated, with another objects, we receive scalability problem, because our Copy method should have a lot of code. We can’t deep duplicate complicated object, that contains another objects.

And one of methods, that can resolve this task is using serialize methods. For example this extension method.

    public static class ExtensionMethods
    {
        public static T DeepCopy<T>(this T self)
        {
            using (var stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, self);
                stream.Seek(0, SeekOrigin.Begin);
                object copy = formatter.Deserialize(stream);
                return (T)copy;
            }
        }
    }

In this example we can also use Factory pattern for creating objects.

        public class DocumentFactory
        {
            private static Document orderDocTemplate = new Document("", DateTime.Now, "", new List<string> { "Human resources", "Office", "Rules" });
            private static Document specDocTemplate = new Document("", DateTime.Now, "", new List<string> { "Security", "Secret" });
            public static Document CreateOrderDoc(string num, DateTime date, string content)
            {
                var orderDoc = orderDocTemplate.DeepCopy();
                orderDoc.Num= num;
                orderDoc.Date= date;
                orderDoc.Content= content;
                return orderDoc;
            }
            public static Document CreateSpecDoc(string num, DateTime date, string content)
            {
                var specDoc = specDocTemplate.DeepCopy();
                specDoc.Num = num;
                specDoc.Date = date;
                specDoc.Content = content;
                return specDoc;
            }
        }

Main advantage of Factory and Prototype patterns is easy objects creation. Let’s see.

            var orderDoc = DocumentFactory.CreateOrderDoc("Order-1", DateTime.Now, "Main order doc");
            var specDoc = DocumentFactory.CreateSpecDoc("Spec-1", DateTime.Now, "First special document");

            Console.WriteLine(orderDoc);
            Console.WriteLine(specDoc);

Result of our program:

Num: Order-1; Date: 27.01.2023 20:28:05; Content: Main order doc; TagList: Human resources Office Rules
Num: Spec-1; Date: 27.01.2023 20:28:05; Content: First special document; TagList: Security Secret