[handwritten source code - design mode 11] - enjoy yuan mode - based on playing mahjong scene

1: Subject disassembly

① Basic introduction

② The source of Peacock Flying Southeast

③ Mahjong scene simulation

④ Advantages and disadvantages of sharing mode

⑤ Applicable scenario

⑥ Application examples

⑦ Differences between meta mode and singleton mode

⑧ Meta mode extension

2: Basic introduction

          When it comes to meta sharing mode, the first thought should be the pool technology. String constant pool, database connection pool, buffer pool, etc. are all applications of meta sharing mode, so meta sharing mode is an important implementation of pool technology.

         For example, every time we create a string object, we need to create a new string object, which will lead to a large memory overhead. Therefore, if we create a string object "design pattern" for the first time and create the same string "design pattern" next time, we only need to point its reference to "design pattern", so as to realize "design pattern" String sharing in memory.

3: The source of Peacock Flying Southeast

         When it comes to playing mahjong, I believe you are most interested in Hu cards and winning money. I also want to ha ha. Let's play Hu cards today. Let's have a big one. Start with the picture above.

          This deck of cards is named Peacock Flying Southeast. The Peacock Flying Southeast in Mahjong refers to Yao chicken, east wind and south wind. Because Yao chicken looks like a peacock, it is called "Peacock Flying Southeast" when encountering east wind and south wind, which belongs to the name of Hu brand.

The picture is only used to explain. It does not involve gambling. Please treat it correctly.

1: Origin 1

Originated from the Yuefu poem "Peacock Flying Southeast" in the Han Dynasty, it is the peak work in the development history of Yuefu Poetry. Later generations call it "Yuefu double Bi" with Mulan poetry in the Northern Dynasty. The story is simple, well tailored and the characters are lifelike. It not only creates the image of the couple of Jiao and Liu who are heart to heart and firm and unyielding, but also deeply depicts the stubbornness of Jiao's mother and brother Liu's arrogance. The end of the article conceives the myth that Liu Lanzhi and Jiao Zhongqing become mandarin ducks after their death, and places the strong desire of the people to pursue love freedom and a happy life.

Based on the yearning for love freedom and happy life, combined with the spirit of mahjong, the brand type of "Peacock Flying Southeast" came into being.

The peacock flies southeast, which means that the east wind and the south wind must be carved when playing the peace card. The Yao chicken can be carved or only one pair.

As for other cards, there are no restrictions. After all, a single chicken can fly in the East and south directions, so more than two single chickens must be required, otherwise it can only fly in one direction, and the east wind and south wind should be equal.

2: Origin 2

Peacock SoutheastFlying, first evolved from the playing method of Japanese Red peacock. Red peacock is a deck of cards with cops in it. And they all have red strips, and they must be three or three, such as three single chickens, three five strips, three seven strips and three nine strips.

  The Peacock Flying Southeast is based on the red peacock, plus three easterly winds and three southerly winds, such as two single chickens, three five, three seven, three southerly winds and three easterly winds. This is called Peacock Flying Southeast.

3: Summary

I believe that source 1 must be the most authentic. The combination of love freedom and the longing for a happy life and the spirit of mahjong is the crystallization of the wisdom of our predecessors of the Chinese nation.

4: Mahjong scene simulation

Do we still remember the Hu cards above, three Yao chickens, two five, three seven, three East and three south wind

Now we begin to simulate playing mahjong.

1: Basic Edition

① Mahjong base

public abstract class Base mahjong
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreateTime { get; set; }
    public abstract string Get();
}

② Single mahjong instance

