抽象工厂模式
工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物,电视机厂只生产电视机等。这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合性的工厂,能生产许多等级(种类)的产品,如电器厂既可以生产电视机又可以生产洗衣机或空调,大学既有软件工程专业又有生物专业等。
本节主要介绍的抽象工厂模式或将考虑多等级产品的生产,将同一个具体工厂所生产的不同等级的一个产品称为一个产品族,简单理解所谓的产品族就是不同的产品,一般是由一个公司生产的,产品等级就是同一个产品的不同实现
概念
是一种为访问类提供一个创建一组相关或者相互依赖对象的接口,且访问类无需指定所要产品的具体类就能得到同族的不同等级的产品的模式结构,抽象模式是工厂方法模式的升级版本,工厂方法模式只能生产一个等级的产品,而抽象工厂模式可生产多个等级的产品
结构
抽象工厂模式的主要角色如下:
- 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
- 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
- 抽象产品:定义了产品的规范,描述产品的主要特性和功能,抽象工厂模式有多个抽象产品
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间时多对一的关系
实现
现咖啡店业务发生变化,不仅要生产咖啡还要生产甜点,如提拉米苏,抹茶慕斯等,要是按照工厂方法模式需要定义提拉米苏类,抹茶慕斯类,提拉米苏工厂,抹茶慕斯工厂,甜点工厂,很容易发生类爆炸情况。其中拿铁咖啡,美式咖啡是一个产品等级,都是咖啡;提拉米苏,抹茶慕斯也是一个产品等级;拿铁咖啡和提拉米苏是同一个产品族(意大利风味),美式咖啡和抹茶慕斯是同一产品族(美式风味)。所以这个案例就可以使用抽象工厂模式来实现
抽象工厂
/**
* 抽象工厂
*/
public interface DessertFactory {
//生产咖啡的功能
Coffee createCoffee();
//生产甜品的功能
Dessert createDessert();
}
美式风味工厂
/**
* 美式风味工厂
*/
public class AmericanDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
@Override
public Dessert createDessert() {
return new MatchaMousse();
}
}
意大利风味工厂
/**
*意大利风味工厂
*/
public class ItalyDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
@Override
public Dessert createDessert() {
return new Trimisu();
}
}
抽象产品类-咖啡
/**
* 抽象产品
*/
public abstract class Coffee {
public abstract String getName();
//加糖
public void addSugar(){
System.out.println("加糖");
}
// 加奶
public void addMile(){
System.out.println("加奶");
}
}
抽象产品类-甜品
/**
* 抽象甜品类
*/
public abstract class Dessert {
public abstract void show();
}
具体产品-美式风味(属于同一产品族不同产品)
/**
* 美式咖啡
*/
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
/**
* 抹茶慕斯甜品
*/
public class MatchaMousse extends Dessert{
@Override
public void show() {
System.out.println("抹茶慕斯");
}
}
具体产品-意大利式风味(属于同一产品族不同产品)
/**
* 拿铁咖啡
*/
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
/**
* 提拉米苏甜品类
*/
public class Trimisu extends Dessert{
@Override
public void show() {
System.out.println("提拉米苏");
}
}
测试类
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
DessertFactory factory = new AmericanDessertFactory();
Coffee coffee = factory.createCoffee();
Dessert dessert = factory.createDessert();
System.out.println(coffee.getName());
dessert.show();
}
}
优点
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用一个产品族中的对象
缺点
当产品中需要增加一个新的产品时,所有的工厂都需要进行修改
使用场景
- 当需要创建的对象是一系列相互关联或者相互依赖的产品族时,如电器厂中的电视机,洗衣机,空调等
- 系统中有多个产品族,但是每次只使用其中的某一产品族,如有人只喜欢一个品牌的衣服和鞋子
- 系统中提供了产品的类库,且所有的产品接口相同,客户端不依赖产品实例的创建细节和内部结构