定义
提供一个创建 一系列相关 或相互依赖对象的接口,而无需指定它们具体的类
构成
- 抽象产品类
- 具体产品类
- 抽象工厂类
- 具体工厂类
调用
- 实例具体工厂对象
- 使用具体工厂对象创建具体产品
使用场景
- 适配不同类型的数据库,例如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");
}
}优点与缺点
- 抽象工厂具有工厂模式的优点,对添加 系列产品符合开闭原则
- 抽象工厂添加新产品不符合开闭原则,需要取修改抽象工厂类,添加抽象产品类