要求:由一个特定的工厂提供所需的对象,由工厂来完成对象的创建
工厂模式一般分为三种:简单工厂模式,工厂方法模式,抽象工厂模式
其中简单工厂模式不属于23种设计模式
简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)
简单工厂模式就是 定义了一个创建对象的类,让这个类来封装实例化对象的行为
特点:只有一个工厂,根据入参,通过硬编码的方式创建所需对象。不方便扩展,不建议用
假设:我要开一个小店,卖牛肉包子,猪肉包子
分析上述需求,我们用简单工厂模式实现,如下:
/**
* 抽象包子类
**/
public interface Bun {
void pack();//打包
}
/*************************************************************************/
public class BeefBun implements Bun {
public BeefBun() {
System.out.println("包牛肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
public class PorkBun implements Bun {
public PorkBun() {
System.out.println("包猪肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
/**
* 简单包子工厂
**/
public class BunFactory {
public Bun createBun(String type){
Bun bun = null;
switch (type){
case "beef":
bun = new BeefBun();
break;
case "pork":
bun = new PorkBun();
break;
default:
throw new RuntimeException("我不会做");
}
return bun;
}
}
上述代码通过包子工厂 BunFactory,根据入参选择生产不同种类的包子,实现了工厂模式,隐藏了生产细节
测试代码如下:
public class MyStore01 {
/**
* 简单工厂模式
* 只有一个工厂
*/
BunFactory factory = new BunFactory();
public Bun order(String type){
Bun bun = factory.createBun(type);
//打包...等操作
bun.pack();
return bun;
}
}
/*************************************************************************/
@Test
public void client01(){
MyStore01 myStore = new MyStore01();
Bun beef = myStore.order("beef");
Bun pork = myStore.order("pork");
}
输出:
包牛肉包
包猪肉包
上述代码完成了简单工厂模式的使用,可以隐藏实例的创建,通过工厂对实例进行创建。
但是设想一下,如果需要扩展功能怎么办
假设,我的小店 又要做 香菇菜包,那么势必要修改 BunFactory的代码,很明显,这违反了开闭原则。
那么接下来我们看下 工厂方法模式
定义多个工厂,每个工厂生产一种产品
特点:有多个工厂,工厂抽象化,一个具体工厂只生产一个具体产品,容易类爆炸
还是针对上面的需求,开一个小店,卖牛肉,猪肉包子
使用工厂方法模式,实现如下:
/**
* 抽象包子类
**/
public interface Bun {
void pack();//打包
}
/*************************************************************************/
public class BeefBun implements Bun {
public BeefBun() {
System.out.println("包牛肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
public class PorkBun implements Bun {
public PorkBun() {
System.out.println("包猪肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
/**
* 抽象包子工厂
*/
public interface BunFactory {
Bun createBun();
}
/*************************************************************************/
/**
* 牛肉包子工厂
*/
public class BeefBunFactory implements BunFactory{
@Override
public Bun createBun() {
return new BeefBun();
}
}
/*************************************************************************/
/**
* 猪肉包子工厂
*/
public class PorkBunFactory implements BunFactory {
@Override
public Bun createBun() {
return new PorkBun();
}
}
测试代码:
public class MyStore02 {
/**
* 工厂方法模式
* 有多个工厂,一个工厂只产一种产品
* @param type
* @return
*/
BunFactory factory;
public void setFactory(BunFactory factory) {
this.factory = factory;
}
public Bun order(){
Bun bun = factory.createBun();
//打包...等操作
bun.pack();
return bun;
}
}
@Test
public void client02(){
MyStore02 myStore = new MyStore02();
myStore.setFactory(new BeefBunFactory());
myStore.order();
myStore.setFactory(new PorkBunFactory());
myStore.order();
}
输出:
包牛肉包
包猪肉包
上述代码完成了 和简单工厂模式相同的功能,
但是使用工厂方法模式,可以不修改原有代码,通过增加工厂类的方式来扩充功能。
例如:我想增加青菜包的业务,只需要实现一个青菜包类 和 青菜包工厂即可
但是,我们再想一下,新增一个功能要加两个类,如果后面业务越来越广泛,类是不是越来越多,是不是 容易类爆炸。
再思考一下,一个工厂只生产一种产品是不是太浪费了。难道又要回到简单工厂模式了?
当然不是,我们可以折中一下,对工厂类进行更深层的抽象。对产品进行划分,让一个工厂可以生产多种产品,这些产品都是同一组的,相关联的。
下面看下抽象工厂模式
提供一个生产一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
抽象工厂模式比工厂方法模式的抽象程度更高。在工厂方法模式中每一个具体工厂只需要生产一种具体产品,但是在抽象工厂模式中一个具体工厂可以生产一组相关的具体产品,这样一组产品被称为产品族。产品族中的每一个产品都分属于某一个产品继承等级结构。
特点:多个工厂,工厂进行更高层次的抽象,每个工厂生产一个产品族(生产一组相关的具体产品)
先引入两个概念:产品族,产品等级结构
在前面的工厂方法模式中,考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机。工厂方法模式只考虑生产同等级(同种类被称为同等级)的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调。而抽象工厂模式就考虑了多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,如图所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。
还是针对我的包子店的需求,我扩充了牛奶的需求。
使用抽象工厂模式开发如下:
/**
* 抽象包子类
**/
public interface Bun {
void pack();//打包
}
/*************************************************************************/
public class BeefBun implements Bun {
public BeefBun() {
System.out.println("包牛肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
public class PorkBun implements Bun {
public PorkBun() {
System.out.println("包猪肉包");
}
@Override
public void pack() {
}
}
/*************************************************************************/
/**
*抽象牛奶类
*/
public interface Milk {
void pack();//打包
}
/*************************************************************************/
public class PureMilk implements Milk{
public PureMilk() {
System.out.println("做一杯纯牛奶");
}
@Override
public void pack() {
}
}
/*************************************************************************/
public class BreakfastMilk implements Milk{
public BreakfastMilk() {
System.out.println("做一杯早餐奶");
}
@Override
public void pack() {
}
}
/*************************************************************************/
/**
*抽象工厂类
*/
public interface Factory {
Bun createBun();
Milk createMilk();
}
/*************************************************************************/
/**
*具体工厂类1号,生产牛肉包和纯牛奶
*/
public class PureBeefFactory implements Factory{
@Override
public Bun createBun() {
return new BeefBun();
}
@Override
public Milk createMilk() {
return new PureMilk();
}
}
/*************************************************************************/
/**
*具体工厂类2号,生产猪肉包和早餐奶
*/
public class BreakfastPorkFactory implements Factory{
@Override
public Bun createBun() {
return new PorkBun();
}
@Override
public Milk createMilk() {
return new BreakfastMilk();
}
}
上述代码中,纯牛奶和牛肉包被看作一个产品族
纯牛奶和早餐奶被看成一个产品等级结构
测试代码:
public class MyStore03 {
/**
* 抽象工厂模式
* 有多个工厂,一个工厂生产一个产品族
* @param type
* @return
*/
Factory factory;
public void setFactory(Factory factory) {
this.factory = factory;
}
public Bun orderBun(){
Bun bun = factory.createBun();
//打包...等操作
bun.pack();
return bun;
}
public Milk orderMilk(){
Milk milk = factory.createMilk();
milk.pack();
return milk;
}
}
/*************************************************************************/
/**
* 抽象工厂模式
*/
@Test
public void client03(){
MyStore03 myStore = new MyStore03();
myStore.setFactory(new PureBeefFactory());
myStore.orderBun();
myStore.orderMilk();
}
输出:
包牛肉包
做一杯纯牛奶
上述抽象工厂实现了一个工厂创建多个产品的功能,与简单工厂类似,自然有简单工厂类似的缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。