概述
在系统中往往会有这种需求,客户端会用到很多对象,而且根据需求变化很可能会切换成另外一套对象。抽象工厂模式可以提供一种封装机制来面对这种需求。
实践
物理模型:
皮肤主题:设计一个可以切换皮肤主题,切换为 黑色 和灰色样式,每个元素的样式都要单独定义,如Input的样式,button的样式,这些所有的元素样式组成一套皮肤主题。
根据模型,先抽象,每种元素相当于一种产品,如button
/// <summary> /// Button按钮样式 /// </summary> public interface IButton { int Border { get; } string BackColor { get; } }
然后 具体实现它
/// <summary> /// 灰色按钮样式 /// </summary> public class GrayButton : IButton { public GrayButton() { Border = 1; BackColor = "#ccc"; } public int Border { get; set; } public string BackColor { get; set; } } /// <summary> /// 黑色按钮样式 /// </summary> public class BlackButton : IButton { public BlackButton() { Border = 1; BackColor = "#fff"; } public int Border { get; set; } public string BackColor { get; set; } }
上面是一种html元素,其它元素的样式类似
/// <summary> /// 文本框 /// </summary> public interface IInput { int Border { get; } } /// <summary> /// 灰色文本框样式 /// </summary> public class GrayInput : IInput { public GrayInput() { Border = 1; } public int Border { get; set; } } /// <summary> /// 黑色文本框样式 /// </summary> public class BlackInput : IInput { public BlackInput() { Border = 1; } public int Border { get; set; } }
产品抽象完后,接下来抽象工厂
/// <summary> /// 抽象工厂 /// </summary> public interface IThemesFactory { IButton CreateButton(); IInput CreateInput(); }
具体主题样式工厂
/// <summary> /// 创建灰色样式工厂 /// </summary> public class GrayFactory : IThemesFactory { public IButton CreateButton() { return new GrayButton(); } public IInput CreateInput() { return new GrayInput(); } }
其它主题工厂类似
/// <summary> /// 黑色主题样式工厂 /// </summary> public class BlackFactory : IThemesFactory { public IButton CreateButton() { return new BlackButton(); } public IInput CreateInput() { return new BlackInput(); } }
客户端调用
/// <summary> /// 主题 /// </summary> public class ThemesMain { public void Main() { //灰色主题工厂 IThemesFactory factory = new GrayFactory(); //按钮样式 IButton button = factory.CreateButton(); //文本框样式 IInput input = factory.CreateInput(); } }
小结
抽象工厂适用于一系列的对象的创建和切换,如 数据库配置有 MsSql,MySql,每种数据库下的 查询User 都是不一样,可以抽象工厂,写两套,客户端方便切换。
抽象工厂优点:
- 客户端Main 里 都是使用抽象产品如IButton 不依赖具体的产品创建,而统一由工厂方法创建;
- 切换产品方便,只需要切换工厂,接下来的由工厂创建的产品也就切换了;
- 易扩展,如后续加产品,只需在工厂里创建出来就行,客户端不用改。
缺点:
- 代码量大,由于抽象有工厂接口,有产品接口;
- 修改量大,如有修改现有的产品,可能从接口修改到具体,全改一遍。