为什么我需要Singleton设计模式?

时间:2009-01-27 08:02:06

标签: c# .net design-patterns oop

我尝试学习设计模式,但真的很难理解OOD的主要思想。我用经典方法创建了我的软件。另一方面,我想学习OOD。为什么我需要单身人士和其他人?我编写了一些简单的程序:其中一个是clasical(我的风格),另一个是singleton模式。请教我为什么需要单身。我的方法比它更好更明确:)

我的风格:(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();
                }
            }
        }
    }

10 个答案:

答案 0 :(得分:28)

设计模式不是设计或开发方法。它们是词汇:它们有助于将名称放在软件体系结构中出现的重复模式上。根据我的经验,设计软件FROM模式最终会出现在多毛的软件中,并且有很多单一用途的类,这增加了程序员必须考虑的事情数量(并且软件开发很复杂,足以避免让你的大脑充满噪音)。

然而,设计模式在后期非常方便。始终从您的特定问题和域开始,尝试找到解决方案,并识别流程中的模式。不要从模式开始,尝试将问题强制适应它们。了解最常见的模式是必须的,因为它可以简化程序员(无论是开发人员还是图书馆用户)之间的沟通,并促进良好实践。

例如,假设您的问题涉及数据集。在某些时候,您已经构建了数据结构和算法。现在,您(或其他人)需要以更高级别的方式访问您的数据。这是Iterator或Visitor模式可以应用的典型情况。这就是在C ++ STL中完成的方式,其中所有集合类都理解迭代器。但是,您不需要事先考虑可能会或可能不适用于此处或那里的模式,一旦确定了模式或需求,总会有时间重构事物。

设计模式最初来自建筑和架构,它们在很多方面与软件开发非常相似。根据我的经验,理解DP的最佳方式是通过类比建筑:软件是建筑,模式是建筑元素的组织方式:窗户,门,走廊,楼梯,灯......建筑师不考虑他们的元素想要使用,但想想他们想要得到的效果。例如,建筑师可能会想:这个楼梯需要光线。为了达到这个目的,他可以根据建筑限制,建筑规范,客户的品味等使用窗户,天窗,玻璃砖,人造灯等。在考虑他试图解决的问题之前,他不会随意选择元素。解决,除非他试图达到效果或风格。此外,如果市场上有另一种解决方案(例如反光阳光隧道),那么他可以将其整合到他未来项目的可用设计模式中。 OTOH如果他在考虑问题之前习惯于考虑解决方案,就会冒着错过替代解决方案,使问题复杂化或根本不解决问题的风险。

在这里,你使用Singleton模式来看似需要动态初始化的全局对象。在这种情况下,Singleton是一个可接受的解决方案。但是,由于外部约束(例如,您需要按特定顺序初始化对象),有时您需要更复杂的解决方案,而Singleton将不再适用。或者对象只需要静态初始化,而普通的全局变量就可以满足您的需求。

过度使用设计模式与在需要时不使用它们一样糟糕。选择是否使用某种模式需要具备软件设计和开发方面的知识和经验,特别是您的领域。

答案 1 :(得分:10)

你真的不需要模式。您需要的是解决具体问题的方法。 模式只是众所周知问题的通用解决方案,因此被认为是良好且有效的解决方案。

模式的问题在于您可以轻松地找到自己在解决方案中寻找问题。即你开始搜索适合问题的模式,当你应该反思时:想一想问题,然后尝试你的解决方案是否符合模式。

当你拿锤子时,一切看起来像钉子......

答案 2 :(得分:5)

Singleton模式是widely recognised并不是真正的模式。它更像是一个人如何呈现模式的例子。

您可能会发现更通用的模式,例如Visitor更有用。

答案 3 :(得分:5)

单身人士通常只是用来证明一些全球国家的存在。

如果你有全局状态接受它并且不觉得需要将它包装在像singleton这样的模式中,除非在以下有限的情况下:

您正在从图书馆展示这个全球状态。

如果您将其作为一个普通的公共静态字段公开,那么改变您依赖全局状态(可能发生的事情)的决定可能变得非常困难。

在这些情况下,将外部世界的价值呈现为不是Singleton而是作为默认,恰好是静态定义将允许设计更改(并阻止API的用户对待就好像它只能是唯一的实例一样。)

这实际上只是您目前正在实施的工厂

因此,构造的“隐藏”是重要的部分,而不是返回值的全局性质。

如果类的使用者是同一构建过程的一部分(即如果以某种方式更改类,受影响的代码将在下一个构建中直接受到影响)那么需要执行此包装以允许更改是一个有争议的问题,因为你可以根据需要直接改变它。这是“你不需要它”的应用指南。

