一、工厂模式概述
属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂 。
二、使用场景
1.对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。
2.类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
三、简单(静态)工厂模式
一个栗子:
我喜欢吃面条,面条有很多种,声明一个接口,让不同的面条通过实现接口展示自己的特点,这是产品的接口。
public interface INoodles {
void descNeed();
}
先来一份兰州拉面(具体的产品类):
public class LzNoodleImp implements INoodles {
@Override
public void descNeed() {
System.out.println("兰州拉面牛肉粒真多!");
}
}
程序员加班必备也要吃泡面(具体的产品类):
public class PaoMianImp implements INoodles {
@Override
public void descNeed() {
System.out.println("泡面是真的好次,还便宜!");
}
}
我最爱吃的是海鲜牛肉面(也是具体的产品类):
public class MyLoveNoddleImp implements INoodles {
@Override
public void descNeed() {
System.out.println("最爱吃的当然是妈妈做的海鲜牛肉面。");
}
}
准备工作做完了,我们来到一家“简单面馆”(简单工厂类),菜单如下:
enum Noodle {
LzNoodle, PaoMian, MyLoveNoddle,
}
public class SimpleNoodlesFactory {
public static INoodles createNoodles(Noodle noodle) {
switch (noodle) {
case LzNoodle:
return new LzNoodleImp();
case PaoMian:
return new PaoMianImp();
case MyLoveNoddle:
default:
return new MyLoveNoddleImp();
}
}
}
简单面馆就提供三种面条(产品),你说你要啥,他就给你啥。这里我点了一份干扣面:
public class ChooseTest {
public static void main(String[] args) {
//简单工厂模式测试
INoodles noodles=SimpleNoodlesFactory.createNoodles(Noodle.MyLoveNoddle);
noodles.descNeed();
}
}
//输出:
四、多方法工厂(常用)
简单工厂有这样的缺点:不同的产品需要不同额外参数的时候不支持,容错率不高。
而多方法的工厂模式为不同产品,提供不同的生产方法,使用时需要哪种产品就调用该种产品的方法,使用方便、容错率高。
① 工厂如下:
public class MultiMethodfactory {
/**
* 生产泡面
*/
public static INoodles createPm() {
return new PaoMianImp();
}
/**
* 生产兰州拉面
*/
public static INoodles createLz() {
return new LzNoodleImp();
}
/**
* 生产海鲜牛肉面
*/
public static INoodles createMyNooddle() {
return new MyLoveNoddleImp();
}
}
② 测试:
public class ChooseTest {
public static void main(String[] args) {
//多方法工厂模式测试
INoodles lz=MultiMethodfactory.createLz();
lz.descNeed();
INoodles pm=MultiMethodfactory.createPm();
pm.descNeed();
INoodles my=MultiMethodfactory.createMyNooddle();
my.descNeed();
}
}
③ 输出:
五、抽象工厂
抽象工厂是多产品系 (貌似也有产品家族的说法)。
举个例子来说,每个店(工厂)不仅仅卖面条,还提供饮料卖。
提供饮料卖,饮料是产品,先抽象一个产品类,饮料:
public abstract class IDrinks {
//描述每种饮料价钱
public abstract void prices();
}
1 .实现两个具体产品类:
① 可乐:
public class ColaDrinks extends IDrinks {
@Override
public void prices() {
System.out.println("可乐三块");
}
}
② 多喝烫水:
public class WaterDrinks extends IDrinks {
@Override
public void prices() {
System.out.println("和我一样的穷光蛋都喝水,不要钱~!");
}
}
2.抽象饭店(抽象工厂类):
public abstract class AbstractFoodFactory {
//生产面条
public abstract INoodles createNoodles();
//生产饮料
public abstract IDrinks createDrinks();
}
① 蓝天大酒店(具体工厂类)
public class LzlmFoodFactory extends AbstractFoodFactory {
@Override
public INoodles createNoodles() {
return new LzNoodles();//卖兰州拉面
}
@Override
public IDrinks createDrinks() {
return new WaterDrinks();//卖水
}
}
② KFC(具体工厂类):
public class KFCFoodFactory extends AbstractFoodFactory {
@Override
public INoodles createNoodles() {
return new PaoNoodles();//KFC宅急超级泡面
}
@Override
public IDrinks createDrinks() {
return new ColaDrinks();//卖可乐
}
}
3.使用:
AbstractFoodFactory abstractFoodFactory1 = new KFCFoodFactory();
abstractFoodFactory1.createDrinks().prices();
abstractFoodFactory1.createNoodles().desc();
abstractFoodFactory1= new LzlmFoodFactory();
abstractFoodFactory1.createDrinks().prices();
abstractFoodFactory1.createNoodles().desc();
4.输出:
六、工厂模式作用
1.工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用Class B,那么只是调用B的方法,而至于B的实例化,就交给工厂类。
2.工厂模式可以降低代码重复。如果创建B过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。可以把这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的维护。
3.工厂模式可以减少错误,因为工厂管理了对象的创建逻辑,使用者不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误。