与单例模式一样,工厂模式也属于创建型模式。这里说的工厂模式,是一个泛化的概念,具体分为下面几种:👇
前几天,我和几个同为程序员的朋友,讨论了不罗代码了去做什么,几个朋友一致认为要去开火锅店。所以,在这里我就以开火锅店为例子,来讲一下什么是工厂模式。
前面说了,我要开火锅店。那首先我就要考虑怎么开了。是找个店面,自己装修呢。还是采取直接加盟火锅店的方式去做呢。
所谓静态工厂模式,就是直接加盟店面这种方式,店面的装修风格,火锅原料都为你准备好了,你只需要选择哪个品牌加盟就可以了。
类比到java中,就是我们常用的那些StringUtils工具类啊等等的实现方式。比如要判断字符串是否为空,直接调用StringUtils.isEmpty(...)。
继续前面的开火锅店啊,那我现在就开一个火锅店。朋友起了一个名字叫---锅火火锅。
首先我们简单抽象一下火锅哈。
/**
* 火锅抽象类
*
* @author aysaml
* @date 2019-10-14
*/
public abstract class AbstractHuoguo {
protected String name;
public void prepareFoods(){
System.out.println("准备火锅食材~~~");
}
public void plate(){
System.out.println("摆盘,加干冰~~~");
}
public void serving(){
System.out.println("上菜~~~");
}
}
猝不及防的代码,哈哈哈。没关系,下面我们都这个套路。
想好怎么做火锅了之后,我们分一下火锅的种类啊。
/**java
* 变态辣火锅
*
* @author aysaml
* @date 2019-10-14
*/
public class AbnormalHotHuoguo extends AbstractHuoguo{
public AbnormalHotHuoguo() {
this.name = "变态辣火锅";
}
}
/**
* 甜味火锅
*
* @author aysaml
* @date 2019-10-14
*/
public class SweetHuoguo extends AbstractHuoguo{
public SweetHuoguo() {
this.name = "甜味火锅";
}
}
火锅的事情解决完了,我们就开一个火锅店了。
/**
* 锅火火锅店
*
* @author aysaml
* @date 2019-10-14
*/
public class GuohuoHuoguoStore {
/**
* 根据顾客要求提供不同类型的火锅
*
* @param type
* @return
*/
public AbstractHuoguo provideHuoguo(String type) {
AbstractHuoguo huoguo = null;
if ("变态辣".equals(type)) {
huoguo = new AbnormalHotHuoguo();
} else if ("甜味".equals(type)) {
huoguo = new SweetHuoguo();
}
//准备食材,摆盘,上菜
{
huoguo.prepareFoods();
huoguo.plate();
huoguo.serving();
}
return huoguo;
}
}
好了,我们的火锅店经营了一段时间后发现顾客对火锅的口味要求多种多样,我们只有两种显然不能满足顾客的口味。所以管理层决定,每个一个星期推出不同口味的火锅。那基于现有的火锅店我们怎么实现呢?查看上面,每推出一种口味,我们就要对提供火锅provideHuoguo(String type) 方法进行不断的修改。那作为一个老板,我只想关心钱怎么来,所以我雇佣了一个经理来管理,让他来管理制作火锅的过程:
/**
* 火锅经理
*
* @author aysaml
* @date 2019-10-14
*/
public class SimpleHuoguoFactory {
/**
* 根据客人要求提供不同类型的火锅
*
* @param type
* @return
*/
public AbstractHuoguo createHuoguo(String type) {
AbstractHuoguo huoguo = null;
if ("变态辣".equals(type)) {
huoguo = new AbnormalHotHuoguo();
} else if ("甜味".equals(type)) {
huoguo = new SweetHuoguo();
}
//准备食材,摆盘,上菜
{
huoguo.prepareFoods();
huoguo.plate();
huoguo.serving();
}
return huoguo;
}
}
那相应的,现在火锅店的管理层发生了变动:
/**
* 锅火火锅店
*
* @author aysaml
* @date 2019-10-14
*/
public class GuohuoHuoguoStore {
/**
* 每个火锅店要有一个经理
*/
private SimpleHuoguoFactory factory;
/**
* 那我每开一个火锅店就要招一个经理
*
* @param factory
*/
public GuohuoHuoguoStore(SimpleHuoguoFactory factory) {
this.factory = factory;
}
/**
* 根据客人要求提供不同类型的火锅
*
* @param type
* @return
*/
public AbstractHuoguo provideHuoguo(String type) {
AbstractHuoguo huoguo = factory.createHuoguo(type);
{
huoguo.prepareFoods();
huoguo.plate();
huoguo.serving();
}
return huoguo;
}
}
这样之后,再加什么口味的火锅也不要和我这个老板说了,直接找经理(SimpleHuoguoFactory )就行了,这就是简单工厂模式。
简单工厂模式中可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
它由下面三部分组成:
在以下情况下可以使用简单工厂模式:
工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
带着上面这句话,我们再次回到火锅店吃火锅。
聘用了经理之后,经理的能力不错,生意贼拉的好,那我们就要扩张了啊,开分店,融资上市啊~
经公司管理层(我)决定,大笔一挥,在重庆开一百家分店。
好,那我们先开一家。现在有了分店,所以在原来的基础上面我们抽象出总店。
/**
* 锅火火锅店总店
*
* @author aysaml
* @date 2019-10-14
*/
public abstract class GuohuoHuoguoStore {
public abstract AbstractHuoguo createHuoguo(String type);
/**
* 根据客人要求提供不同类型的火锅
*
* @param type
* @return
*/
public AbstractHuoguo provideHuoguo(String type) {
AbstractHuoguo huoguo = createHuoguo(type);
{
huoguo.prepareFoods();
huoguo.plate();
huoguo.serving();
}
return huoguo;
}
}
再开一个分店:
/**
* 锅火火锅西安分店
*
* @author aysaml
* @date 2019-10-14
*/
public class XianGuohuoHuoguoStore extends GuohuoHuoguoStore{
@Override
public AbstractHuoguo createHuoguo(String type) {
AbstractHuoguo huoguo = null;
if("辣椒".equals(type)){
huoguo = new AbnormalHotHuoguo();
}
return huoguo;
}
}
好了,这样,我们就开完了重庆分店。总店只是定义了,你开火锅店就要做火锅,具体的制作过程总店不管,我们下放到各个分店加入分店自己的特色实现,这就是工厂方法模式。
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
仅仅看上面的一句莫名其妙的定义,真的是...
这个相对有点复杂,所以我们不开火锅店了,😝。
本例子采用一个汽车代工厂造汽车的例子。假设我们是一家汽车代工厂商,我们负责给奔驰和特斯拉两家公司制造车子。我们简单的把奔驰车理解为需要加油的车,特斯拉为需要充电的车。其中奔驰车中包含跑车和商务车两种,特斯拉同样也包含奔驰车和商务车。
以上场景,我们就可以把跑车和商务车分别对待,对于跑车有单独的工厂创建,商务车也有单独的工厂。这样,以后无论是再帮任何其他厂商造车,只要是跑车或者商务车我们都不需要再引入工厂。同样,如果我们要增加一种其他类型的车,比如越野车,我们也不需要对跑车或者商务车的任何东西做修改。
下面是抽象产品,奔驰车和特斯拉车:
public interface BenzCar {
//加汽油
public void gasUp();
}
public interface TeslaCar {
//充电
public void charge();
}
下面是具体产品,奔驰跑车、奔驰商务车、特斯拉跑车、特斯拉商务车:
public class BenzSportCar implements BenzCar {
public void gasUp() {
System.out.println("给我的奔驰跑车加最好的汽油");
}
}
public class BenzBusinessCar implements BenzCar{
public void gasUp() {
System.out.println("给我的奔驰商务车加一般的汽油");
}
}
public class TeslaSportCar implements TeslaCar {
public void charge() {
System.out.println("给我特斯拉跑车冲满电");
}
}
public class TeslaBusinessCar implements TeslaCar {
public void charge() {
System.out.println("不用给我特斯拉商务车冲满电");
}
}
下面是抽象工厂:
public interface CarFactory {
public BenzCar getBenzCar();
public TeslaCar getTeslaCar();
}
下面是具体工厂:
public class SportCarFactory implements CarFactory {
public BenzCar getBenzCar() {
return new BenzSportCar();
}
public TeslaCar getTeslaCar() {
return new TeslaSportCar();
}
}
public class BusinessCarFactory implements CarFactory {
public BenzCar getBenzCar() {
return new BenzBusinessCar();
}
public TeslaCar getTeslaCar() {
return new TeslaBusinessCar();
}
}
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。
抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。