C#设计模式之工厂模式

发布于:2025-03-22 ⋅ 阅读:(17) ⋅ 点赞:(0)

C#设计模式之工厂模式

工厂模式包含:简单工厂->工厂方法->抽象工厂,是设计模式中的创建型模式

1. 简单工厂模式:用来生产同一等级结构中的任意产品(对于增加新的产品,需要覆盖已有代码(工厂类里的GetCalcultor方法)
在这里插入图片描述

注:新增产品需要修改工厂类创建产品的方法较为麻烦!!

**2. 工厂方法模式:**用来生产同一等级结构中的固定产品(支持增加任意产品)
在这里插入图片描述

注:将判断调用代码独立出去(类中不再进行判断),新增产品仅需增加对应的产品类和工厂类即可

具体调用的代码如下:

ICalcultor? cal1;
ICalFactory? calFactory;
switch (sOper)
{
    case "+":
        calFactory = new AddFactory();
        cal1 = calFactory.GetCalultor();
        break;
    case "*":
        calFactory = new MulFactory();
        cal1 = calFactory.GetCalultor();
        break;
    case "%":
        calFactory = new ModFactory();
        cal1 = calFactory.GetCalultor();
        break;
    //case "/":...
    //...
    default: cal1 = null;break;
}

**3. 抽象工厂模式:**围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂(适用于产品族)

特点:一个工厂对多个产品,但新增产品处需新增产品类外还需要修改工厂接口和具体工厂类!!!
在这里插入图片描述

调用代码如下:

 #region 抽象工厂

    //windows组件
    IGUIFactory IWinFactory;
    IGUIComponent oWinLayout, oWinSpacer, oWinButton;
    Console.WriteLine($"创建windows组件如下:");
    IWinFactory = new WinFactory();
    oWinLayout = IWinFactory.CreateLayout();
    oWinSpacer = IWinFactory.CreateSpacer();
    oWinButton = IWinFactory.CreateButton();
    //使用组件
    oWinLayout.paint();
    oWinSpacer.paint();
    oWinButton.paint();
    
    
    //MacOS组件
    IGUIFactory IMacOsFactory;
    IGUIComponent oMacOSLayout, oMacOSSpacer, oMacOSbutton;
    Console.WriteLine($"创建MacOS组件如下:");
    IMacOsFactory = new MacOSFactory();
    oMacOSLayout = IMacOsFactory.CreateLayout();
    oMacOSSpacer = IMacOsFactory.CreateSpacer();
    oMacOSbutton = IMacOsFactory.CreateButton();
    
    oMacOSLayout.paint();
    oMacOSSpacer.paint();
    oMacOSbutton.paint();
    #endregion

附录. 完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Formats.Asn1.AsnWriter;

namespace ConsoleCsharp00
{
    internal class 设计模式
    {
        public static void Test()
        {
            #region 简单工厂
            try
            {
                Console.WriteLine("请输入运算数1:");
                double dNumA = Convert.ToDouble(Console.ReadLine());

                Console.WriteLine("请输入运算符:");
                string? sOper = Console.ReadLine();

                Console.WriteLine("请输入运算数2:");
                double dNumB = Convert.ToDouble(Console.ReadLine());

                
                ICalcultor? cal = new CalFactory().GetCalultor(sOper);
                if (cal != null)
                {
                    cal.NumA = dNumA;
                    cal.NumB = dNumB;
                    Console.WriteLine($"{dNumA} {sOper} {dNumB} = {cal.GetResult()}");
                }
                
            }
            catch
            {
                Console.WriteLine("输入不合理");
            }

            #endregion

            #region 工厂方法模式
            //客户端代码:仅与工厂接口和产品接口交互,具体使用哪种产品由具体工厂创建:创建逻辑与使用逻辑的分离
            try
            {
                ICalcultor? cal1;
                ICalFactory? calFactory;
                Console.WriteLine("请输入运算数1:");
                double dNumA = Convert.ToDouble(Console.ReadLine());

                Console.WriteLine("请输入运算符:");
                string? sOper = Console.ReadLine();

                Console.WriteLine("请输入运算数2:");
                double dNumB = Convert.ToDouble(Console.ReadLine());

                switch (sOper)
                {
                    case "+":
                        calFactory = new AddFactory();
                        cal1 = calFactory.GetCalultor();
                        break;
                    case "*":
                        calFactory = new MulFactory();
                        cal1 = calFactory.GetCalultor();
                        break;
                    case "%":
                        calFactory = new ModFactory();
                        cal1 = calFactory.GetCalultor();
                        break;
                    //case "/":...
                    //...
                    default: cal1 = null;break;
                }
                if (cal1 != null) 
                {
                    cal1.NumA = dNumA;
                    cal1.NumB = dNumB;
                    Console.WriteLine($"{dNumA} {sOper} {dNumB} = {cal1.GetResult()}");
                }
            }
            catch
            {
                Console.WriteLine("输入不合理");
            }



            #endregion

            #region 抽象工厂

            //windows组件
            IGUIFactory IWinFactory;
            IGUIComponent oWinLayout, oWinSpacer, oWinButton;
            Console.WriteLine($"创建windows组件如下:");
            IWinFactory = new WinFactory();
            oWinLayout = IWinFactory.CreateLayout();
            oWinSpacer = IWinFactory.CreateSpacer();
            oWinButton = IWinFactory.CreateButton();
            //使用组件
            oWinLayout.paint();
            oWinSpacer.paint();
            oWinButton.paint();


            //MacOS组件
            IGUIFactory IMacOsFactory;
            IGUIComponent oMacOSLayout, oMacOSSpacer, oMacOSbutton;
            Console.WriteLine($"创建MacOS组件如下:");
            IMacOsFactory = new MacOSFactory();
            oMacOSLayout = IMacOsFactory.CreateLayout();
            oMacOSSpacer = IMacOsFactory.CreateSpacer();
            oMacOSbutton = IMacOsFactory.CreateButton();

            oMacOSLayout.paint();
            oMacOSSpacer.paint();
            oMacOSbutton.paint();
            #endregion
        }

    }

    #region 工厂方法模式
    /* 1)场景:“某个对象”的创建工作:由于需求的变化,
     *         这个对象(的具体实现)经常面临着剧烈的变化,
     *         但是它却拥有比较稳定的接口。
     * 2)定义一个创建对象的工厂接口,由其子类决定要实例化的类,将实际创建工作推迟到子类中
     *    eg:运算器(双目),包含各种算法(加、减、乘、除、取余等等),由运算符决定实例化什么子类
     */

    /********简单工厂->工厂方法->抽象工厂:****
     *
     *  1、简单工厂:
     *    工厂类:根据需求创建具体的对象;
     *    抽象产品类:接口或抽象类,定义产品的公共接口
     *    具体产品:继承或实现抽象产品类,实现自身产品具体方法
     *    
     *    缺点:新增一个产品需修改工厂类的Get产品的方法(如下文的GetCalultor)
     *    优化:将工厂方法提取成一个接口=>工厂方法模式
     *    
     *  2、工厂方法(将简单工厂的工厂类进行抽象,增加具体工厂类去创建对应的产品):
     *    抽象工厂类:接口/抽象类;
     *    具体工厂类:每个具体工厂类对应一种产品类型;
     *    抽象产品类:
     *    具体产品类:    
     *    
     *    调用代码:即将需求判断交付给具体调用的地方去判断,但调用时不与具体产品对接
     *              实现创建逻辑与使用逻辑的分离
     *     
     *    优点:新增产品只需增加对应的产品类和工厂类即可,无需改动类内部的代码;
     *    缺点:类结构边复杂了
     *       
     *  3、抽象工厂:适用于产品族
     *    抽象工厂:定义了创建一系列产品的方法,每个方法对应一种产品。
     *    具体工厂:实现了抽象工厂接口,负责创建具体的产品。
     *    
     *    
     */

    //1、简单工厂
    /// <summary>
    /// 双目运算器接口--抽象产品类
    /// </summary>
    interface ICalcultor
    {
        public double  NumA{get;set;}
        public double NumB {get;set;}

        public double GetResult();
    }
    /// <summary>
    /// 双目运算器工厂类:根据用户需求(运算符类型)创建具体的对象
    /// </summary>
    class CalFactory
    {
        public ICalcultor? GetCalultor(string sOper)
        {
            ICalcultor? cal;
            switch (sOper) 
            {
                case "+":cal = new CalAdd();break;
                case "*":cal = new CalMul();break;
                case "%":cal = new CalMod();break;

                //case "/":cal = new CalDiv();break;
                //...
                default: cal = null;break;
            }
            return cal;
        }
    }

    ///具体产品类:加、取余、...
    class CalAdd : ICalcultor
    {
        private double dNumA = 0.0;
        private double dNumB = 0.0;
        public double NumA { get { return dNumA; } set { dNumA = value; } }
        public double NumB { get { return dNumB; } set { dNumB = value; } }

        public double GetResult()
        {
            return ( dNumA + dNumB );
        }
    }

    class CalMul : ICalcultor
    {
        private double dNumA = 0.0;
        private double dNumB = 0.0;
        public double NumA { get { return dNumA; } set { dNumA = value; } }
        public double NumB { get { return dNumB; } set { dNumB = value; } }

        public double GetResult()
        {
            return ( dNumA * dNumB );
        }
    }
    class CalMod : ICalcultor
    {
        private double dNumA = 0.0;
        private double dNumB = 0.0;
        public double NumA { get { return dNumA; } set { dNumA = value; } }
        public double NumB { get { return dNumB; } set { dNumB = value; } }

        public double GetResult()
        {
            return (dNumA % dNumB);
        }
    }

    //class CalDiv...可自行扩展

    //每次扩展新产品需要修改工厂类的方法,不符合开闭原则
    //将工厂类进行抽象变成=>工厂方法模式;增加客户端代码判断需求


    //2、工厂方法
    /// <summary>
    /// 抽象工厂接口
    /// </summary>
    interface ICalFactory
    {
        public ICalcultor GetCalultor();
    }

    //具体产品对应的工厂类
    class AddFactory : ICalFactory
    {
        public ICalcultor GetCalultor()
        {
            return new CalAdd();
        }
    }

    class MulFactory : ICalFactory
    {
        public ICalcultor GetCalultor()
        {
            return new CalMul();
        }
    }

    class ModFactory : ICalFactory
    {
        public ICalcultor GetCalultor()
        {
            return new CalMod();
        }
    }

    //class DivFactory : ICalFactory
    //...自行扩展


    //3、抽象工厂
    //抽象工厂模式:将工厂方法的客户端调用封装成一个类,适用于产品族;抽象工厂为超级工厂,可调用多个工厂生产多种类型产品
    //eg:不同操作系统的GUI组件
    //GUI产品接口
    interface IGUIComponent
    {
        public void paint();
    }

    //工厂接口:生产所有的组件
    interface IGUIFactory
    {
        public IGUIComponent CreateLayout();
        public IGUIComponent CreateSpacer();
        public IGUIComponent CreateButton(); 
    }


    //Windows组件
    class WindowsLayout : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("布局组件:WindowsLayout");
        }
    }

    class WindowsSpacer : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("分隔组件:WindowsSpacer");
        }
    }

    class WindowsButton : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("按钮组件:WindowsButton");
        }
    }

    //windows工厂:生产所有windows组件
    class WinFactory: IGUIFactory
    {
        public IGUIComponent CreateLayout()
        {
            return new WindowsLayout();
        }
        public IGUIComponent CreateButton()
        {
            return new WindowsButton();
        }
        public IGUIComponent CreateSpacer()
        {
            return new WindowsSpacer();
        }
    }

    //MacOS组件
    class MacOSLayout : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("布局组件:MacOSLayout");
        }
    }

    class MacOSSpacer : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("分隔组件:MacOSSpacer");
        }
    }

    class MacOSButton : IGUIComponent
    {
        public void paint()
        {
            Console.WriteLine("按钮组件:MacOSButton");
        }
    }

    //MacOS工厂:生产所有MacOS组件
    class MacOSFactory : IGUIFactory
    {
        public IGUIComponent CreateLayout()
        {
            return new MacOSLayout();
        }
        public IGUIComponent CreateButton()
        {
            return new MacOSButton();
        }
        public IGUIComponent CreateSpacer()
        {
            return new MacOSSpacer();
        }
    }

    #endregion
}