这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
1. 多平台软件设计
开发一款软件,要求是支持多个平台,代码还要尽可能的被复用。 不管是哪个平台,软件的架构外观和功能都是一样的,只是不同的组件在不同的平台实现代码不一样而已。 假设这个软件很简单,只由三部分构成:按钮、文本框、绚丽的图表。 先抽象出组件接口,定义组件的特性和功能。
假设目前只支持Windows和Linux系统,对不同的平台需要编写不同的实现代码。
只贴WindowsButton和LinuxButton,省略部分代码。
class WindowsButton implements Button{
@Override
public void click() {
System.out.println("Windows按钮被点击");
}
}
class LinuxButton implements Button{
@Override
public void click() {
System.out.println("Linux按钮被点击");
}
}
软件类由Button、Text、Chart组合而成。
// 软件类
public class Application {
private Button button;
// 省略其他组件
public void buttonClick(){
button.click();
}
}
至此,软件类和组件类已经全部定义好了,该如何组装这些组件呢?手动new出来再set吗?你怎么知道我需要的是Windows的组件还是Linux的组件呢?万一以后要为Mac平台开发一套,你又要怎么做?
定义一个工厂接口,指定需要生产哪些组件,再由子类来负责生产对应的组件,Windows工厂就只生产Windows组件,Linux工厂只生产Linux组件,各司其职。
public interface ComponentFactory {
// 生产按钮
Button createButton();
// 生产其他组件
}
// Windows组件工厂
public class WindowsComponentFactory implements ComponentFactory{
@Override
public Button createButton() {
return new WindowsButton();
}
// 省略部分代码.......
}
// Linux组件工厂
public class LinuxComponentFactory implements ComponentFactory{
@Override
public Button createButton() {
return new LinuxButton();
}
// 省略部分代码.......
}
Application
依赖于组件工厂生产组件,类稍作修改:
public class Application {
private Button button;
// 其他组件
public Application(ComponentFactory factory) {
this.button = factory.createButton();
// 生产其他组件
}
public void buttonClick(){
button.click();
}
// 省略部分代码.......
}
至此,整个结构都出来了,最终类图如下:
这就是抽象工厂模式!
2. 抽象工厂模式的定义
抽象工厂模式通用类图为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
- Factory:工厂抽象,定义工厂的功能,需要生产哪些产品。
- ConcreteFactory:工厂实现,负责生产产品族。
- Product:产品抽象,定义产品所具有的特性和方法。
- ConcreteProduct:具体的产品实现。
抽象工厂模式是工厂方法模式的升级版,工厂方法模式只能生产单个品类的产品,而抽象工厂模式可以生产一组相关或相互关联的产品,也叫作【产品族】,有N个产品族,抽象工厂就应该有N个方法。如果存在多个业务品种,通过抽象工厂模式来产生对象是非常好的。
1. 工厂方法模式的优缺点
优点
- 良好的封装性,客户端不关心产品实现类,只关心工厂,和产品的抽象,符合依赖倒置原则。
- 可以保证客户端只使用同一个产品族内的对象。
- 产品族内的约束对客户端来说是透明的,例如抽象工厂模式可以保证每生产M个产品A,同时生产出N个产品B。
缺点
- 产品族难以扩展,如果要增加一个产品类,抽象工厂和所有的工厂实现都需要修改,不符合开闭原则。
抽象工厂模式虽然产品族难以扩展,但是产品等级是非常统一扩展的,例如Application
要为Mac系统也开发一套,只需要实现Mac系统的组件,和Mac系统的ComponentFactory
即可,其他地方都不需要修改。
4. 总结
抽象工厂模式是工厂方法模式的扩展,工厂方法模式只能生产单个品类的产品,而抽象工厂模式可以生产一组相关或相互依赖的产品族。抽象方法模式的产品等级非常容易扩展,但是产品族难以扩展。因此,抽象工厂模式更适合于产品结构相对稳定的场景,对于后续可能会频繁添加或删除产品类的结构,就不太适用了。