简体   繁体   中英

Why do I need the Singleton design pattern?

i try to learn design pattern, but it's really really hard to understand main idea of OOD. i have created my software with classic method. On the other hand i want to learn OOD. why i need singleton and others? i coded some simple program: one of them clasical(my style), the other is singleton pattern.Please teach me why do i need singleton. my method better and clear than it :)

my style: (C#)


  public partial class Singletonsuz : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Loadbalancer balancer = new Loadbalancer();

        for (int i = 0 ; i < 15 ; i++)
        {
            string server = balancer.Server;
            Response.Write("Dispatch Request to: " + server);
        }
    }
}
class Loadbalancer
{
    private List<string> _servers = new List<string>();
    private Random _random = new Random();
    public Loadbalancer()
        {
            _servers.Add("ServerI");
            _servers.Add("ServerII");
            _servers.Add("ServerIII");
            _servers.Add("ServerIV");
            _servers.Add("ServerV");
        }
    public string Server
    {
        get
        {
            int r = _random.Next(_servers.Count);
            return _servers[r].ToString();
        }
    }
}

SINGLETON:


    public partial class SingletonDP2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
            for (int i = 0; i < 15; i++)
            {
                string server = balancer.Server;
                Response.Write("Dispatch Request to: " + server );
            }
        }

        class LoadBalancer
        {
            private static LoadBalancer _instance;
            private List<string> _servers = new List<string>();
            private Random _random = new Random();

            private static object syncLock = new object();
            protected LoadBalancer()
            {
                _servers.Add("ServerI");
                _servers.Add("ServerII");
                _servers.Add("ServerIII");
                _servers.Add("ServerIV");
                _servers.Add("ServerV");
            }

            public static LoadBalancer GetLoadBalancer()
            {
                if (_instance == null)
                {
                    lock (syncLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new LoadBalancer();
                        }
                    }
                }
                return _instance;
            }

            public string Server
            {
                get
                {
                    int r = _random.Next(_servers.Count);
                    return _servers[r].ToString();
                }
            }
        }
    }

Design patterns are not a design or development methodology . They are a vocabulary : they help putting names on recurring patterns that occur in software architectures. From my experience, designing a software FROM patterns ends up in hairy software with a lot of single-purpose classes, which increases the number of things that the programmer must have in mind (and software development is complicated enough to avoid filling your brain with noise).

However design patterns come very handy at a later stage. Always start with your specific problem and domain, try to find solutions, and identify patterns in the process. Don't start with the patterns, trying to force-fit your problem into them. Knowledge of the most common patterns is a must, as it eases communication between programmers (be they developer or library users) and promotes good practices.

For example, let's suppose that your problem deals with sets of data. At some point you've built your data structures and algorithms. Now you (or someone else) need to access your data in a higher level way. This is the typical case where the Iterator or Visitor patterns can apply. That's the way it has been done in the C++ STL, where all collection classes understand iterators. However you don't need to think upfront about the patterns you may or may not apply here or there, there is always a time to refactor things once patterns or needs have been identified.

Design patterns originally come from building and architecture, which are very similar to software development in many ways. From my experience the best way to understand DPs is through analogy with architecture: software is the building, patterns are the way architectural elements are organized: windows, doors, corridors, stairs, lights... Architects don't think about the elements they want to use, but think about the effect they want to get. For example, an architect might think: this staircase needs light. To achieve this, he may use windows, skylights, glass blocks, artificial lights, etc., according to the architectural constraints, building code, his client's taste, etc. He doesn't arbitrarily choose elements before thinking about the problem he's trying to solve, unless he's trying to achieve an effect or style. Moreover, if another solution becomes available on the market (eg reflective sunlight tunnels) then he may integrate it in the available design patterns for his future projects. OTOH if he takes the habit of thinking about solutions before thinking about problems, he takes the risk of missing alternative solutions, complicating the problem, or not solving it at all.

Here you've used the Singleton pattern for what appears to be a global object needing dynamic initialization. In this case the Singleton is an acceptable solution. However sometimes you would need more complex solutions because of external constraints (eg you need to initialize the objects in a certain order), and Singleton would no longer be appropriate. Or the object would only need static initialization and a plain global variable would fit your needs.

Overusing design patterns is as bad as not using them where they are needed. Choosing whether to use some pattern or not comes with knowledge and experience on software design and development in general, and your field in particular.

You don't really need patterns. What you need are solutions to a concrete problem. Patterns are just generic solutions to well-known problems, and thus are considered good and working solutions.

The problem with patterns is that you can easily find yourself seeking the problem to the solution. ie you start searching a pattern which fits into the problem, when you should be thinking the other way around: think of the problem, and then try if your solution match a pattern.

When you have a hammer everything looks like a nail...

The Singleton pattern is widely recognised as not really a pattern. It's more like an example of how one might present a pattern.

You may find that a more general purpose pattern such as the Visitor is more useful.

Singleton's are often simply used to justify the existence of some global state.

