国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

六、創(chuàng)建型模式之工廠模式進(jìn)化史-----《大話設(shè)計(jì)模式》

2019-11-14 13:59:11
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

      創(chuàng)建類模式隱藏了這些類的實(shí)例是如何被創(chuàng)建和放在一起,整個(gè)系統(tǒng)關(guān)于這些對(duì)象所知道的是由抽象類所定義的接口;這樣,創(chuàng)建類模式在創(chuàng)建了什么,誰(shuí)創(chuàng)建它的,它怎么被創(chuàng)建的,以及何時(shí)創(chuàng)建這些方面提供了很大的靈活性。創(chuàng)建類模式抽象了實(shí)例化的過(guò)程,允許客戶用結(jié)構(gòu)和功能差別很大的“產(chǎn)品”對(duì)象配置一個(gè)系統(tǒng)配置可以是靜態(tài)的,即在編譯時(shí)指定,也可以是動(dòng)態(tài)的,就是運(yùn)行時(shí)再指定。

 

一、簡(jiǎn)單工廠模式:

需要增加運(yùn)算形式時(shí)只需要增加運(yùn)算子類,同時(shí)修改簡(jiǎn)單工廠中的switch增加分支即可,這樣客戶端調(diào)用代碼基本不動(dòng)。

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    // 運(yùn)算類    public class Operation    {        PRivate double _numberA = 0;        private double _numberB = 0;                // 數(shù)字A屬性     
        public double NumberA        {            get            {                return _numberA;            }            set            {                _numberA = value;            }        }        // 數(shù)字B屬性        public double NumberB        {            get            {                return _numberB;            }            set            {                _numberB = value;            }        }        // 得到運(yùn)算結(jié)果        public virtual double getResult()        {            double result = 0;             return result;        }           }
// 加法類    class OperationAdd : Operation    {        public override double getResult()        {            double result = 0;             result = NumberA + NumberB;            return result;        }    }    // 減法類    class OperationSub : Operation    {       public override double getResult()        {            double result = 0;            result = NumberA - NumberB;            return result;        }    }    // 乘法類    class OperationMul : Operation    {        public override double getResult()        {            double result = 0;            result = NumberA * NumberB;            return result;        }    }    // 除法類    class OperationDiv : Operation    {        public override double getResult()        {            double result = 0;            if (NumberB==0)                throw new Exception("除數(shù)不能為0。");            result = NumberA / NumberB;            return result;        }    }
   // 簡(jiǎn)單類工廠    class OperationFactory    {        public static Operation createOperate(string operate)        {            Operation oper = null;            switch (operate)            {                case "+":                    {                        oper = new OperationAdd();                        break;                    }                case "-":                    {                        oper = new OperationSub();                        break;                    }                case "*":                    {                        oper = new OperationMul();                        break;                    }                case "/":                    {                        oper = new OperationDiv();                        break;                    }            }            return oper;        }    }
//控制臺(tái)調(diào)用static void Main(string[] args)        {            try            {                Console.Write("請(qǐng)輸入數(shù)字A:");                string strNumberA = Console.ReadLine();                Console.Write("請(qǐng)選擇運(yùn)算符號(hào)(+、-、*、/):");                string strOperate = Console.ReadLine();                Console.Write("請(qǐng)輸入數(shù)字B:");                string strNumberB = Console.ReadLine();                string strResult = "";                Operation oper;                                         //聲明運(yùn)算類                oper = OperationFactory.createOperate(strOperate);      //根據(jù)運(yùn)算符調(diào)用工廠類初始化相應(yīng)運(yùn)算子類                oper.NumberA = Convert.ToDouble(strNumberA);                oper.NumberB = Convert.ToDouble(strNumberB);                strResult = oper.GetResult().ToString();                Console.WriteLine("結(jié)果是:" + strResult);                Console.ReadLine();            }            catch (Exception ex)            {                Console.WriteLine("您的輸入有錯(cuò):" + ex.Message);            }        }

  

二、工廠方法模式:

    與簡(jiǎn)單工廠模式相比,增加了工廠類的虛類,并針對(duì)每一個(gè)運(yùn)算子類編寫(xiě)了一個(gè)工廠方法;當(dāng)增加運(yùn)算方式時(shí)只需增加運(yùn)算子類和工廠子類,不需對(duì)原有類進(jìn)行修改。運(yùn)算類代碼見(jiàn)上。

    工廠方法模式實(shí)現(xiàn)時(shí),客戶端需要決定實(shí)例化哪一個(gè)工廠來(lái)實(shí)現(xiàn)運(yùn)算類,只是將簡(jiǎn)單工廠類的內(nèi)部邏輯判斷(switch)移到了客戶端代碼來(lái)進(jìn)行。

image

