MonoState,Singleton或Derived Forms:CRUD应用程序的最佳方法?

时间:2009-05-05 16:03:24

标签: c# .net winforms design-patterns singleton

我有一个相当大的CRUD WinForm应用程序,它有很多对象。 人员,注册,计划,案例注释等。应用程序中有超过30种表单,逻辑上分解了UI。 会员,注册,计划,CaseNotes等

我想在搜索表单上搜索并将对象传递给下一个后,想办法如何创建 人物对象 要求的表格。无论那是什么,让我们说人口统计。缺点是我需要在整个应用程序中使用Person对象,并且只能有一个。

现在我对设计模式有零接触,但我正在尝试。我已阅读http://www.switchonthecode.com/tutorials/csharp-tutorial-singleton-patternhttp://www.yoda.arachsys.com/csharp/singleton.html,但我想确保我正确理解如何将此应用于我的情况。

首先,示例说明您正在访问引用,对吗?我错了还是需要访问

其次,还有什么我需要做的才能使全球可用吗?我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个吗?

由于

编辑1

澄清一下,所有对象都是Person的子对象。此外,正如搜索页面所躲避的那样;用户可以选择不同的currentPerson。但他们一次只能与 ONE 人进行互动。

最后,正如我所说,我是一个婴儿,如果我应该考虑其他事情,请说明一个不同的方法,如果你愿意提供一些解释,为什么,我会非常感激。

编辑2

基于Medicine Man的评论我认为我已经澄清了。

首先,感谢迄今为止做出贡献的所有人。 其次,我不知道关于设计模式的第一件事,如果在我目前的情况下需要某个模型,我肯定没有最模糊的。

如果某人有一个更好,更简单,或者在您看来,更合适的方法将数据对象从FORM传递到FORM到FORM,那么请告诉。

最后,我需要一种跟踪信息的方法,因为我的用户从一个地方到另一个地方。 谢谢


5 个答案:

答案 0 :(得分:2)

  

首先,示例说明您正在访问引用,对吗?我错了还是需要访问该值?

您正在访问的类是对内存中单个类的引用。例如,假设您的班级是:

public class Person { ... }

如果你有一个单身,你将在内存中保存一个“人物”,并在单身人士中共享一个人。当您访问单个人时,您将使用该引用,这可能是您想要的。对此人的任何更改都会在任何地方进行更改。

  

其次,还有什么我需要做的才能使全球可用吗?我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个吗?

Singletons基本上强制执行每次使用对象时,它都是相同的对象(每次使用都是对内存中单个对象的单独引用)。你可以在你需要的任何地方抓住单身人士,它只会起作用。

答案 1 :(得分:1)

你可以这样做:

public static class PersonController
{
    private static Person _Person;

    public static Person GetPerson()
    {
        if (_Person == null)
            _Person = new Person();

        return _Person;
    }
}

这将确保只有一个人物对象。您将获得对_Person对象的引用,而不是副本,因此任何更改都将是您期望的单个对象。

答案 2 :(得分:1)

您可以使用Singleton模式确保只创建一个实例。

然而,the jury is still out(至少在我看来)是否这是一个好的决定。 SO和其他地方有很多关于此的阅读。

我会从不同的角度来看待这个问题。我将所有表单都放在构造函数中的Person实例中。这样,每个表单只会担心它的Person实例。

您可以通过创建一个继承自Form的新类来实现此目的,并为您的Person提供字段/属性/构造函数。然后,任何使用Person的表单都可以从您的新类继承。

当然,您必须管理Person对象的创建。你甚至可以用单身人士来做这件事。但是,好处是每个表单不必知道如何创建Person或创建Person的人。这样,如果您选择move away from the Singleton pattern,则不必更改对单例实例的所有引用。

修改

这里有一些代码来证明这一点。我花了一段时间才让设计师玩得很开心。我必须在PersonForm中添加一个空的私有构造函数,以使设计者不会抛出错误。

Program.cs的

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyDerivedForm(new Person { Name = "Hello World!" }));
        }
    }

Person.cs

public class Person
{
    public virtual string Name { get; set; }
}

PersonForm.cs

using System;
using System.Windows.Forms;

public class PersonForm : Form
{
    private readonly Person myPerson;

    protected virtual Person MyPerson 
    {
        get
        {
            return this.myPerson;
        }
    }

    private PersonForm()
    {
    }

    public PersonForm(Person person)
    {
        this.myPerson = person;
    }
}

MyDerivedForm.cs(添加名为label1的标签)

public partial class MyDerivedForm : SingletonMadness.PersonForm
{
    public MyDerivedForm(Person person)
        : base(person)
    {
        InitializeComponent();
    }

    private void MyDerivedForm_Load(object sender, EventArgs e)
    {
        label1.Text = this.MyPerson.Name;
    }
}

答案 3 :(得分:1)

正如里德所说,单身人士强制要求在整个应用程序中使用相同的对象。但是,从您的问题来看,它并不像我在整个应用程序中拥有相同的人员类实例,因为有“搜索表单”,它可以让您更改当前选定的人员。

在这种情况下,您的单例可能需要是一个容器类,它包含应用程序的当前上下文以及当前选择的人员。这可能是这样的:

public class Context
{
   private static Context _instance;

   public static Context Instance
   {
       get
       {
           if (_instance == null)
           {
               _instance = new Context();
           }
           return _instance;
       }
   }

   public Person CurrentlySelectedPerson { get; set; }

   private Context() { }
}

(注意,这不是一个理想的单例模式,因为它不是线程安全的......)

然后搜索表单会将当前选定的人员设置为:

Context.Instance.CurrentlySelectedPerson = personSelectedInForm;

人口统计可以像以下一样使用它:

//Get the demographics for the current person
ShowDemographics(Context.Instance.CurrentlySelectedPerson);

答案 4 :(得分:0)

你也可以在你的Person类中使用monostate模式。

public class Person
{
    public Guid Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

Person构建一个monostate对象。

public class CurrentPerson
{
    public static Person Person { get; set; }

    public Guid Id
    {
        get { return CurrentPerson.Person.Id; }
        set { CurrentPerson.Person.Id = value; }
    }

    public String FirstName
    {
        get { return CurrentPerson.Person.FirstName; }
        set { CurrentPerson.Person.FirstName = value; }
    }

    public String LastName
    {
        get { return CurrentPerson.Person.LastName; }
        set { CurrentPerson.Person.LastName = value; }
    }
}

现在你可以初始化monostate。

CurrentPerson.Person = GetPersonByUserInput();

然后在整个代码中使用CurrentPerson个实例,它们都将访问一个共同的共享状态。

CurrentPerson currentPerson = new CurrentPerson();