要想明白这三玩意的区别就需要知道这三玩意的优缺点;
之所以有三种工厂模式,就说明它们各有所长,能解决不同场景的问题;
一、简单工厂模式
UML图
代码
public class MobileFactory {
public static Mobile getMobile(String brand){
switch (brand){
case "apple":
return new AppleMobile();
case "huawei":
return new HuaweiMobile();
default: throw new RuntimeException("参数不合法");
}
}
}
public interface Mobile {
String getBrand();
}
public class AppleMobile implements Mobile {
@Override
public String getBrand() {
return "apple";
}
}
public class HuaweiMobile implements Mobile {
@Override
public String getBrand() {
return "huawei";
}
}
public class Client {
public static void main(String[] args) {
Mobile appleMobile = MobileFactory.getMobile("apple");
System.out.println(appleMobile.getBrand());
Mobile huaweiMobile = MobileFactory.getMobile("huawei");
System.out.println(huaweiMobile.getBrand());
}
}
//如果想增加小米手机的生产,则需要修改 Factory类的代码:public class MobileFactory {
public static Mobile getMobile(String brand){
switch (brand){
case "apple":
return new AppleMobile();
case "huawei":
return new HuaweiMobile();
case "xiaomi":
return new XiaomiMobile();
default: throw new RuntimeException("参数不合法");
}
}
}
优点
不需要定义工厂接口,往往直接写一个工厂实现类,方法往往也是静态的,客户端用起来非常方便快捷。
缺点
不符合开闭原则,增加产品种类时需要修改工厂类代码(if else问题),为了解决此缺点,工厂方法模式产生
二、工厂方法模式
UML图
代码
//只生产一种产品,生产不同的产品需要不同的工厂
public class Client {
public static void main(String[] args) {
IFactory factory;
IProduct product;
//华为工厂 生产华为播放器
factory = new FactoryHuawei();
product = factory.getProduct();
product.sing();
//小米工厂 生产小米播放器
factory = new FactoryXiaomi();
product = factory.getProduct();
product.sing();
}
}
public interface IFactory {
IProduct getProduct();
}
public interface IProduct {
/**
* 这个产品可以唱歌
*/
void sing();
}
public class FactoryHuawei implements IFactory {
@Override
public IProduct getProduct() {
return new ProductHuawei();
}
}
public class FactoryXiaomi implements IFactory {
@Override
public IProduct getProduct() {
return new ProductXiaomi();
}
}
public class ProductHuawei implements IProduct {
@Override
public void sing() {
System.out.println("hi,我是华为音乐播放器,我正在唱歌。。。。。");
}
}
public class ProductXiaomi implements IProduct {
@Override
public void sing() {
System.out.println("hi,我是小米音乐播放器,我正在唱歌。。。。。");
}
}
优点
解决了简单工厂模式违反“开闭原则”的问题,增加产品的种类不需要修改已有代码。直接实现一个工厂接口即可。
缺点
在生产多种商品的情况下,工厂接口和实现类的数量会大大增加。但是每个工厂目前只有一个车间只能生产一种产品,老板不服,因为他觉得一个工厂只有一个车间太浪费了,我要在一个工厂里开多个车间生产不同的产品
三、抽象工厂模式
UML图
代码
//用于一个系列或风格的产品生成
public class Client {
public static void main(String[] args) {
System.out.println("来一套A牌茶具");
FactoryTeaset teasetA = new FactoryTeasetA();
Tea teaA = teasetA.getTea();
Teacup teacupA = teasetA.getTeacup();
Teapot teapotA = teasetA.getTeapot();
teaA.show();
teacupA.show();
teapotA.show();
System.out.println("来一套B牌茶具");
FactoryTeaset teasetB = new FactoryTeasetB();
Tea teaB = teasetB.getTea();
Teacup teacupB = teasetB.getTeacup();
Teapot teapotB = teasetB.getTeapot();
teaB.show();
teacupB.show();
teapotB.show();
}
}
public interface FactoryTeaset {
//生产茶壶
Teapot getTeapot();
//生产茶杯
Teacup getTeacup();
//生产茶叶
Tea getTea();
}
public interface Tea {
void show();
}
public interface Teacup {
void show();
}
public interface Teapot {
void show();
}
//A品牌茶具工厂
public class FactoryTeasetA implements FactoryTeaset {
@Override
public Teapot getTeapot() {
return new TeapotA();
}
@Override
public Teacup getTeacup() {
return new TeacupA();
}
@Override
public Tea getTea() {
return new TeaA();
}
}
public class TeaA implements Tea {
@Override
public void show() {
System.out.println("我是A牌茶叶");
}
}
public class TeacupA implements Teacup {
@Override
public void show() {
System.out.println("我是A牌茶杯");
}
}
public class TeapotA implements Teapot {
@Override
public void show() {
System.out.println("我是A牌茶壶");
}
}
//B品牌茶具工厂
public class FactoryTeasetB implements FactoryTeaset {
@Override
public Teapot getTeapot() {
return new TeapotB();
}
@Override
public Teacup getTeacup() {
return new TeacupB();
}
@Override
public Tea getTea() {
return new TeaB();
}
}
public class TeaB implements Tea {
@Override
public void show() {
System.out.println("我是B牌茶叶");
}
}
public class TeacupB implements Teacup {
@Override
public void show() {
System.out.println("我是B牌茶杯");
}
}
public class TeapotB implements Teapot {
@Override
public void show() {
System.out.println("我是B牌茶壶");
}
}
优点
解决了类爆炸问题,一个工厂有多个车间,可以生产一套产品、一个系列产品,并且这些产品品牌一致、风格一致、看着高大上。从来不会由于失误把A品牌的茶杯和B品牌的茶壶组合在一起使用。
缺点
一天老板想增加“茶桌”生产线,需要在厂里增加一个生产车间,好在它并不需要修改其它车间,只需要增加一个新的车间。其它茶具老板一听说行业规范变了,竞争对手已经增加了“茶桌”,他也必须跟上,否则就落伍了,不符合行业规范可是会被取缔啊。
四、总结
1、简单工厂不需要工厂接口,工厂类往往提供静态方法,简单方便。但是存在不断增加if else问题,不符合开闭原则。
2、工厂方法模式完全符合开闭原则,但会产生大量的接口和实现类,俗称“类爆炸”
3、抽象工厂模式不会产生大量的接口和实现类,但是在扩展性上又不完全符合开闭原则,但不会存在if else问题。
4、所以老吕认为:抽象工厂模式解决了“简单工厂模式”的if else问题,同时解决了 “工厂方法模式”的类爆炸问题,但在开闭原则上有一定的损害,这可能就是“折中”的意义吧,世界上本没有完美的方案,实际使用中还是要根据业务场景、团队情况等综合判断来决定使用哪种模式,并不是越复杂越好也不是越完美越好。