三种工厂模式与策略模式

2,809 阅读5分钟

简单工厂模式

实现一个功能,假设现在有跑车,越野车,商务车,想要开什么车的时候随时能发车。

抽象汽车

    /// <summary>
    /// 抽象汽车
    /// </summary>
    public interface ICar
    {
        void Run();
    }

汽车类型枚举

    public enum CarType
    {
        SportCarType = 0,
        JeepCarType = 1,
        BusinessCarType = 2
    }

各种类型汽车实现

    /// <summary>
    /// 跑车
    /// </summary>
    public class SportCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("跑车发车");
        }
    }

    /// <summary>
    /// 越野车
    /// </summary>
    public class JeepCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("越野车发车");
        }
    }

    /// <summary>
    /// 商务车
    /// </summary>
    public class  BusinessCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("商务车发车");
        }
    }

工厂类

    public class Factory
    {
        public ICar GetCar(CarType carType)
        {
            switch (carType)
            {
                case CarType.SportCarType:
                    return new SportCar();
                case CarType.JeepCarType:
                    return new JeepCar();
                case CarType.BusinessCarType:
                    return new BusinessCar();
                default:
                    throw new Exception("翻车!");
            }
        }
    }

调用

    class Program
    {
        static void Main(string[] args)
        {
            ICar car;
            Factory factory = new Factory();
            Console.WriteLine("老司机跑车发车");
            car = factory.GetCar(CarType.SportCarType);
            car.Run();
        }
    }

优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。当要新增一个汽车类型的时候,只要实现指定接口就可以,符合开发关闭原则。

缺点:很明显工厂类集中了所有实例的创建逻辑,当要加车类型的时候需要修改工厂类源码,违背开放关闭原则。

工厂方法模式

简单工厂的例子中,可以把工厂类看成汽车仓库,里面是已经生产好的汽车,想要什么类型的汽车,只要是已经生产好的就可以得到。

现在我们想要开大卡车,但是仓库里没有,怎么办呢?

我们换个高级点的仓库,一个可以生产大卡车的仓库,而且有很多这种仓库,每个仓库生产指定类型的汽车。

抽象高级仓库

    public interface IFactory
    {
        ICar CreateCar();
    }

抽象汽车

    /// <summary>
    /// 抽象汽车
    /// </summary>
    public interface ICar
    {
        void Run();
    }

各种类型汽车实现

    /// <summary>
    /// 跑车
    /// </summary>
    public class SportCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("跑车发车");
        }
    }

    /// <summary>
    /// 越野车
    /// </summary>
    public class JeepCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("越野车发车");
        }
    }

    /// <summary>
    /// 商务车
    /// </summary>
    public class  BusinessCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("商务车发车");
        }
    }

    /// <summary>
    /// 卡车
    /// </summary>
    public class  Truck : ICar
    {
        public void Run()
        {
            Console.WriteLine("卡车发车");
        }
    }

具体高级仓库

    /// <summary>
    ///  跑车仓库
    /// </summary>
    public class SportFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new SportCar();
        }
    }

    /// <summary>
    ///  越野车仓库
    /// </summary>
    public class JeepFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new JeepCar();
        }
    }

    /// <summary>
    ///  商务车仓库
    /// </summary>
    public class BusinessCarFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new BusinessCarCar();
        }
    }
    /// <summary>
    ///  卡车仓库
    /// </summary>
    public class TruckFactory : IFactory
    {
        public ICar CreateCar()
        {
            return new Truck();
        }
    }

调用

class Program
    {
        static void Main(string[] args)
        {
            IFactory factory = new TruckFactory();
            ICar truck = factory.CreateCar();
            truck.Run();
        }
    }

通过工厂方法模式,只要实现ICar接口,就可以创建一种新的类型的汽车,然后通过实现IFactory接口,创建一个可以生产这种新类型汽车的工厂。使用的时候,new一个新的工厂,就可以生产新类型的车了。

抽象工厂模式

汽车不仅有不同类型了,还有不同品牌的,比如跑车类型,有劳斯莱斯的,有宾利的,有迈凯伦的。。。假设,现在我们想开劳斯莱斯的跑车,我们的仓库怎么给我们车呢?或者说我们怎么从仓库把我们想要开的车拿到呢?工厂方法模式中我们通过实现仓库的多态,创建了很多可以具体生产某种类型汽车的工厂。

现在通过实现汽车类型多态,具体的仓库(工厂)可以生产特定品牌不同类型的汽车,比如某个车库(工厂)可以生产宾利的跑车,商务车,越野车,卡车(滑稽)。

