转载地址:http://blog.youkuaiyun.com/lingyun_blog/article/details/41479563
追MM少不了请吃饭了,麦当劳的套餐和肯德基的套餐都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“两个B套餐”就行了。麦当劳和肯德基就是B套餐的Abstract Factory, B套餐里含有汉堡, 鸡翅和饮料. 麦当劳或肯德基会根据B套餐的规格, 让汉堡Factory, 鸡翅Factory, 饮料Factory分别生产对应B套餐的材料.
定义
有称作“工具箱”模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
使用场景
一个系列要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当要强调一系列相关的产品对象的设计以便进行联合使用时。
当要提供一个产品类库,而只要显示它们的接口而不是实现时。
简单的说就是适用于客户端中经常需要切换配置(交换产品系列)时,客户端通过抽象接口来操纵实例,具体的类名不会出现在客户端中。
优缺点分析
优点 缺点
简单工厂模式
分离了客户端和后台逻辑,使得客户端无需关心后台的实现,去除了客户端与具体产品的依赖,增强了移植性能。
实现简单,易于操作。
违背了开放-封闭原则
添加新产品时比较麻烦
工厂方法模式
是简单工厂模式的升级
易于添加新产品
后台模块契合了开放-封闭原则
新产品的添加带来了大量新的类的创建,增加了工作量
客户端部分仍然违反开放-封闭原则,只是后台判断逻辑挪到了前台
抽象工厂模式
分离了具体的类,工厂封装了创建产品对象的责任和过程,将客户端和类的实现分离,客户端通过抽象接口操纵实例
易于交换产品系列,一个具体的工厂类在一个应用中仅在初始化时出现一次,改变一个应用的具体工厂变得容易
有利于产品的一致性,一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一系列中的对象
难以支持新种类的产品,抽象工厂接口确定了可以被创建的产品集合。新种类产品加入需要扩展抽象工厂接口,这就涉及到了接口本身和所有实现类的改变
角色及其职责
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
抽象工厂模式UML图
应用场景及代码分析
程序员小明使用工厂方法模式对面包店进行了一番改造,效果显著,加入新的面包时变得容易了,可是,小明的生意做的越来越大,并不满足只卖面包了,他想在自己的店里面加入自己喜欢吃的披萨,于是按照他开始了编码的道路
首先将我们的面包师和面包写出来:
[java] view plaincopy
//面包师,作为父类
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("烤出了香蕉面包");
}
}
同样,类似于面包师和面包,也创建出了披萨师和各种披萨
[java] view plaincopy
//披萨师 各种披萨的父类
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个披萨实体类对应的工厂实体类,小明突然发现这样做的成本太大了,回头想了想,原来披萨和面包的制作方法都是相似的嘛,完全可以放在一起制作啊,对于顾客来说,他们并不关心面包和披萨在哪里做出来的,关心的是面包和披萨的直接、快速取得。于是在同一个工厂里加入了披萨工厂。
[java] view plaincopy
//工厂接口
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;
}
}
现在小明又开始重新开张了:
[java] view plaincopy
//抽象工厂模式测试
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();
}
}
输出结果:
小明面包披萨店开始营业!
顾客要一个奶油面包
烤出了奶油面包
顾客要一个奶油披萨
制作出了奶油披萨