定义
提供一个创建 一系列相关 或相互依赖对象的接口,而无需指定它们具体的类
构成
- 抽象产品类
 - 具体产品类
 - 抽象工厂类
 - 具体工厂类
 
调用
- 实例具体工厂对象
 - 使用具体工厂对象创建具体产品
 
使用场景
- 适配不同类型的数据库,例如SqlServer Access
 - 创建不同品牌的产品,例如戴尔的电脑,惠普的电脑
 
代码实现
// 抽象产品
public interface Keyboard
{
    void Input();
}
public interface Mouse
{
    void Click();
}
// 具体产品
public class MacKeyboard : Keyboard
{
    public void Input()
    {
        Console.WriteLine("Mac 专用键盘");
    }
}
public class MacMouse : Mouse
{
    public void Click()
    {
        Console.WriteLine("Mac 专用鼠标");
    }
}
public class WinKeyboard : Keyboard
{
    public void Input()
    {
        Console.WriteLine("Win 专用键盘");
    }
}
public class WinMouse : Mouse
{
    public void Click()
    {
        Console.WriteLine("Win 专用鼠标");
    }
}
// 抽象工厂类
public interface Hardware
{
    Keyboard CreateKeyBoard();
    Mouse CreateMouse();
}
// 具体工厂类
public class MacFactory : Hardware
{
    public Keyboard CreateKeyBoard()
    {
        return new MacKeyboard();
    }
    public Mouse CreateMouse()
    {
        return new MacMouse();
    }
}
public class WinFactory : Hardware
{
    public Keyboard CreateKeyBoard()
    {
        return new WinKeyboard();
    }
    public Mouse CreateMouse()
    {
        return new WinMouse();
    }
}
void Main()
{
    Hardware macFactory = new MacFactory();
    Keyboard macKeyboard = macFactory.CreateKeyBoard();
    macKeyboard.Input();
    Hardware winFactory = new WinFactory();
    Mouse winMouse = winFactory.CreateMouse();
    winMouse.Click();
}用简单工厂改进抽象工厂(添加判断使用哪种工厂,用户不用判断)<此模式需要在需求改变的情况下改变代码,需要重新编译>
public class DataAccess
{
      private static string db = "Sqlserver"; //指定Sqlserver 数据库,也可指定别的数据库
      public static IUser CreateUser()
     {
           switch()
           {
                case "SqlServer":
                    return new SqlServerUser();
                case "Access":
                    return new AccessUser();
                default:
                    return null;
           }
     }
}
void Main()
{
      IUser user = DataAccess.CreateUser();
      user.Insert(new User());
}反射 + 配置文件 + 抽象工厂(添加判断使用哪种工厂,用户不用判断)<此模式需要在需求改变的情况下改变配置文件,不需要重新编译>
所有在用简单工厂的地方,都可以考虑用反射技术来去除 switch 和 if, 解除分支判断带来的耦合
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="DB" value="Sqlserver"/>
    </appSettings>
</configuration>public class DataAccess
{
    private static readonly string AssemblyName = "c15"; //程序集名称
    private static readonly string db = ConfigurationManager.AppSettings["DB"];
    public static IUser CreateUser()
    {
         return (IUser)Assembly.Load(AssemblyName).CreateInstance($"{AssemblyName}.{db}User");
    }
}优点与缺点
- 抽象工厂具有工厂模式的优点,对添加 系列产品符合开闭原则
 - 抽象工厂添加新产品不符合开闭原则,需要取修改抽象工厂类,添加抽象产品类