转换为设计界面
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;
}
我们目前有一个登录结构,但我们想用另一个结构替换它。但是,我们希望保留两者,以防新结构不起作用。
我们现在拥有的
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;
}