什么是一个好的设计模式,以避免在主窗体顶部使用全局变量?

Mic*_*ton 4 c# design-patterns

每当我与有经验的程序员交谈时,他们都会谈论由于调试或安全漏洞导致全局变量是一种不好的做法.我有一个简单的字符串列表,我想从一个文本文件加载,并访问我的表单中的不同方法.以前,我只是在我的表单类的顶部初始化所述变量,并在方法中使用它.我总是尽力减少这种做法,只在我真正需要它们时才初始化这些变量.这样做是不好的做法,还是更有经验的程序员也这样做?是否有标准的设计模式方法,因此您不必在表单顶部使用"全局变量"?

Mat*_*zer 6

当你在谈论C#并且它是一种完全面向对象的编程语言时,没有办法声明全局变量.

在像C#这样的OOP语言中,一个不好的做法是使用静态类来模拟全局变量:

public static class Global
{
     public static string Value1 { get; set; }
     public static int Value2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

...以后从其他类中获取或设置这些值.当然,这是一种不好的做法,因为状态应由特定且有意义的对象来控制.

通常,在完美/理想的OOP解决方案中,您应该使用构造函数将这些值从类传递给类:

public class X
{
    public int Value1 { get; set; }

    public void DoStuff()
    {
        Y y = new Y(this);
        y.DoChildStuff();
    }
}

public class Y
{
    public class Y(X parent)
    {
         Parent = parent;
    }

    public X Parent { get; }

    public void DoChildStuff()
    {
         // Do some stuff with Parent
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以传递为某些方法提供参数的状态:

public class Y
{    
    public void DoChildStuff(X parent)
    {
         // Do some stuff with "parent"
    }
}
Run Code Online (Sandbox Code Playgroud)

由于您使用引用类型传递状态,因此如果链中的任何方法决定Parent.Value1使用其他值更改,则持有对同一X对象的引用的所有对象都将获得新的X.Value1.

有些人可能认为我们通常会构建配置对象,这些对象拥有其他任意对象访问的大量属性,对吧?顺便说一句,配置本身就是一个概念,不是吗?我们通常使用组合对配置值进行分类:

public class ApplicationConfiguration
{
     public DatabaseConfiguration Database { get; } = new DatabaseConfiguration();
     public StorageConfiguration Storage { get; } = new StorageConfiguration();
}

public class DatabaseConfiguration
{
     public string ConnectionString { get; set; }
}

public class StorageConfiguration
{
     public string TemporalFileDirectoryPath { get; set; }
     public string BinaryDirectoryPath { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以稍后我们 在任何需要的地方注入应用程序配置:

// Please note that it's a VERY hypothetical example, don't take
// it as an actual advise on how to implement a data mapper!!
public class DataMapper
{
     public DataMapper(ApplicationConfiguration appConfig)
     {
           AppConfig = appConfig;
     }

     public ApplicationConfiguration AppConfig { get; }
     private IDbConnection Connection { get; }

     public void Connect()
     {
           // We access the configured connection string
           // from the application configuration object
           Connection = new SqlConnection(AppConfig.Database.ConnectionString);
           Connection.Open();
     }
}
Run Code Online (Sandbox Code Playgroud)

总而言之,由于我喜欢比较现实世界和编程用例,想象一下你永远不会打扫你的房间,你会用一个盒子来存储你有一天可能需要的每一个工具.有一天你需要从整个盒子里拿一把螺丝刀,而且你知道它在里面...但是你需要把盒子里的所有东西扔到地上然后弄清楚它们之前找到无价的螺丝刀来完成一些家庭任务.

或者想象一下,你已经购买了一个工具箱来按顺序存放你的工具,一旦你需要一把螺丝刀,你就知道它在工具箱和你存放螺丝刀的部分.

你知道第二种方法是最安心的.也就是说,当您开发软件时,您需要设计出对设计友好的体系结构,而不是将大量不相关的数据和行为协同工作.