MonoState,Singleton或Derived Forms:CRUD应用程序的最佳方法?
我有一个相当大的CRUD WinForm应用程序,有很多对象。 人员,报名,计划,案例注释等 。 应用程序中有超过30种表单,逻辑上分解了UI。 会员,注册,计划,CaseNotes等 。
我试图找出如何在搜索表单上搜索并将该对象传递给下一个请求的表单后如何创建我的Person对象 。 无论那是什么,让我们说人口统计学 。 缺点是我需要Person对象在整个App中可用,并且只能有一个。
现在我有ZERO接触设计模式,但我正在尝试。 我已阅读http://www.switchonthecode.com/tutorials/csharp-tutorial-singleton-pattern和http://www.yoda.arachsys.com/csharp/singleton.html但我想确保我理解正确将此应用于我的情况。
首先,示例说明您正在访问引用 ,对吗? 我错了还是需要访问该值 ?
其次,还有什么我需要做的才能使全球可用吗? 我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个?
谢谢
编辑1
为了澄清,所有对象都是Person的子对象。 此外,正如搜索页面所躲避的那样; 用户可以选择不同的currentPerson。 但他们一次只能与一个人互动。
最后,正如我所说的那样,我是一个婴儿,如果我应该考虑其他事情,请说明一个不同的方法,如果你愿意提供一些解释,为什么,我会非常感激。
编辑2
根据Medicine Man的评论我认为我已经澄清了。
首先,感谢迄今为止贡献的所有人。 其次,我不知道关于设计模式的第一件事,如果在我目前的情况下需要某一个,我当然没有最模糊的。
如果有人有一个更好,更简单,或者,在您看来,更合适的方法将数据对象从FORM传递到FORM到FORM然后请告诉。
最后,我需要一种跟踪信息的方法,因为我的用户从一个地方到另一个地方。 谢谢
您可以使用Singleton模式确保只创建一个实例。
然而, 陪审团仍然 (至少在我看来)是否这是一个好的决定。 SO和其他地方有关于此的大量阅读。
我会从不同的角度来看待这个问题。 我将所有表单都放在构造函数中的Person实例中。 这样,每个表单只会担心它的Person实例。
您可以通过创建一个inheritance自Form的新类来实现此目的,并为您的Person提供字段/属性/构造函数。 然后,任何使用Person的表单都可以从您的新类inheritance。
当然,您必须管理Person对象的创建。 你甚至可以用单身人士做到这一点。 但是,好处是每个表单不必知道如何创建Person或创建Person的人。 这样,如果您选择远离Singleton模式 ,则不必更改对单例实例的所有引用。
编辑:
这里有一些代码来演示这一点。 我花了一段时间才让设计师玩得很开心。 我必须在PersonForm中添加一个空的私有构造函数,以使设计者不会抛出错误。
Program.cs中
static class Program { /// /// The main entry point for the application. /// [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; } }
首先,示例说明您正在访问引用,对吗? 我错了还是需要访问该值?
您正在访问的类是对内存中单个类的引用。 例如,说你的class级是:
public class Person { ... }
如果你有一个单身,你将在内存中保存一个“人”,并在单身人士中共享一个人。 当您访问单个人时,您将使用该引用,这可能是您想要的。 对此人的任何更改都会在任何地方改变它。
其次,还有什么我需要做的才能使全球可用吗? 我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个?
单例用于基本上强制执行每次使用对象时,它都是相同的对象(每次使用都是对内存中单个对象的单独引用)。 你可以在你需要的任何地方抓住单身人士,它就会起作用。
你可以这样做:
public static class PersonController { private static Person _Person; public static Person GetPerson() { if (_Person == null) _Person = new Person(); return _Person; } }
这将确保只有一个人对象。 您将获得对_Person对象的引用,而不是副本,因此任何更改都将是您期望的单个对象。
正如里德所说,单身人士强制要求在整个应用程序中使用相同的对象。 但是,从您的问题来看,它并不像我在整个应用程序中拥有相同的人员类实例,因为有“搜索表单”,它可以让您更改当前选定的人员。
在这种情况下,您的单例可能需要是一个容器类,它包含应用程序的当前上下文以及当前选择的人员。 这可能是这样的:
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);
您也可以在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; } } }
现在您可以初始化单稳态。
CurrentPerson.Person = GetPersonByUserInput();
然后在整个代码中使用CurrentPerson
实例,它们都将访问公共共享状态。
CurrentPerson currentPerson = new CurrentPerson();