使用Factory方法设计模式管理C#中的不同类版本是否是个好主意?

时间:2009-05-15 17:50:44

标签: c# design-patterns refactoring

下面的代码是编写和管理代码的新方式(对我而言)的一个小起点。在我放松几周之前,可能在结束时表示是的,这是一个愚蠢的想法,我认为首先在这里“压力测试”会更好。

所以这就是主意。每当Client(Envoker)类使用Server(提供某些服务的类 - 在下面的示例中称为Controller)时类型的依赖关系,客户端将使用静态方法到名称的“存根”,该存根将是足够通用的,以便此名称不必更改 - 例如CreateDynamicTextBox()或RunProcedureGetDataSet(),并将传递一个配置对象,工厂将提供所请求的Server类版本,因此每次有足够稳定的Server版本时当必须向其添加新功能(或者应该更改它的逻辑)时,将编写新的Server类版本。建议的好处是通过通用方法保存流程并传递“设置”对象。

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

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  

2 个答案:

答案 0 :(得分:1)

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

您的RunMethod()会改变为这样......

ControllerFactory cf = new ControllerFactory();
Controller c = cf.FactoryMethod(objCFSetter);
c.Scream();

你的FactoryMethod()看起来像这样......

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;

答案 1 :(得分:0)

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

using System;


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

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

      ControllerFactory cf = new ControllerFactory ();

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

      Console.WriteLine ( " RUN METHOD 2 WITH CONTROLLER 1 WITH CONFIG 2 " );
      cf.RunMethod ( 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
    }

    public void RunMethod ( CFSetter objCFSetter )
    {
      Controller c = this.FactoryMethod ( objCFSetter );
      c.Scream ();
    } //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;
        default:
          controllerReturn = new Controller1 ();
          break;
      }
      return controllerReturn;
    }

  } //eof class

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


  public class Controller1 : Controller
  {

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

  public class Controller2 : Controller
  {

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

  #endregion Controllers



} //eof namespace