public class Single : Base mahjong
{
    public Single()
    {
        long lResult = 0;
        for (int i = 0; i < 1000000; i++)
        {
            lResult += i;
        }
        Thread.Sleep(1500);
        this.Name = this.GetType().Name;
        Console.WriteLine("{0}Constructed....", this.Name);            
    }
    public override string Get()
    {
        return this.Name;
    }
}
public class east : Base mahjong
{
    public east()
    {
        long lResult = 0;
        for (int i = 0; i < 1000000; i++)
        {
            lResult += i;
        }
        Thread.Sleep(1500);
        this.Name = this.GetType().Name;
        Console.WriteLine("{0}Constructed....", this.Name);
    }
    public override string Get()
    {
        return this.Name;
    }
}
public class south : Base mahjong
{
    public south()
    {
        long lResult = 0;
        for (int i = 0; i < 1000000; i++)
        {
            lResult += i;
        }
        Thread.Sleep(1500);
        this.Name = this.GetType().Name;
        Console.WriteLine("{0}Constructed....", this.Name);
    }
    public override string Get()
    {
        return this.Name;
    }
}
public class five : Base mahjong
{
    public five()
    {
        long lResult = 0;
        for (int i = 0; i < 1000000; i++)
        {
            lResult += i;
        }
        Thread.Sleep(1500);
        this.Name = this.GetType().Name;
        Console.WriteLine("{0}Constructed....", this.Name);
    }
    public override string Get()
    {
        return this.Name;
    }
}
public class seven : Base mahjong
{
    public seven()
    {
        long lResult = 0;
        for (int i = 0; i < 1000000; i++)
        {
            lResult += i;
        }
        Thread.Sleep(1500);
        this.Name = this.GetType().Name;
        Console.WriteLine("{0}Constructed....", this.Name);
    }
    public override string Get()
    {
        return this.Name;
    }
}

③ Upper end call

Base Mahjong chicken 1 = new Single();
Base Mahjong chicken 2 = new Single();
Base Mahjong chicken 3 = new Single();
Base Mahjong five 1 = new five();
Base Mahjong five 2 = new five();
Base Mahjong seven 1 = new seven();
Base Mahjong seven 2 = new seven();
Base Mahjong seven 3 = new seven();
Base Mahjong Dongfeng 1 = new east();
Base Mahjong Dongfeng 2 = new east();
Base Mahjong Dongfeng 3 = new east();
Base Mahjong South Wind 1 = new south();
Base Mahjong south wind 2 = new south();
Base Mahjong south wind 3 = new south();
var hupai = $"{Yaoji 1.Get()}{Yaoji 2.Get()}{Yaoji 3.Get()}{Article 5 1.Get()}{Article 5 2.Get()}{Article 7 1.Get()}{Article 7 2.Get()}{Article 7 3.Get()}{Dongfeng 1.Get()}{Dongfeng 2.Get()}{Dongfeng 3.Get()}{South Wind 1.Get()}{South wind 2.Get()}{South wind 3.Get()}";
Console.WriteLine(hupai);

④ Execution results

Analysis: at present, a basic version of Peacock Flying Southeast has been realized. Each piece of mahjong is instantiated at the time of construction, which is particularly time-consuming. Obviously, this method constructs many repeated objects, resulting in a waste of resources

2: Object reuse

① Upper end call

Base Mahjong chicken 1 = new Single();              
Base Mahjong five 1 = new five();              
Base Mahjong seven 1 = new seven();             
Base Mahjong Dongfeng 1 = new east();               
Base Mahjong South Wind 1 = new south();               
var hupai = $"{Yaoji 1.Get()}{Yaoji 1.Get()}{Yaoji 1.Get()}{Article 5 1.Get()}{Article 5 1.Get()}{Article 7 1.Get()}{Article 7 1.Get()}{Article 7 1.Get()}{Dongfeng 1.Get()}{Dongfeng 1.Get()}{Dongfeng 1.Get()}{South Wind 1.Get()}{South Wind 1.Get()}{South Wind 1.Get()}";
Console.WriteLine(hupai);

② Execution results

Analysis: after reusing the same objects, the execution time is obviously much less than before, avoiding the waste of many duplicate objects. But if other methods -- other classes -- other class libraries -- other threads need to reuse objects to improve performance, what should we do?