If you have global state accept it and don't feel the need to wrap it in a pattern like singleton except perhaps in the following limited circumstances:

Your are presenting this global state from a library.

If you are exposing it as a plain public static field it may become extremely difficult to change your decision to rely on global state (something that is likely to occur).

In those circumstances presenting the value to the outside world not as a Singleton but as a default that just happens to be statically defined will allow the change in design (and discourage users of the API to treat it as if it could only be the only instance).

This is really just a Factory that you are currently implementing simply

As such the 'hiding' of the construction is the important part, not the global nature of the returned value.

In cases where the consumers of the class are part of the same build process (ie if you change the class in some way the code affected will be directly affected on the next build) then the need to do this wrapping to allow change is a moot point since you can simply change it directly if need be. This is an application of the You Aren't Gonna Need It guideline.

The Singleton Pattern is the officially-recognized way of doing something akin to global variables in modern, OOP languages. This prevents global variable name conflicts and so forth since it is isolated to a class, and therefore duplicate class names are easier to avoid (since your compiler will err out). It's also easier to create an object with "lazy instantiation": You can wait until the object is needed the first time to instantiate it, within the singleton function. This saves some CPU cycles in the long run.

This is one of the most famous design patterns as far as interview questions are concerned.

Imagine a building with G+4 floors. Each floor has 2 flats and a total of 8 flats in the building. With an average of 4 members per flat, you would have 32 members minimum using the lift.

Now consider an office building of 8 floors. Each floor has at least 5 offices, and the number of employees in each is never limited.

In the first scenario we didn't need more than one elevator. In the second scenario, a single elevator simply wasn't enough.

Now that you have understood the need of single lift vs the need of multiple lifts. This sets the ground for us to understand Singleton design pattern.

SINGLETON DESIGN PATTERN

Just like the elevator in previous example, Singleton design pattern is also used to create and use ONLY ONE instance of an object.

Why? Because the application doesn't need more than one object.

If you have seen professional offices, you would have observed one single printer being shared by all employees on one floor. All students don't keep a printer at their home, they would rather go and pay to the cyber cafe in their colony and use his printer for their momentary requirement.

All of this because the object in question here is EXPENSIVE. From a software perspective, an object is "expensive" when it utilizes a lot of resources to execute its operation.

So now we have the need of Singleton design pattern:

1) when the application will not use that object more than a few times throughout its entire lifecycle.

2) when the application needs an object frequently, but the object itself is very computationally expensive.

IMPLEMENTATION OF SINGLETON DESIGN PATTERN

Singleton design pattern states that: Allow creation of only one instance of a class throughout the application and provide a global point of access to it

So the first part refers to "restricting" construction.

From our early days of object oriented implementation in Java, we know that constructors are special functions called during program execution and they can be made private. When a constructor is made private, any code outside the class cannot create its object. So for implementation of Singleton design pattern, we will need a "private constructor" and we'll create an object inside the class using that constructor.

The second part of our definition talks about giving a global handle to this single object. We will do that using a public method.

Design patterns are used to structure code in large code bases. Instead of every single programmer using their own style of coding, and connecting systems left to right, you use a design pattern suitable for the application that you are developing. The design pattern basically says how you should structure your code, and how different systems should interact with each other.

The use of design patterns can speed up development time, and might force you to think in a way that can prevent further problems down the line. If you want to work in the field, learning, or at least having knowledge of a multitude of design patterns is of the utmost importance. A company with a large software project, constructed with a specific pattern, won't look kindly on you if you start writing code like some cowboy, breaking and corrupting the chosen idiom. Since this has the effect of confusing other developers on the team, and generally making things harder to understand.

Singletons are more for when you provide code/libraries to others...

Your first example allows multiple instances and therefore does not follow the singleton pattern.

The second example does not allow multiple instances... having a public constructor in the first one allows multiple instances of LoadBalancer. Because it is protected (private) in the second example and the caller must use "GetLoadBalancer" which checks for an existing instance, it enforces only one copy.

Well, you need to know where a patron using the most important thing is not the code is specific to the context The singleton can be used if you want to ensure a single point of access to methods and properties of an object in your aplication. Is used for example in classes that handle access to a table in the database. However singletons tends to spread through the applications even when you really dont need them

In your example there's no real benefit in having only one instance of LoadBalancer around. That makes it harder to understand the possible benefits of a Singleton.

The LoadBalancer in your example just returns random servers.

Imagine a Loadbalancer class that keeps track of which servers he/she has already returned, this way the LoadBalancer can return the server with the least load on.

In that situation it is necessary that all Singletonsuz instances talk to the same LoadBalancer: if they would all just create their own (which has no knowledge of what other LoadBalancers did), then there would be no real balancing and keeping track of returned servers would be useless.

If they all need to talk to the same instance, they can call the static GetLoadBalancer and then that singe instance can return a server that has been returned the fewest times.

Hope this helps

Jan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM