Do not understand the design mode, do not understand the design mode

Source: Internet
Author: User

Do not understand the design mode, do not understand the design mode

This article focuses on the design pattern, which is complex and not the same as in the book.

Let's start with a simple requirement: "to make the system only have one SendEmailObject object"

Code:

Public class SendEmailObject {public bool Send () {Console. writeLine ("Email sent from:" + this. getHashCode (); // call GetHashCode to check whether the instance has the same return false;} public static class Factory {private static SendEmailObject sendEmail; public static SendEmailObject GetSendEmailObject () {if (sendEmail = null) {lock (typeof (SendEmailObject) // adds a lock {if (sendEmail = null) sendEmail = new SendEmailObject ();}} return sendEmail ;}}

Main function call code:

            var o = Factory.GetSendEmailObject();            o.Send();            o = Factory.GetSendEmailObject();            o.Send();            Console.Read();

After running:

The above code is strongly coupled with the specific class "SendEmailObject", so it is not general enough. If I need many classes to control the number of instances, we need to copy and paste a lot of code, so let's look at the following improvements:

Supports generic methods (more general)

Code:

Public static class Factory {private static Dictionary <Type, object> instances = new Dictionary <Type, object> (); public static T GetInstance <T> () where T: class, new () {T o = null; if (instances. containsKey (typeof (T) o = instances [typeof (T)] as T; if (o = null) {lock (instances) {if (instances. containsKey (typeof (T) o = instances [typeof (T)] as T; if (o = null) {o = new T (); instances [typeof (T)] = o ;}} return o;} public static int GetInstanceCount () // This method is only used for testing, remove {return instances. count ;}}

 

Main call code:

            var o = Factory.GetInstance<SendEmailObject>();            o.Send();            o = Factory.GetInstance<SendEmailObject>();            o.Send();            o = Factory.GetInstance<SendEmailObject>();            o.Send();            o = Factory.GetInstance<SendEmailObject>();            o.Send();            Console.WriteLine("Factory instance count: " + Factory.GetInstanceCount());            Console.Read();

 

After running:

Check the output of the last row. Only one instance is required. Haha, Universal Pull...

 

All of the above requirements require only one instance. What if this requirement is required? "Because the SendEmailObject class is very heavy and considering the performance, you need to: Convenient access + control the number of instances + simultaneous request processing for multiple instances", please refer to the following method:

The following code controls the number of instances (max:

Public static class Factory {private static int MaxInstancePerType = 3; // a maximum of three instances are set here: private static Dictionary <Type, List <object> instances = new Dictionary <Type, list <object> (); // instance queue private static Dictionary <Type, int> instanceCounters = new Dictionary <Type, int> (); // instance corresponding counter queue public static T GetInstance <T> () where T: class, new () {lock (instances) // lock Object {if (! Instances. containsKey (typeof (T) {List <object> tmplist = new List <object> (); for (int I = 0; I <MaxInstancePerType; I ++) {T o = new T (); tmplist. add (o);} instances. add (typeof (T), tmplist); instanceCounters. add (typeof (T), 0);} List <object> list = instances [typeof (T)] as List <object>; int curIndex = instanceCounters [typeof (T)]; T instance = list [curIndex] as T; curIndex ++; curIndex = curIndex % MaxInstancePerType; // cyclically modulo instanceCounters [typeof (T)] = curIndex; return instance ;}}}

 

Main call code:

            SendEmailObject o;            for (int i = 0; i < 10; i++)            {                o = Factory.GetInstance<SendEmailObject>();                o.Send();            }            Console.Read();

 

Run the following command:

Haha, the above output is cyclical, with three loops in one group.

 

Next, let's talk about the problem. Some people say, "Why is there no interface for this object ?" Well, add one, as shown below:

Public interface IEmailService // the newly added interface {bool Send ();} public class SendEmailObject: IEmailService {public bool Send () {Console. writeLine ("Email sent from:" + this. getHashCode (); return false ;}}

 

Some people say that I want to implement this requirement: "I provide an interface, and the factory returns an instance". OK, no problem. Write the Code:

public static class Factory    {        private static Dictionary<Type, Type> typeMappers = new Dictionary<Type, Type>();        public static void Register<M, N>()            where N : class, new()        {            if (typeMappers.ContainsKey(typeof(M)))                throw new Exception("Key existed");            typeMappers.Add(typeof(M), typeof(N));        }        public static M Resolve<M>()        {            if (!typeMappers.ContainsKey(typeof(M)))                throw new Exception("Key empty, register please");            Type type = typeMappers[typeof(M)];            return (M)Activator.CreateInstance(type);        }    }

 

Main call code:

Factory.Register<IEmailService, SendEmailObject>();
IEmailService srv = Factory.Resolve<IEmailService>();srv.Send();
srv = Factory.Resolve<IEmailService>();srv.Send();
Console.Read();

 

Running output:

Look, oh, no, it's two instances ?! Haha, right, there are two instances, because the above Code does not control the number of instances. If you are interested, change it and release it. Haha.

Oh, by the way, do the above Code really miss the Resolve methods of Unity Resolve and StructureMap? Haha.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.