// 工廠類,接口,Creator    interface IFactory    {        Operation CreateOperation();    }
// 加法工廠,ConcreteCreator    class AddFactory : IFactory    {        public Operation CreateOperation()        {            return new OperationAdd();                  // 初始化加法類(ConcreteProduct)
        }    }    //減法工廠,ConcreteCreator     class SubFactory : IFactory    {        public Operation CreateOperation()        {            return new OperationSub();        }    }    // 乘法工廠,ConcreteCreator     class MulFactory : IFactory    {        public Operation CreateOperation()        {            return new OperationMul();        }    }    ///除法工廠,ConcreteCreator     class DivFactory : IFactory    {        public Operation CreateOperation()        {            return new OperationDiv();        }    }
static void Main(string[] args)                                          //客戶端調(diào)用        {            IFactory operFactory = new AddFactory();                     //初始化加法工廠              Operation oper = operFactory.CreateOperation();              //初始化加法類              oper.NumberA = 1;            oper.NumberB = 2;             double result=oper.GetResult();            Console.WriteLine(result);            Console.Read();        }

三、抽象工廠模式

    抽象工廠模式與工廠方法模式的區(qū)別是在于當(dāng)涉及到多個(gè)產(chǎn)品系列又是不同的分類時(shí),對(duì)專門的工廠模式的叫法而已。從圖上理解就是工廠方法模式解決的問(wèn)題只有一個(gè)A產(chǎn)品,而抽象工廠模式解決A、B、……甚至更多的產(chǎn)品。

    優(yōu)點(diǎn):1.具體類只初始化一次,修改代碼時(shí)方便;2.讓具體的創(chuàng)建實(shí)例過(guò)程與客戶端分離,產(chǎn)品的具體類名被具體工廠的實(shí)現(xiàn)分離,不會(huì)出現(xiàn)在客戶代碼中。

    增加產(chǎn)品時(shí)需增加AbstractProductC、ProductC1、ProductC2,修改AbstractFactory、ConcreteFactory1和ConcreteFactory2增加CreateProductC()方法。

image

   //用戶表,用戶信息
class User                                           {        private int _id;        public int ID        {            get { return _id; }            set { _id = value; }        }        private string _name;        public string Name        {            get { return _name; }            set { _name = value; }        }    }//部門表,部門信息    
class Department                                            {        private int _id;        public int ID        {            get { return _id; }            set { _id = value; }        }        private string _deptName;        public string DeptName        {            get { return _deptName; }            set { _deptName = value; }        }    }
//用戶信息接口,AbstractProductA
interface IUser{    void Insert(User user);    User GetUser(int id); }
//SQL實(shí)現(xiàn)用戶信息操作,ProductA1
class SqlserverUser : IUser{    public void Insert(User user)    {        Console.WriteLine("在Sqlserver中給User表增加一條記錄");    }    public User GetUser(int id)    {        Console.WriteLine("在Sqlserver中根據(jù)ID得到User表一條記錄");        return null;    }}
//access實(shí)現(xiàn)用戶信息操作,ProductA2
class AccessUser : IUser{    public void Insert(User user)    {        Console.WriteLine("在Access中給User表增加一條記錄");    }    public User GetUser(int id)    {        Console.WriteLine("在Access中根據(jù)ID得到User表一條記錄");        return null;    }}
//部門信息接口,AbstractProductB
interface IDepartment    {        void Insert(Department department);        Department GetDepartment(int id);    }
//SQL實(shí)現(xiàn)部門信息操作,ProductB1
class SqlserverDepartment : IDepartment    {        public void Insert(Department department)        {            Console.WriteLine("在Sqlserver中給Department表增加一條記錄");        }        public Department GetDepartment(int id)        {            Console.WriteLine("在Sqlserver中根據(jù)ID得到Department表一條記錄");            return null;        }    }//ACCESS實(shí)現(xiàn)部門信息操作,ProductB2
class AccessDepartment : IDepartment    {        public void Insert(Department department)        {            Console.WriteLine("在Access中給Department表增加一條記錄");        }        public Department GetDepartment(int id)        {            Console.WriteLine("在Access中根據(jù)ID得到Department表一條記錄");            return null;        }    }
//工廠接口,AbstractFactory
interface IFactory    {        IUser CreateUser();        IDepartment CreateDepartment();    }
//SQL具體工廠類,ConcreteFactory1
class SqlServerFactory : IFactory    {        public IUser CreateUser()        {            return new SqlserverUser();        }        public IDepartment CreateDepartment()        {            return new SqlserverDepartment();        }    }
//Accese具體工廠類,ConcreteFactory2
class AccessFactory : IFactory    {        public IUser CreateUser()        {            return new AccessUser();        }        public IDepartment CreateDepartment()        {            return new AccessDepartment();        }    }
//客戶端調(diào)用static void Main(string[] args)        {            //初始化兩個(gè)產(chǎn)品            User user = new User();            Department dept = new Department();            //選擇實(shí)現(xiàn)哪個(gè)工廠            IFactory factory = new AccessFactory();            IUser iu = factory.CreateUser();            iu.Insert(user);            iu.GetUser(1);            IDepartment id = factory.CreateDepartment();            id.Insert(dept);            id.GetDepartment(1);            Console.Read();        }    }