抽象汽车

    /// <summary>
    /// 抽象汽车
    /// </summary>
    public interface ICar
    {
        void Run();
    }

抽象汽车类型

    /// <summary>
    /// 抽象跑车类型
    /// </summary>
    public interface ISportCar:ICar
    {
         //具体品牌名称
         string Name{get;}
    }
    //越野车,商务车类型类似(而且这里用抽象类更加合适)

具体品牌的汽车类型

    /// <summary>
    /// 劳斯莱斯跑车
    /// </summary>
    public class RollsRoyceSportCar:ISportCar
    {
         //具体品牌名称
         public string Name
         {
           get{return "劳斯莱斯";}
         }
         public void Run(){
            Console.WriteLine(this.Name+"跑车发车");
         }


    }
    /// <summary>
    /// 宾利跑车
    /// </summary>
    public class BentleySportCar:ISportCar
    {
         //具体品牌名称
         public string Name
         {
           get{return "宾利";}
         }
         public void Run(){
            Console.WriteLine(this.Name+"跑车发车");
         }

    }
    ...
    //越野车,商务车类型类似

抽象车库(工厂)

之前每个生产具体类型汽车的仓库(工厂)只要返回具体类型(实现ICar的汽车类)的汽车就可以,但是现在返回特定品牌的具体类型的汽车

    public interface IFactory
    {
        ISportCar CreateSportCar();

        IJeepCar CreateJeepCar();

        IJeepCar CreateJeepCar();
    }

具体工厂

  /// <summary>
  ///  宾利工厂
  /// </summary>
  public class BentleyFactory : IFactory
  {
      public ISportCar CreateSportCar()
      {
          return new BentleySportCar();
      }

      public IJeepCar CreateJeepCar(){
          return new BentleyJeepCar();
      }

      ...
  }
  //其它工厂类似

调用

class Program
    {
        static void Main(string[] args)
        {
            //开宾利跑车
            IFactory factory = new BentleyFactory();
            ISportCar bentleySportCar = factory.CreateSportCar();
            bentleySportCar.Run();
        }
    }

当我们要新增一个新的类型的汽车,只要加一个继承ICar接口的新类型接口,然后在新类型下创建(实现新类型接口)具体品牌的汽车。但是要修改抽象工厂的源码,然后每个具体工厂的源码也要修改。在现有类型的车下新增品牌就很容易

使用简单工厂减少具体工厂的数量,这样就可以不用去修改具体工厂的源码

   public class Factory
   {
        public ISportCar CreateSportCar(string name)
        {
               if(name=="Bentley")
               {
                  return new BentleySportCar();
              }
              if(name=="RollsRoyce")
              {
                  retutn new RollsRoyceSportCar();
              }
              ...
        }
        public IJeepCar CreateJeepCar(string name)
        {
               if(name=="Bentley")
               {
                  return new BentleyJeepCar();
              }
              if(name=="RollsRoyce")
              {
                  retutn new RollsRoyceJeepCar();
              }
              ...
        }
        ...
   }

调用

  class Program
      {
          static void Main(string[] args)
          {
              //开宾利跑车
              Factory factory = new Factory();
              ISportCar bentleySportCar = factory.CreateSportCar("Bentley");
              bentleySportCar.Run();
          }
      }

还有更加方便的方法就是使用反射

策略模式

工厂模式是从工厂里new一个服务对象出来给客户使用,策略模式是客户注入一个具体实例对象给工厂以使用工厂提供的服务

将上面的工厂改造一下

  public class Factory
     {
          private ISportCar sportCar;
          private IJeepCar jeepCar;
          ...
          public CreateSportCar(ISportCar sportCar)
          {
             this.sportCar=sportCar;
          }
          public CreateJeepCar(IJeepCar jeepCar)
            {
               this.jeepCar=jeepCar;
            }
          ...
          public void SportCarRun(){
          {
             this.sportCar.Run();
          }
          public void JeepCarRun(){
            {
               this.jeepCar.Run();
            }

     }

调用

  class Program
      {
          static void Main(string[] args)
          {
              //开宾利跑车
              ISportCar bentleySportCar = new BentleySportCar();
              Factory factory=new Factory();
              factory.CreateSportCar(bentleySportCar);
              factory.SportCarRun();
          }
      }

可能会因为注入的具体实现不同而得到不同的服务功能;

更多依赖注入文章

首发