转换为设计界面

Convert to Design Interface

我们目前有一个登录结构,但我们想用另一个结构替换它。但是,我们希望保留两者,以防新结构不起作用。

我们现在拥有的

PasswordControl.cs

public class PasswordControl
{
   public passwordControl()
   {
      // code here
   }
   public doLogin()
   {
      // code here
   }
}

Main.cs

provide void btnLogin()
{
  passwordControl pw = new passwordControl();
  pw.doLogin();
}

我们想将其转换为设计结构

IloginManager.cs

Interface ILoginManager 
{
  void dologin();
}

所以我们也可以添加第二个结构

PasswordControl2.cs

public class PasswordControl2
{
   public passwordControl()
   {
      // code here
   }
   public doLogin()
   {
      // code here
   }
}

我需要如何修改 Main.cs 中的代码才能利用这个新设计?

要使用一个接口,首先要从它派生每个实现。然后在客户端代码中,将其存储为接口类型:

ILoginManager login = new PasswordControl();
//Do stuff with login

如果您决定使用其他实现,只需切换您实例化的内容即可:

ILoginManager login = new PasswordControl2();
//Do stuff with login

后面的代码还是可以的,因为你还是通过ILoginManager接口访问class。在生产代码中,接口通常只会由调用堆栈上层的某些 class 或 DI 容器传递给您。

您想在运行时在同一合约的不同实现之间切换,这就是您想要使用接口的原因。接口是一个契约:如果一些 class 实现了一些接口,它提供在该接口中定义的服务。如果任何 class 实现 ILoginManager 接口,则 class 包含 public doLogin() 方法。

public interface ILoginManager 
{
    void doLogin();
}

public class PasswordControl : ILoginManager
{
   public PasswordControl()
   {
      // code here
   }
   public void doLogin()
   {
      // code here
      Debug.WriteLine("PasswordControl.doLogin()");
   }
}

public class PasswordControl2 : ILoginManager
{
   public PasswordControl2()
   {
      // code here
   }
   public void doLogin()
   {
      // code here
      Debug.WriteLine("PasswordControl2.doLogin()");
   }
}

您说要在创建表单时确定 ILoginManager 实现。例如,您的表单可以从配置文件中读取选择。这意味着当你想改变合约实现时,你不必重新编译你的程序,你只需要更改配置文件并重新启动程序。

您的表单可以具有以下构造函数:

public class MyForm
{
   ILoginManager _loginManager;

   public MyForm()
   {
      // let's assume read value is 2
      int choice = ReadChoiceFromConfigFile();

      if (choice == 1)
      {
         _loginManager = new PasswordControl();
      }
      else
      {
         _loginManager = new PasswordControl2();
      }
   }
}

因此,当您按下“登录”按钮时,将使用正确的实现方式:

private void btnLogin()
{
   // in our case PasswordControl2.doLogin() is called as _choice has been set to 2
   _loginManager.doLogin();
}

更好的是,如果创建适当的 LoginManager 的责任将从 MyForm 中取出,因为表单不应该知道它的细节 - 它想要得到的只是一个实现 ILoginManager 但它不应该关心它是如何制作的。因此,理想情况下,您将在创建表单之前创建 ILoginManager 实现程序,然后将其作为表单的依赖项传递(您将 "inject" 它,例如通过构造函数;阅读 Dependency injection) .看起来像这样:

public class MyForm
{
   ILoginManager _loginManager;

   public MyForm(ILoginManager loginManager)
   {
      if (loginManager == null)
      { 
         throw new ArgumentNullException("loginManager");
      }

      _loginManager = loginManager;
   }
} 

public static void Main()
{
   ILoginManager loginManager = CreateLoginManager();
   Application.Run(new MyForm(loginManager));
}

// factory method - it creates desired instance which implements given interface
public static CreateLoginManager()
{
   ILoginManager loginManager = null;

   // let's assume read value is 2
   int choice = ReadChoiceFromConfigFile();

   if (choice == 1)
   {
       loginManager = new PasswordControl();
   }
   else
   {
       loginManager = new PasswordControl2();
   }

   return loginManager;
}