实现策略模式而不是几个if语句

时间:2015-12-28 16:45:14

标签: c# if-statement design-patterns

我有很多if statements的方法,其中我根据员工位置过滤SharePoint list。结果是query string,它作为参数传递给另一个方法QuerySPList

 public List<Phone> GetListOfPhones(Employee emp)
 {
    List<Phone> records = new List<Phone>();
    string query = string.Empty;

    if (emp.Positions.Count == 1 && emp.Positions[0] == "Regular")
    {
       query = "";// some querystring                              
    }


    if (emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector")
    {   
       query = "";// some querystring    
    }

    if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
    {
        query = "";// some querystring 
    }              

    if (emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector"))
    {

      query = "";// some querystring 

     }

   var rawItems = QuerySPList(query);

   foreach (SPListItem item in rawItems)
   {
        //business logic 
   }
   return records;
}}

我已经了解到,通过实施strategy pattern,我们可以避免使用大量if的混乱代码,但是,我不熟悉开发和设计模式所以我对这个问题一点帮助,所以如果有人可以指导我应该做什么并给我建议,请随时回答我的问题。我有想法,但我认为我走向了错误的方向。 想法是创建interface IRoleHandler,而不是将其实现为3 classes,例如RoleAdmin ,RoleRegular,RoleOfficeDirector。这样的事情:

public interface IRoleHandler<T>
{
    string handleRole(T obj);
}
public class RoleAdmin:IRoleHandler<Employee>
{

    public string handleRole(Employee emp)
    {
        if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
        {
            //return some string query
        }

    }
}

然后想法是创建dictionary,类似这样:

Dictionary<string, IRoleHandler<Employee>> strategyHandlers = new Dictionary<string, IRoleHandler<Employee>>();
        strategyHandlers.Add("Admin", new RoleAdmin());
        strategyHandlers.Add("Regular", new RoleRegularUser());

4 个答案:

答案 0 :(得分:4)

首先,我认为你需要更少关注内部结构&#39;战略模式,更关注其设计目标/用途。

https://en.wikipedia.org/wiki/Strategy_pattern

  

策略模式(也称为策略模式)是一种软件设计模式,可以在运行时选择算法的行为。战略模式

     
      
  • 定义了一系列算法,
  •   
  • 封装每个算法,
  •   
  • 使算法在该系列中可互换。
  •   

对我来说,看起来你真的打算&#34;创建&#34;一个字符串,基于一些输入值。

因此,您可能希望使用Creational patterns

之一

我的建议可能是工厂模式,或者可能是Builder模式。 (两者都在创作模式链接中链接)

private string BuildQueryByEmployee(Employee emp) {
    // create your builder
    EmployeeQueryBuilder mBuilder = new EmployeeQueryBuilder ();
    // add # of positions
    mBuilder.addPositionCount(emp.Positions.Count);
    // add each position
    for (int i =0 ; i < emp.Positions.Count; i++ ){
        mBuilder.addPosition(emp.Positions[i]);
    }
    // 'build' your query. 
    // and return the query as a string.
    return mBuilder.buildQuery(); 
}

然后在您的EmployeeQueryBuilder类中,您可以处理基于位置数及其含义构建查询的复杂性。

其次,以下是一些可能对您有用的链接。

  • https://en.wikipedia.org/wiki/Software_design_pattern(一般光盘模式)
  • https://en.wikipedia.org/wiki/Design_Patterns(&#34; Gang of Four&#34;书,基本上是关于设计模式的第一本书,值得阅读几次,并且手动编写每个模式几次,直到你是对他们感到满意,如果你以前没有使用过这种模式,这将使你的编码能力提高2~3倍。本书中的例子有点过时,因为它的激励因素是编写文本编辑器......但是仍然是一个经典的&#39;,非常值得了解)
  • http://www.cs.wustl.edu/~schmidt/POSA/POSA2/(关于必须处理并发的模式的第一本书之一)(POSA =面向模式的软件架构)(现在可能有点过头了,但很高兴知道&#39;一般而言)

答案 1 :(得分:3)

我不认为战略模式是你想要的。我只是重构你的代码以将ifs提取到另一种方法。

public List<Phone> GetListOfPhones(Employee emp)
{
   List<Phone> records = new List<Phone>();
   string query = BuildQueryByEmployeePosition(emp);

   var rawItems = QuerySPList(query);

   foreach (SPListItem item in rawItems)
   {
        //business logic 
   }
   return records;
}

private string BuildQueryByEmployeePosition(Employee emp) 
{
    if (emp.Positions.Count == 1 && emp.Positions[0] == "Regular")
        return "";// some querystring    

    if (emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector")
        return "";// some querystring    

    if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
        return "";// some querystring    

    if (emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector"))
        return "";// some querystring    

    return ""; // some default query
}

这是对战略模式的一个很好的解释link (有一个排序算法的真实例子)。

很高兴看到你是编程新手并正在研究模式,但是 注意:在不需要它们时使用它们是一种反模式。

答案 2 :(得分:0)

在我的选择中,最好使用STATE PATTERN COMPOSITE public abstract class Position { public abstract List<int> ListOfPhones(); } public class Employer { public virtual IList<Position> CurrentPositions { get; set; } } public class Manager : Employer { public Manager(List<Position> positions) { this.CurrentPositions = positions; } public IEnumerable<int> GetNumbers() { foreach (Position position in this.CurrentPositions) foreach (var number in position.ListOfPhones()) yield return number; } }

示例:

<div class="admonition warning"> ...

上面的代码不完整,只是为了获得ideia。

答案 3 :(得分:0)

我同意mawalker,你不需要策略模式,因为你对所有情况都有相同的行为。你需要的是某种创作模式。我会使用构建器责任链模式重构您的代码。

1)实现基类:

public abstract class EmployeeHandler
{
  private readonly EmployeeHandler _nextHandler;

  protected EmployeeHandler(EmployeeHandler nextHandler)
  {
    _nextHandler = nextHandler;
  }

  public string BuildQuery(Employee emp)
  {
    if (CanHandle(emp))
    {
        return GetQuery(emp);
    }

    if (_nextHandler == null)
    {
        return string.Empty;
    }

    return _nextHandler.BuildQuery(emp);
  }

  protected abstract string GetQuery(Employee emp);

  protected abstract bool CanHandle(Employee emp);
}

2)定义具体实施:

public class RegularEmployeeHandler : EmployeeHandler
{
  public RegularEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
  }

  protected override bool CanHandle(Employee emp)
  {
    return emp.Positions.Count == 1 && emp.Positions[0] == "Regular";
  }

  protected override string GetQuery(Employee emp)
  {
    return "some regular query";
  }
}