3: Enjoy yuan mode version

① Xiangyuan factory

public class FlyweightFactory
{
    //Prepare a container for data reuse
    private static Dictionary<mahjong Type, Base mahjong> FlyweightFactoryDictionary = new Dictionary<mahjong Type, Base mahjong>();
    private static object FlyweightFactory_Lock = new object();


    ///Multiple threads execute at the same time, and the dictionary is empty, so it will be constructed multiple times at the same time
    ///Finally, only one element was printed because other threads hung -- because there was an exception when adding the dictionary
    ///Two identical mahjong events belong to small probability events. The first two threads add the same mahjong at the same time, so they have not failed, so there will be two,
    ///But at the back of mahjong, there was a conflict again
    ///The exception of a child thread cannot be obtained unless waitall
    public static Base mahjong Creat mahjong(mahjong Type type)
    {
            if (!FlyweightFactoryDictionary.ContainsKey(type))
            //This is to optimize performance and avoid waiting for locks after the object has been initialized
            {
                lock (FlyweightFactory_Lock)//Monitor.Enter to ensure that only one thread of the method body can enter
                {
                    if (!FlyweightFactoryDictionary.ContainsKey(type))
                    {
                        Base mahjong word = null;
                        switch (type)
                        {
                            case mahjong Type.Single:
                                word = new Single();
                                break;
                            case mahjong Type.five:
                                word = new five();
                                break;
                            case mahjong Type.seven:
                                word = new seven();
                                break;
                            case mahjong Type.east:
                                word = new east();
                                break;
                            case mahjong Type.south:
                                word = new south();
                                break;
                            default:
                                break;
                        }
                        FlyweightFactoryDictionary.Add(type, word);
                    }
                }
            }
            return FlyweightFactoryDictionary[type];
        }
}

public enum mahjong Type
{
    Single,
    five,
    seven,
    east,
    south
}

② Upper end call, multithreading mode

for (int i = 0; i < 5; i++)
{
    Task.Run(() =>//Almost start five threads at the same time to complete the calculation
    {
        Base Mahjong chicken 1 = FlyweightFactory.Creat mahjong(mahjong Type.Single);
        Base Mahjong five 1 = FlyweightFactory.Creat mahjong(mahjong Type.five);
        Base Mahjong seven 1 = FlyweightFactory.Creat mahjong(mahjong Type.seven);
        Base Mahjong Dongfeng 1 = FlyweightFactory.Creat mahjong(mahjong Type.east);
        Base Mahjong South Wind 1 = FlyweightFactory.Creat mahjong(mahjong Type.south);
        var hupai = $"{Yaoji 1.Get()}{Yaoji 1.Get()}{Yaoji 1.Get()}{Article 5 1.Get()}{Article 5 1.Get()}{Article 7 1.Get()}{Article 7 1.Get()}{Article 7 1.Get()}{Dongfeng 1.Get()}{Dongfeng 1.Get()}{Dongfeng 1.Get()}{South Wind 1.Get()}{South Wind 1.Get()}{South Wind 1.Get()}";
        Console.WriteLine(hupai);
    });
}

Analysis: unified entry -- things that want to control the global situation and add reuse Logic -- static dictionary cache. Based on these two points, object reuse of different classes, different class libraries and different threads is realized.

In order to solve the problem of object reuse, shared meta mode provides third-party management and can complete object reuse.

1: You can also instantiate objects by yourself, unlike singleton, which is mandatory  .

2: The shared element factory can also initialize multiple objects -- objects that need to be used in other places can be taken from me (modify a state) -- put them back after they are used up (change the state) -- avoid repeated creation and destruction of objects, especially for unmanaged resources - pooled resource management.

5: Advantages and disadvantages of sharing mode

1: Advantages

