其他工厂模式
介绍
抽象工厂模式是类的创建型模式,它是工厂方法模式的进一步推广。是所有形态的工厂模式中最为抽象和最具一般性的一种形态。提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式中的“抽象”来自抽象“产品角色”,而“抽象工厂”就是抽象产品角色的工厂。
模式角色
抽象工厂模式有以下角色。
- AbstractFactory(抽象工厂),担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
- ConcreteCreator(具体工厂),这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
- AbstractProduct(抽象产品),担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
- ConcreteProduct(具体产品),抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
模式结构图
模式实现
模式实现,下面通过伪代码去实现该模式:
模拟移动端的View框架或者说需要写一个有多端风格的GUI框架(Android风格、iOS风格),这个系统有显示文本的TextView控件,显示一个按钮的Button控件,显示一个列表、一个圆…对于Android端,有一套View。对于iOS端,也有一套View。它们的相位图如下。
/**
* 抽象工厂模式
*/
public abstract class AbstractFactory {
public abstract AbstractFactoryTextVew factoryTextVew();
public abstract AbstractFactoryButton factoryButton();
}
/**
* 抽象产品
* 控件基类-View
*/
abstract class AbstractFactoryView {
private int width;
private int height;
public AbstractFactoryView() {
}
public AbstractFactoryView(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public abstract void onDraw();
}
/**
* 抽象产品
* 抽象控件TextView
*/
abstract class AbstractFactoryTextVew extends AbstractFactoryView {
// 具体逻辑
}
/**
* 抽象产品
* 抽象控件Button
*/
abstract class AbstractFactoryButton extends AbstractFactoryView {
// 具体逻辑
}
/**
* Android风格 工厂类
*/
class AndroidStyleFactory extends AbstractFactory {
@Override
public AbstractFactoryTextVew factoryTextVew() {
return new AndroidStyleTextView();
}
@Override
public AbstractFactoryButton factoryButton() {
return new AndroidStyleButton();
}
}
/**
* 具体产品
* Android风格控件TextView
*/
class AndroidStyleTextView extends AbstractFactoryTextVew {
@Override
public void onDraw() {
// 逻辑
}
}
/**
* 具体产品
* Android风格控件Button
*/
class AndroidStyleButton extends AbstractFactoryButton {
@Override
public void onDraw() {
// 逻辑
}
}
/**
* iOS风格 工厂类
*/
class IOSStyleFactory extends AbstractFactory {
@Override
public AbstractFactoryTextVew factoryTextVew() {
return new IOSStyleTextView();
}
@Override
public AbstractFactoryButton factoryButton() {
return new IOSStyleButton();
}
}
/**
* 具体产品
* iOS风格控件TextView
*/
class IOSStyleTextView extends AbstractFactoryTextVew {
@Override
public void onDraw() {
// 逻辑
}
}
/**
* 具体产品
* iOS风格控件Button
*/
class IOSStyleButton extends AbstractFactoryButton {
@Override
public void onDraw() {
// 逻辑
}
}
/**
* Client
*/
class AbstractFactoryClient {
public static void main(String[] args) {
AbstractFactory factory = null;
// 可根据当前环境,动态决定使用哪个style的产品
if (null != args && args.length > 0) {
if ("Android".equals(args[0])) {
factory = new AndroidStyleFactory();
// Android风格的控件处理..
// factory.factoryTextVew();
// factory.factoryButton();
} else if ("iOS".equals(args[0])) {
factory = new IOSStyleFactory();
// iOS风格的控件处理..
// factory.factoryTextVew();
// factory.factoryButton();
}
}
}
}
多个产品等级结构
产品族与产品等级结构
引进抽象工厂模式
博客中关于抽象工厂模式的代码实现的产品族也产品等级结构如下:
模式的优点和缺点
优点:
- 分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。
- 易于交换产品系列。一个具体工厂类只在初始化时出现一次,这使得改变一个应用的具体工厂变得很容易,只需改变具体的工厂即可使用不同的产品配置。
- 有利于产品的一致性。当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。
缺点:
- 当增加新的产品族时(在博文代码实现中,新增Windows端时)易于实现,只需新增具体工厂类,对客户没有影响。但是当增加新的产品等级结构时,需要修改所有的工厂角色,这一点是违背开闭原则的。
模式应用
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。
- 一个系统有多于一个的产品族,而系统只消费其中某一族的产品。
- 同属于同一个产品族的产品是在一起使用的。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。