定义
有称作“工具箱”模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
使用场景
一个系列要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当要强调一系列相关的产品对象的设计以便进行联合使用时。
当要提供一个产品类库,而只要显示它们的接口而不是实现时。
简单的说就是适用于客户端中经常需要切换配置(交换产品系列)时,客户端通过抽象接口来操纵实例,具体的类名不会出现在客户端中。
优缺点分析
优点 | 缺点 | |
简单工厂模式 |
|
|
工厂方法模式 |
|
|
抽象工厂模式 |
|
|
角色及其职责
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
抽象工厂模式UML图
应用场景及代码分析
程序员小明使用工厂方法模式对面包店进行了一番改造,效果显著,加入新的面包时变得容易了,可是,小明的生意做的越来越大,并不满足只卖面包了,他想在自己的店里面加入自己喜欢吃的披萨,于是按照他开始了编码的道路
首先将我们的面包师和面包写出来:
//面包师,作为父类
public class BreadMaker {
//生产面包
public void getBread(){
//等待孩子们生产出来
}
}
//奶油面包
public class ButterBread extends BreadMaker{
// 覆盖父类方法
@Override
public void getBread() {
// TODO Auto-generated method stub
super.getBread();
System.out.println("烤出了奶油面包");
}
}
//巧克力面包
public class ChocolateBread extends BreadMaker{
// 覆盖父类方法
@Override
public void getBread() {
// TODO Auto-generated method stub
super.getBread();
System.out.println("烤出了巧克力面包");
}
}
//香蕉面包
public class BananaBread extends BreadMaker{
// 覆盖父类方法
@Override
public void getBread() {
// TODO Auto-generated method stub
super.getBread();
System.out.println("烤出了香蕉面包");
}
}
同样,类似于面包师和面包,也创建出了披萨师和各种披萨
//披萨师 各种披萨的父类
public class PizzaMaker {
//制作披萨
public void GetPizza(){
}
}
//奶油披萨
public class ButterPizza extends PizzaMaker {
@Override
public void GetPizza() {
// TODO Auto-generated method stub
super.GetPizza();
System.out.println("制作出了奶油披萨");
}
}
//巧克力披萨
public class ChocolatePizza extends PizzaMaker {
@Override
public void GetPizza() {
// TODO Auto-generated method stub
super.GetPizza();
System.out.println("制作出了巧克力披萨");
}
}
//香蕉披萨
public class BananaPizza extends PizzaMaker {
@Override
public void GetPizza() {
// TODO Auto-generated method stub
super.GetPizza();
System.out.println("制作出了香蕉披萨");
}
}
写到这里,按照之前工厂方法模式的方法,还需要添加新的工厂接口和3个披萨实体类对应的工厂实体类,小明突然发现这样做的成本太大了,回头想了想,原来披萨和面包的制作方法都是相似的嘛,完全可以放在一起制作啊,对于顾客来说,他们并不关心面包和披萨在哪里做出来的,关心的是面包和披萨的直接、快速取得。于是在同一个工厂里加入了披萨工厂。
//工厂接口
public interface IFactory {
BreadMaker createBread();
//增加了返回披萨实例的接口方法
PizzaMaker createPizzer();
}
//奶油面包和奶油披萨的工厂方法实现
public class ButterBreadFactory implements IFactory{
@Override
public BreadMaker createBread() {
//返回奶油面包实例
return new ButterBread();
}
@Override
public PizzaMaker createPizzer() {
// 返回奶油披萨实例
return new ButterPizza();
}
}
//巧克力面包和巧克力披萨的工厂方法实现
public class ChocolateBreadFactory implements IFactory{
@Override
public BreadMaker createBread() {
//返回巧克力面包实例
return new ButterBread();
}
@Override
public PizzaMaker createPizzer() {
// 返回巧克力披萨实例
return null;
}
}
//香蕉面包和香蕉披萨的工厂方法实现
public class BananaBreadFactory implements IFactory{
@Override
public BreadMaker createBread() {
//返回香蕉面包实例
return new ButterBread();
}
@Override
public PizzaMaker createPizzer() {
//返回香蕉披萨实例
return null;
}
}
现在小明又开始重新开张了:
//抽象工厂模式测试
public class AbstractFactoryTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("小明面包披萨店开始营业!");
BreadMaker breadMaker = null;
PizzaMaker pizzaMaker = null;
IFactory breadFactory = null;
System.out.println("顾客要一个奶油面包");
//根据需要实例化接口
breadFactory = new ButterBreadFactory();
breadMaker =breadFactory.createBread();
breadMaker.getBread();
System.out.println("顾客要一个奶油披萨");
pizzaMaker =breadFactory.createPizzer();
pizzaMaker.GetPizza();
}
}
输出结果:
小明面包披萨店开始营业!
顾客要一个奶油面包
烤出了奶油面包
顾客要一个奶油披萨
制作出了奶油披萨