三種工廠模式與策略模式

若邪發表於2019-03-04

簡單工廠模式

實現一個功能,假設現在有跑車,越野車,商務車,想要開什麼車的時候隨時能發車。

抽象汽車

    /// <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();
          }
      }複製程式碼

可能會因為注入的具體實現不同而得到不同的服務功能;

更多依賴注入文章

首發

相關文章