答案 4 :(得分:1)

Singleton Pattern是官方认可的在现代OOP语言中做类似于全局变量的方法。这可以防止全局变量名称冲突等等,因为它与类隔离,因此更容易避免重复的类名(因为编译器会出错)。使用“延迟实例化”创建对象也更容易:您可以在单例函数中等到第一次需要该对象时进行实例化。从长远来看,这可以节省一些CPU周期。

答案 5 :(得分:0)

设计模式用于在大型代码库中构造代码。不是每个程序员都使用自己的编码风格,而是从左到右连接系统,而是使用适合您正在开发的应用程序的设计模式。设计模式基本上说明了如何构建代码,以及不同的系统应该如何相互交互。

使用设计模式可以加快开发时间,并可能迫使您以一种可以防止进一步出现问题的方式进行思考。如果您想在该领域工作,学习或至少了解多种设计模式至关重要。一个拥有大型软件项目的公司,如果你开始像一些牛仔一样编写代码,打破并破坏所选择的习惯用法,那么就不会看起来很好看。因为这会使团队中的其他开发人员感到困惑,并且通常会让事情变得更难理解。

答案 6 :(得分:0)

当你向其他人提供代码/图书馆时,单身人士更有用......

您的第一个示例允许多个实例,因此不遵循单例模式。

第二个例子不允许多个实例......在第一个例子中有一个公共构造函数允许LoadBalancer的多个实例。因为它在第二个示例中受到保护(私有),并且调用者必须使用“GetLoadBalancer”来检查现有实例,所以它只强制执行一个副本。

答案 7 :(得分:0)

嗯,你需要知道使用最重要的事情的顾客在哪里不是特定于上下文的代码 如果要确保单独访问应用程序中对象的方法和属性,可以使用单例。例如,在处理对数据库中表的访问的类中使用。 然而,即使你真的不需要它们,单身人士也会在应用程序中传播

答案 8 :(得分:0)

在您的示例中,只有一个LoadBalancer实例没有任何实际好处。 这使得理解Singleton可能带来的好处变得更加困难。

示例中的LoadBalancer只返回随机服务器。

想象一下一个Loadbalancer类,它跟踪他/她已经返回的服务器,这样LoadBalancer可以以最小的负载返回服务器。

在这种情况下,所有Singletonsuz实例都必须与同一个LoadBalancer交谈:如果他们都只是创建自己的(它不知道其他LoadBalancers做了什么),那么就没有真正的平衡和跟踪返回的服务器将毫无用处。

如果他们都需要与同一个实例交谈,他们可以调用静态GetLoadBalancer然后该单个实例可以返回已经返回最少次数的服务器。

希望这有帮助

答案 9 :(得分:0)

就面试问题而言,这是最着名的设计模式之一。

想象一下G + 4楼的建筑物。每层楼有2个单位,共有8个单位。平均每个单位有4名成员,使用升降机最少有32名成员。

现在考虑一幢8层楼的办公楼。每层楼至少有5个办公室,每个办公室的员工数量从不受限制。

在第一个场景中,我们不需要多个电梯。在第二种情况下,单个电梯是不够的。

现在您已了解单升程的需要与多个升降机的需求。这为我们理解Singleton设计模式奠定了基础。

SINGLETON DESIGN PATTERN

就像前面例子中的电梯一样,Singleton设计模式也用于创建和使用对象的一个​​实例。

为什么呢?因为应用程序不需要多个对象。

如果您看过专业办公室,您会发现一层楼的所有员工共享一台打印机。所有的学生都没有把打印机留在他们的家中,他们宁愿去他们的殖民地的网吧,也可以用他的打印机来满足他们的短暂需求。

所有这一切都是因为这里讨论的对象是昂贵的。从软件的角度来看,当一个对象利用大量资源来执行其操作时,它是“昂贵的”。

所以现在我们需要Singleton设计模式:

1)当应用程序在整个生命周期中不会多次使用该对象时。

2)当应用程序经常需要一个对象时,该对象本身的计算成本非常高。

实施单一设计模式

Singleton设计模式表明: 允许在整个应用程序中仅创建一个类的实例,并提供对它的全局访问点

所以第一部分是指“限制”建设。

从Java早期的面向对象实现开始,我们知道构造函数是在程序执行期间调用的特殊函数,它们可以是私有的。当构造函数变为私有时,类外的任何代码都无法创建其对象。因此,对于Singleton设计模式的实现,我们需要一个“私有构造函数”,我们将使用该构造函数在类中创建一个对象。

我们定义的第二部分讨论了为这个单个对象提供全局句柄。我们将使用公共方法来做到这一点。