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
}