代码仓库:https://gitee.com/jerry_top/wm_design_patterns.git
定义
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
为了更清晰地理解抽象工厂模式,需要先引入两个概念:
- 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是水果,其子类有苹果、香蕉,则抽象水果与具体名称的水果之间构成了一个产品等级结构,抽象水果是父类,而具体名称的水果是其子类。
- 产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如香蕉加纯牛奶套餐中的香蕉、纯牛奶,香蕉位于水果产品等级结构中,纯牛奶位于牛奶产品等级结构中。
结构
抽象工厂模式的主要角色如下:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
类图
案例
package top.jerrymo.pattern.factory.abstract_factory;
public abstract class Fruit {
abstract String getName();
void wash(){
System.out.println("洗水果");
}
void cut(){
System.out.println("切水果");
}
}
public class AppleFruit extends Fruit {
@Override
String getName() {
return "苹果";
}
}
public class BananaFruit extends Fruit {
@Override
String getName() {
return "香蕉";
}
}
public abstract class Milk {
abstract String drink();
}
public class PureMilk extends Milk {
@Override
String drink() {
System.out.println("喝纯牛奶");
return "喝纯牛奶";
}
}
public class Yoghurt extends Milk {
@Override
String drink() {
System.out.println("喝酸牛奶");
return "喝酸牛奶";
}
}
public interface FruitFactory {
Fruit create();
Milk drink();
}
/**
* @Auther: jerry
* @Date: 2021-07-03 18:04
* @Description: 香蕉加纯牛奶套餐
*/
public class BananaMilkFactory implements FruitFactory {
@Override
public Fruit create() {
return new BananaFruit();
}
@Override
public Milk drink() {
return new PureMilk();
}
}
/**
* @Auther: jerry
* @Date: 2021-07-03 18:04
* @Description: 苹果加酸奶套餐
*/
public class AppleMilkFactory implements FruitFactory {
@Override
public Fruit create() {
return new AppleFruit();
}
@Override
public Milk drink() {
return new Yoghurt();
}
}
public class Client {
public static void main(String[] args) {
FruitFactory fruitFactory = new AppleMilkFactory();
Fruit fruit = fruitFactory.create();
Milk milk = fruitFactory.drink();
System.out.println(fruit.getName());
fruit.wash();
fruit.cut();
milk.drink();
}
}
输出:
苹果
洗水果
切水果
喝酸牛奶
注:工厂组合了不同的水果和不同的牛奶
总结
- 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为(如把Client 的AppleMilkFactory改成BananaMilkFactory)。
- 缺点:在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
NEXT
下次会对建造者模式进行分析,欢迎点赞、关注、收藏,谢谢。
读书百遍,其义自见。我是二十三月,下次见。