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
}