Reduce memory consumption: the meta sharing mode can greatly reduce the number of objects in memory, so that only one copy of the same or similar objects is saved in memory, so as to save system resources and provide system performance.

External state independence: the external state of the meta sharing mode is relatively independent and will not affect the internal state, so that the meta sharing objects can be shared in different environments.

2: Shortcomings

Increasing complexity: the meta model makes the system complex, and it is necessary to separate the internal state and external state, making the program logic complex.

Longer running time: in order to enable objects to be shared, the meta sharing mode needs to externalize some states of meta sharing objects, and reading external states makes the running time longer.

6: Applicable scenario

A system has a large number of similar or identical objects, resulting in a large amount of memory waste.

Most states of an object can be externalized, and these external states can be passed into the object.

Because the sharing pool needs to be maintained, resulting in certain resource overhead, it is worth using the sharing mode when the sharing object needs to be reused for many times.

7: Application examples

string constant pool

Database connection pool

8: Differences between meta mode and singleton mode

In meta sharing mode, you can create objects again or get cached objects; Singleton mode strictly controls that there is only one instance object in a single process.

The meta sharing mode can control the external singleton by itself, or create more objects when needed; The singleton mode is self-control and needs to add logic that does not belong to the object itself.

Both can save the time of object creation. The threadPool thread pool and database connection pool all use the meta mode.

9: Meta mode extension

1: Output what?

Base Mahjong 1 = FlyweightFactory.Creat mahjong(mahjong Type.Single);
Base Mahjong Yao 2 = new Single();
Base Mahjong Yao 3 = new Single();
Base Mahjong Yao 4 = FlyweightFactory.Creat mahjong(mahjong Type.Single);
Console.WriteLine(object.ReferenceEquals(Unitary 1, Unitary 2));
Console.WriteLine(object.ReferenceEquals(Unitary 1, Yao 3));
Console.WriteLine(object.ReferenceEquals(Unitary 1, Unitary 4));

 

Analysis: it belongs to reference type   new objects are equal to opening up a space in memory. The variable holds a reference to the memory       object.ReferenceEquals specifically compares reference addresses.

Since unitary 1 and unitary 4 are based on the sharing mode, they are the same object, but unitary 2 and unitary 3 are new instances.

2: Output what?

string mahjong Open = "one five seven";
string mahjong Vip = "one five seven";
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, mahjong Vip)}");
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, new OtherClass().mahjong Other)}");

public class OtherClass
{
   public string mahjong Other = "one five seven";
}

 

Analysis: when allocating memory, string type uses shared meta mode, so it is T.

As long as it is the same process, the allocated Eleven is the same memory address.

3: Output what?

string mahjong Open = "one five seven";
string mahjong Format = string.Format("one five{0}", "seven");
string lastPart = "seven";
string mahjong Combination = "one five" + lastPart;
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, mahjong Format)}");
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, mahjong Combination)}");
Console.WriteLine($"{object.ReferenceEquals(mahjong Format, mahjong Combination)}");

 

Analysis: the allocated "1257" is the same memory address, but these two are not allocated "1257", but partially allocated. Although the final result is "1257", they cannot be reused.

4: Output what?

public class OtherClass
{
   public string mahjong Other = "one five seven";
   public string mahjong Plus = "one five" + "seven";
}
string mahjong Plus = "one five" + "seven";
string mahjong Open = "one five seven";
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, mahjong Plus)}");
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, new OtherClass().mahjong Plus)}");
Console.WriteLine($"{object.ReferenceEquals(mahjong Open, new OtherClass().mahjong Plus)}");

 

Analysis: compiler optimization, string mahjong Plus = "one five" + "seven"; Equivalent to string mahjong Plus = "one hundred fifty-seven";

What are the more interesting scenes? Welcome to study and discuss together, leave a message, and learn and progress together!!!

Tags: Java C# Database Design Pattern architecture

Posted on Fri, 17 Sep 2021 20:18:36 -0400 by danjar