public class OfficeDirectorEmployeeHandler : EmployeeHandler
{
  public OfficeDirectorEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
  }

  protected override bool CanHandle(Employee emp)
  {
    return emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector";
  }

  protected override string GetQuery(Employee emp)
  {
    return "some office director query"; 
  }
}

public class AdminEmployeeHandler : EmployeeHandler
{
  public AdminEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
  }

  protected override bool CanHandle(Employee emp)
  {
    return emp.Positions.Count == 1 && emp.Positions[0] == "Admin";
  }

  protected override string GetQuery(Employee emp)
  {
    return "some admin query"; 
  } 
}

public class RegularAndOfficeDirectorEmployeeHandler : EmployeeHandler
{
  public RegularAndOfficeDirectorEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
  }

  protected override string GetQuery(Employee emp)
  {
    return "some regular and director query";
  }

  protected override bool CanHandle(Employee emp)
  {
    return emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector");
  }
}

3)最后你的主课将改变如下:

public class YouMainClass
{

  private readonly EmployeeHandler _firstHandler;

  public YouMainClass()
  {
    var regularHandler = new RegularEmployeeHandler(null);
    var officeDirectorHandler = new OfficeDirectorEmployeeHandler(regularHandler);
    var adminHandler = new AdminEmployeeHandler(officeDirectorHandler);
    _firstHandler = new RegularAndOfficeDirectorEmployeeHandler(adminHandler);
  }

  public List<Phone> GetListOfPhones(Employee emp, IQueryBuilder queryBuilder)
  {
    List<Phone> records = new List<Phone>();
    string query = _firstHandler.BuildQuery(emp);

    var rawItems = QuerySPList(query);

    foreach (SPListItem item in rawItems)
    {
      //business logic 
    }

    return records;
  }
}