OCP-开闭原则

发布于:2023-01-13 ⋅ 阅读:(148) ⋅ 点赞:(0)

开闭原则

对扩展开放,对修改关闭

  public enum Color { Red,Green,Blue}
  public enum Size { Small, Medium, Large, Yuge }
  public class Product
  {
      public string Name;
      public Color Color;
      public Size Size;

      public Product(string name, Color color,Size size)
      {
          if(name==null)
          {
              throw new ArgumentNullException(paramName: nameof(name));
          }
          Name = name;
          Color = color;
          Size = size;
      }
  }

产品过滤器设置 违反开闭原则

    public class ProductFilter
  {
      public  IEnumerable<Product> FilterBySize(IEnumerable<Product> products,Size size)
      {
          foreach(var p in products)
          {
              if (p.Size == size)
                  yield return p;
          }
      }

      public  IEnumerable<Product> FilterByColor(IEnumerable<Product> products, Color color)
      {
          foreach (var p in products)
          {
              if (p.Color == color)
                  yield return p;
          }
      }


      public IEnumerable<Product> FilterBySizeAndColor(IEnumerable<Product> products, Size size,Color color)
      {
          foreach (var p in products)
          {
              if (p.Size == size && p.Color == color)
                  yield return p;
          }
      }
  }

重构后

  public interface ISpecification<T>
  {
      bool IsSatisfied(T t);
  }


  public interface IFilter<T>
  {
      IEnumerable<T> Filter(IEnumerable<T> items, ISpecification<T> spec);
  }

  public class ColorSpecification : ISpecification<Product>
  {
      private Color color;
      public ColorSpecification(Color color)
      {
          this.color = color;
      }
      public bool IsSatisfied(Product t)
      {
          return t.Color==color;
      }
  }
  public class SizeSpecification : ISpecification<Product>
  {
      private Size size;
      public SizeSpecification(Size size)
      {
          this.size = size;
      }
      public bool IsSatisfied(Product t)
      {
          return t.Size == size;
      }
  }

  public class AndSpecification<T> : ISpecification<T>
  {
      private ISpecification<T>  first,second;
      public AndSpecification(ISpecification<T> first, ISpecification<T> second)
      {
          this.first = first?? throw new ArgumentNullException(paramName: nameof(first));
          this.second = second ?? throw new ArgumentNullException(paramName: nameof(second));
      }
      public bool IsSatisfied(T t)
      {
          return first.IsSatisfied(t) && second.IsSatisfied(t);
      }
  }


  public class BetterFilter : IFilter<Product>
  {
      public IEnumerable<Product> Filter(IEnumerable<Product> items, ISpecification<Product> spec)
      {
          foreach(var i in items)
          {
              if (spec.IsSatisfied(i))
                  yield return i;
          }
      }
  }

测试示例

          var apple = new Product("Apple", Color.Green, Size.Small);
          var tree = new Product("Tree", Color.Green, Size.Large);
          var house = new Product("House", Color.Blue, Size.Large);

          Product[] products = { apple, tree, house };

          var pf = new ProductFilter();
          Console.WriteLine("Green products (old):");
          foreach(var p in pf.FilterByColor(products,Color.Green))
          {
              Console.WriteLine($" -  {p.Name} is green");
          }

          var bf = new BetterFilter();
          Console.WriteLine("Green products (new ):");
          foreach (var p in bf.Filter(products,new ColorSpecification( Color.Green)))
          {
              Console.WriteLine($" -  {p.Name} is green");
          }

          foreach (var p in bf.Filter(
              products, 
              new AndSpecification<Product>(
             new ColorSpecification(Color.Green),
             new SizeSpecification(Size.Large)
              )))
          {
              Console.WriteLine($" -  {p.Name} is big and blue");
          }
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到