1. 引入html
當前社會分工愈來愈細,愈來愈專業化,各種產品的建立有專門的工廠生產,極大縮短了產品生產週期,提升了生產效率。同理,在軟件開發中,軟件對象的生產由具體的工廠進行建立,客戶能夠隨意的增長或刪除產品對象對其餘產品都不會有影響也不須要從新編譯。ide
2. 定義 學習
工廠方法模式,是定義一個用於建立產品對象的工廠接口,將產品對象的實際建立工做推遲到具體子工廠類中。知足了建立型模式中所要求的「建立與使用分離」的特色。spa
若是要建立的產品很少,只須要一個工廠便可完成,這種模式稱爲「簡單工廠模式」,該模式的缺點是,新增產品時違背了面向對象的「開閉原則」。code
3. 工廠方法實現計算器功能htm
之前面博客工廠模式之簡單工廠中提出的實現計算器功能爲例,用工廠方法進行實現,結構圖以下圖1所示,代碼以下:對象
簡單工廠模式中分支與工廠類耦合,須要增長新的運算類時,須要在工廠方法中的switch..case中添加判斷條件,根據依賴倒轉原則,將工廠類與運算進行解耦,所以,抽象出一個接口,接口中只有一個方法,建立抽象產品的工廠方法。以後,全部要生產具體類的工廠去實現這個接口。這樣簡單工廠模式的工廠類,變成了一個抽象工廠接口和多個生產類的具體工廠。此時,簡單工廠模式的工廠類變成一個工廠抽象接口和多個具體生成對象的工廠。blog
class Operate { private double _num1; private double _num2; public double num1 { get { return num1; } set { num1 = _num1; } } public double num2 { get { return num2; } set { num2 = _num2; } } public virtual double getResult(double num1, double num2) { double result = 0.0; return result; } } class Add : Operate { public override double getResult(double n1, double n2) { return n1 + n2; } } class Sub : Operate { public override double getResult(double n1, double n2) { return n1 - n2; } } class Multiply : Operate { public override double getResult(double n1, double n2) { return n1 * n2; } } class Divide : Operate { public override double getResult(double n1, double n2) { if (n2 == 0) throw new Exception("除數不能爲0"); return n1 / n2; } } interface IFactory { Operate createOperate(); } class AddFactory:IFactory { public Operate createOperate() { return new Add(); } } class SubFactory : IFactory { public Operate createOperate() { return new Sub(); } } class MultiplyFactory : IFactory { public Operate createOperate() { return new Multiply(); } } class DivideFactory : IFactory { public Operate createOperate() { return new Divide(); } } class Program { static void Main(string[] args) { IFactory operateFactory = new AddFactory(); Operate ope = operateFactory.createOperate(); double result = ope.getResult(1.0,2.0); Console.WriteLine("{0}",result); Console.Read(); } }
在工廠方法模式中,選擇用哪一個工廠實現運算類,由原來的工廠類內部轉移到客戶端判別。繼承
4.情景實現接口
情景介紹:某同窗「學雷鋒」以學習雷鋒的名義在醫院作義工(打掃、洗衣、買飯),在他生病的時候,其餘人以一樣的名義代替他去,首先使用簡單工廠模式實現。
分析發現,該場景中能夠把「學雷鋒」和其餘人抽象出一個「雷鋒」類,擁有打掃、洗衣、買飯的方法,代碼以下:
class LeiFeng { public void Sweep() { Console.WriteLine("I am sweeping"); } public void Wash() { Console.WriteLine("I am washing"); } public void Cook() { Console.WriteLine("I am cooking"); } } class Student:LeiFeng { } static void Main(string[] args) { LeiFeng lf=new Student(); lf.Cook(); lf.Sweep(); lf.Wash(); Console.WriteLine("Hello World!"); }
然而,若是有多個學生學雷鋒作好事時,須要進行屢次實例化,會形成大量重複代碼以及建立對象的資源消耗。而對醫院病人來講,不須要知道具體的對象是誰,只須要知道是學雷鋒的人幫忙就好。此外,有其餘社會人士「志願者」學雷鋒作好事,須要再新建一個類繼承LieFeng,由雷鋒工廠決定實例化誰,這是簡單工廠模式的實現,具體以下:
class SimpleFactory { public static LeiFeng createObject(string type) { LeiFeng result = null; switch (type) { case "學雷鋒的大學生": result = new Student(); break; case "社區志願者": result=new Volunteer();break; } return result; } } class Volunteer:LeiFeng { } static void Main(string[] args) { LeiFeng stud = SimpleFactory.createObject("學雷鋒的大學生"); stud.Sweep(); LeiFeng stud2 = SimpleFactory.createObject("社區志願者"); stud2.Cook(); Console.WriteLine("Hello World!"); }
上述實現爲簡單工廠模式,將其更改成工廠方法模式,所有代碼以下:
interface SimpleFactory { LeiFeng CreateLeiFeng(); } class StudengFactory:SimpleFactory { public LeiFeng CreateLeiFeng() { return new Student(); } } class VolunteerFactory { public LeiFeng CreateLeiFeng() { return new Volunteer(); } } class LeiFeng { public void Sweep() { Console.WriteLine("I am sweeping"); } public void Wash() { Console.WriteLine("I am washing"); } public void Cook() { Console.WriteLine("I am cooking"); } } class Student:LeiFeng { } class Volunteer:LeiFeng { } static void Main(string[] args) { SimpleFactory sf=new StudengFactory(); LeiFeng studeng = sf.CreateLeiFeng(); studeng.Sweep(); studeng.Wash(); Console.WriteLine("Hello World!"); }
5. 總結
工廠方法模式主要由4部分組成:
簡單工廠模式和工廠方法模式的區別:
簡單工廠模式中工廠類中包含必要的邏輯判斷,根據客戶說的選擇條件實例化相關類,客戶端與具體產品沒有依賴。而工廠方法模式實現時,客戶端須要決定實例化哪一個工廠來實現運算類,可是邏輯判斷在客戶端進行。
工廠方法模式是簡單工廠模式的衍生,解決了簡單工廠模式違反「開閉」原則的問題,並實現了可擴展,可以解決更復雜的層次結構,可用於產品結果複雜的場合。