views:

1662

answers:

9

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();
                }
            }
        }
    }
+5  A: 

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.

Greg Hewgill
Widely recognized as not a pattern? Wouldn't say that, and that's not what the blog post is saying. Potentially harmful? That's more like it, but then so is everything at the wrong time or in the wrong amount, including water.
Pontus Gagge
A: 

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.

jimka
+6  A: 

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. i.e. 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...

Ricky AH
A lot of them are already in the .NET framework too :) http://msdn.microsoft.com/en-gb/magazine/cc188707.aspx
Chris S
+3  A: 

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 (i.e. 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.

ShuggyCoUk
Yes a factory pattern definitely makes more sense for this
Chris S
A: 

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.

Nolte Burke
A: 

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.

jheriko
+18  A: 

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 (e.g. 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 (e.g. 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.

fbonnet
I take it you haven't read Christopher Alexander's "Pattern Language"... His original set of (architectural) patterns includes things like "Light on Two Sides of Every Room", not "a window". But I do agree that software patterns should be DEscriptive, not PREscriptive.
Dave Sherohman
Good remark, thanks. I've rephrased a little bit.
fbonnet
A: 

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

A: 

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

jan