场景
-
随着水果的种类增加,对水果的需求量也增加,由于每次都要客户自己来果园采摘,对客户来说及其不友好,这个时候peter就干起了网上水果店的生意。因为邮寄水果需要包装,这个时候,产品就分为了2个系列:一个水果系列,一个包装盒系列。就相当于水果有自己的水果工厂,包装盒有包装盒工厂。
-
但是网店还没有开多久就收到了客户的投诉,说明明买的是苹果,却给我送来芒果,那谁知道客户还对芒果过敏,这使得peter赔了一笔钱还得到了差评。于是peter就去工厂查找原因,刚好就看到小王在包装芒果的时候,TMD拿了苹果的盒子。害!原来小王是个憨憨,因为不同种类的盒子都放在那个地方,一不小心就拿错了,peter大怒,当即对小王做罚款250元的惩罚。
- 在经过上面的事情之后,peter就想了一个法子,让苹果和苹果包装盒呆在一起,桔子和桔子包装盒呆在一起,这样应该就不会出错了,于是就有了下面的方式。当使用不同工厂时,返回对应这一族的产品系列。
抽象工厂模式
定义
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。即当一个类别的产品还有多个系列区分时,为了按系列生产商品,使用抽象工厂区分。
结构
-
抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
-
具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
-
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
-
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。
UML类图
代码实现
实现
水果&包装接口(抽象产品)
public interface Fruit {
public void getFruit();
}
public interface Bag {
//打包
void pack();
}
水果&包装种类(具体产品)
/**
* 苹果
*/
public class Apple implements Fruit {
@Override
public void getFruit() {
System.out.print("我是苹果");
}
}
/**
* 香蕉
*/
public class Banana implements Fruit {
@Override
public void getFruit() {
System.out.print("我是香蕉");
}
}
/**
* 桔子
*/
public class Orange implements Fruit {
@Override
public void getFruit() {
System.out.print("我是桔子");
}
}
-----------------------------------------------------------------------------------------
/**
* 苹果包装
*/
public class AppleBag implements Bag {
@Override
public void pack() {
System.out.print("--我使用苹果盒包装");
}
}
/**
* 香蕉包装
*/
public class BananaBag implements Bag {
@Override
public void pack() {
System.out.print("--我使用香蕉盒包装");
}
}
/**
* 桔子包装
*/
public class OrangeBag implements Bag {
@Override
public void pack() {
System.out.print("--我使用桔子盒包装");
}
}
工厂方法(抽象工厂)
/**
* 抽象工厂接口
*/
public abstract class AbstractFactory {
/**
* 获取水果
*/
public abstract Fruit getFruit();
/**
* 包装水果
*/
public abstract Bag getBag();
}
工厂方法(具体产品)
/**
* 苹果工厂
*/
public class AppleFactory extends AbstractFactory {
@Override
public Fruit getFruit() {
return new Apple();
}
@Override
public Bag getBag() {
return new AppleBag();
}
}
/**
* 香蕉工厂
*/
public class BananaFactory extends AbstractFactory {
@Override
public Fruit getFruit() {
return new Banana();
}
@Override
public Bag getBag() {
return new BananaBag();
}
}
/**
* 桔子工厂
*/
public class OrangeFactory extends AbstractFactory {
@Override
public Fruit getFruit() {
return new Orange();
}
@Override
public Bag getBag() {
return new OrangeBag();
}
}
客户端调用
public class TestClient {
public static void main(String[] args) {
//初始化工厂
//AbstractFactory factory = new BananaFactory();
AbstractFactory factory = new BananaFactory();
Fruit apple = factory.getFruit();
apple.getFruit();
Bag bag = factory.getBag();
bag.pack();
}
}
结果
我是香蕉--我使用香蕉盒包装
优缺点
优点
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码,满足开闭原则。
缺点
- 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
抽象工厂模式的本质
抽象工厂模式的本质:选择产品簇(族)实现
使用场景
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
- 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
模式的扩展
抽象工厂模式的扩展有一定的“开闭原则”倾斜性:
-
当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
-
当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。
另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。