Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中使用工厂方法设计模式来管理不同的类版本是一个好主意吗?_C#_Design Patterns_Refactoring - Fatal编程技术网

在C#中使用工厂方法设计模式来管理不同的类版本是一个好主意吗?

在C#中使用工厂方法设计模式来管理不同的类版本是一个好主意吗?,c#,design-patterns,refactoring,C#,Design Patterns,Refactoring,下面的代码是(对我来说)编写和管理代码的新方法的一个小起点。在我放松几周并可能在最后说是的,这是个愚蠢的想法之前,我认为最好先在这里进行“压力测试” 这就是我的想法。每当客户机(Envoker)类使用服务器(提供某些服务的类-在下面的示例中称为控制器)时,存在该类型的依赖项时,客户机将使用一个静态方法来创建一个名为“stub”的“stub”,该名称将具有足够的通用性,以便该名称不必更改-例如CreateDynamicTextBox()或RunProcedureGetDataSet(),并将传递一

下面的代码是(对我来说)编写和管理代码的新方法的一个小起点。在我放松几周并可能在最后说是的,这是个愚蠢的想法之前,我认为最好先在这里进行“压力测试”

这就是我的想法。每当客户机(Envoker)类使用服务器(提供某些服务的类-在下面的示例中称为控制器)时,存在该类型的依赖项时,客户机将使用一个静态方法来创建一个名为“stub”的“stub”,该名称将具有足够的通用性,以便该名称不必更改-例如CreateDynamicTextBox()或RunProcedureGetDataSet(),并将传递一个配置对象,工厂将根据该配置对象提供所请求的服务器类版本,因此每当有足够稳定的服务器版本时,必须向其添加新功能(或应更改其逻辑)并写入新的服务器类版本。建议的好处是通过通用方法和传递“设置”对象来保持流

这是个坏主意吗?!如果是,为什么?这种方法有什么好处吗

using System;


namespace ControllerFactory
{
  class ClientEnvoker
  {
    static void Main ( string[] args )
    {

      Console.WriteLine ( " START " );
      ClientEnvoker objClientEnvoker = new ClientEnvoker ();

      ControllerFactory objControllerFactory = new ControllerFactory ();

      Console.WriteLine ( " RUN METHOD 1 WITH CONTROLLER 1 WITH CONFIG 1 " );
      objControllerFactory.GenericMethodName ( ControllerFactory.CFSetter.First );

      Console.WriteLine ( " RUN METHOD 2 WITH CONTROLLER 2 WITH CONFIG 2 " );
      objControllerFactory.GenericMethodName ( ControllerFactory.CFSetter.Second );

      Console.WriteLine ( " RUN METHOD 3 WITH CONTROLLER 3 WITH CONFIG 3 " );
      objControllerFactory.GenericMethodName ( ControllerFactory.CFSetter.Second );

      Console.WriteLine ( " END HIT A KEY TO EXIT " );
      Console.ReadLine ();

    } //eof method 

  } //eof class 


  class ControllerFactory
  {
    public enum CFSetter : int
    {
      First = 1,
      Second = 2 , 
      Third = 3
    }

    public void GenericMethodName ( CFSetter objCFSetter )
    {
      Controller c = this.FactoryMethod ( objCFSetter );
      c.ConcreteMethod ();
    } //eof method 

    public Controller FactoryMethod ( CFSetter objCFSetter )
    {
      Controller controllerReturn = null;
      switch (objCFSetter)
      {
        case CFSetter.First:
          controllerReturn = new Controller1 ();
          break;
        case CFSetter.Second:
          controllerReturn = new Controller2 ();
          break;
        case CFSetter.Third:
          controllerReturn = new Controller3 ();
          break;
        default:
          controllerReturn = new Controller1 ();
          break;
      }
      return controllerReturn;
    }

  } //eof class

  #region Controllers
  public abstract class Controller
  {
    public abstract void ConcreteMethod ();
  }


  public class Controller1 : Controller
  {

    public override void ConcreteMethod ()
    {
      Console.WriteLine ( "Controller1 screams according to version 1 logic" );
    }
  } //eof class 

  public class Controller2 : Controller
  {

    public override void ConcreteMethod ()
    {
      Console.WriteLine ( "Controller2 screams according to version 2 logic" );
    }
  } //eof class 


  public class Controller3 : Controller
  {

    public override void ConcreteMethod ()
    {
      Console.WriteLine ( "Controller3 screams according to version 3 logic" );
    }
  } //eof class 

  #endregion Controllers



} //eof namespace  

对于这种情况,可以使用工厂模式。但是,
FactoryMethod()
应该是逻辑所在的位置,以选择实例化哪个类。另外,如果
FactoryMethod()
返回类型
Controller
,则没有理由强制转换返回的对象

您的
RunMethod()
将更改为以下内容

ControllerFactory cf = new ControllerFactory();
Controller c = cf.FactoryMethod(objCFSetter);
c.Scream();
Controller controllerReturn = null;
switch (objCFSetter) {
    case CFSetter.First:
      controllerReturn = new Controller1();
      break;
    case CFSetter.Second:  
      controllerReturn = new Controller2();
      break;
    default:
      controllerReturn = new Controller1();
      break;
}
return controllerReturn;
您的
FactoryMethod()
将如下所示

ControllerFactory cf = new ControllerFactory();
Controller c = cf.FactoryMethod(objCFSetter);
c.Scream();
Controller controllerReturn = null;
switch (objCFSetter) {
    case CFSetter.First:
      controllerReturn = new Controller1();
      break;
    case CFSetter.Second:  
      controllerReturn = new Controller2();
      break;
    default:
      controllerReturn = new Controller1();
      break;
}
return controllerReturn;

谢谢你,乔恩。我想你指的是我在下面发布的实现(当然不会接受它作为答案!)。是的,它似乎比我上面使用奇怪的静态方法编写的代码更简单。不过,这是相同的“功能”吗?如果这种类型的“热插拔”工作多久,或者在哪种情况下可以使用它(我在考虑动态控件生成和数据库提供程序的动态选择)


谢谢你,乔恩。我不得不粘贴你想作为答案的代码(注释中也应该有语法突出显示;(至少有1000行空格;)好吧,我确实不小心遗漏了CFSetter。switch语句中的第三个…但是是的,这是相同的功能。基本上,Main()不知道将实例化哪种类型的控制器(这也不重要)。这是ControllerFactory的目的。您可以继续添加从Controller派生的不同类来修改cream()功能,Main()中的代码将永远不需要更改。您列出的情况对于使用这种类型的模式非常有意义。