四、對(duì)抽象工廠模式的改進(jìn)

    改進(jìn)手段:簡(jiǎn)單工廠+反射

第一步:取消AbstractFactory、ConcreteFactory1和ConcreteFactory2,用簡(jiǎn)單工廠類來(lái)實(shí)現(xiàn)。

//取消接口,只用一個(gè)類 class DataAccess    {        //指定用什么數(shù)據(jù)庫(kù)        private static readonly string db = "Sqlserver";                      //private static readonly string db = "Access";       //用戶信息維護(hù),根據(jù)指定判斷用哪個(gè)具體產(chǎn)品        public static IUser CreateUser()        {            IUser result = null;            switch (db)            {                case "Sqlserver":                    result = new SqlserverUser();                    break;                case "Access":                    result = new AccessUser();                    break;            }            return result;        }       //部門信息維護(hù),根據(jù)指定判斷用哪個(gè)具體產(chǎn)品        public static IDepartment CreateDepartment()        {            IDepartment result = null;            switch (db)            {                case "Sqlserver":                    result = new SqlserverDepartment();                    break;                case "Access":                    result = new AccessDepartment();                    break;            }            return result;        }    }
//在客戶端程序中不用指定用哪個(gè)數(shù)據(jù)庫(kù),只需要操作即可static void Main(string[] args)        {            //初始化            User user = new User();            Department dept = new Department();            IUser iu = DataAccess.CreateUser();            iu.Insert(user);            iu.GetUser(1);            IDepartment id = DataAccess.CreateDepartment();            id.Insert(dept);            id.GetDepartment(1);            Console.Read();        }

第二步,替換簡(jiǎn)單工廠中部分代碼,采用反射,可以將原執(zhí)行語(yǔ)句部分變成字符串形式易于變化。

//使用反射時(shí),必須引用using System.Reflection; //Assembly.Load(‘程序集名稱’).CreateInstance('命名空間.類名稱');class DataAccess    {        //指定程序集名稱,同時(shí)在配置文件中獲取‘DB’的值,在配置文件中指定數(shù)據(jù)庫(kù)類型        private static readonly string AssemblyName = "抽象工廠模式";        private static readonly string db = ConfigurationManager.AppSettings["DB"];               //指定類名稱,遵循命名規(guī)則        public static IUser CreateUser()        {            string className = AssemblyName + "." + db + "User";            return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);        }        public static IDepartment CreateDepartment()        {            string className = AssemblyName + "." + db + "Department";            return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);        }    }
//配置文件中的寫(xiě)法<configuration>    <appSettings>        <add key="DB" value="Sqlserver"/>    </appSettings></configuration>

 

      PS:所有在用簡(jiǎn)單工廠的地方,都可以考慮用反射技術(shù)來(lái)去除switch或if,解除分支判斷帶來(lái)的耦合。

五、總結(jié)

工廠方法:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,工廠方法模式使一個(gè)類的實(shí)例化延遲到其子類;

抽象工廠:提供一個(gè)創(chuàng)建一系列或相關(guān)依賴對(duì)象的接口,而無(wú)需指定它們具體的類。

    設(shè)計(jì)通常從工廠方法開(kāi)始,當(dāng)設(shè)計(jì)者發(fā)現(xiàn)需要更大的靈活性時(shí),設(shè)計(jì)便會(huì)向其他創(chuàng)建型模式演化;當(dāng)設(shè)計(jì)者在設(shè)計(jì)標(biāo)準(zhǔn)之間進(jìn)行權(quán)衡的時(shí)候,了解多個(gè)創(chuàng)建型模式可以給設(shè)計(jì)者更多的選擇余地。

 


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 二连浩特市| 平阴县| 淳化县| 金川县| 大荔县| 长顺县| 武强县| 黎平县| 浮梁县| 剑河县| 墨玉县| 扎鲁特旗| 永城市| 阿鲁科尔沁旗| 海南省| 玉林市| 竹山县| 丽水市| 新民市| 深水埗区| 黔南| 武隆县| 焉耆| 威宁| 长泰县| 和平区| 彝良县| 株洲县| 浦县| 易门县| 定结县| 稻城县| 饶平县| 聂荣县| 宣武区| 贵定县| 梁河县| 武川县| 临颍县| 茶陵县| 日照市|