简单工厂、工厂方法、抽象工厂模式-这仨货的区别

7a744a67c16180849308456cf88fc0f6.jpeg

要想明白这三玩意的区别就需要知道这三玩意的优缺点;

之所以有三种工厂模式,就说明它们各有所长,能解决不同场景的问题;

一、简单工厂模式

UML图

d4947efe7f5e040ce42be86425338136.png

代码

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图

e94816d4dc786603190ddceef56b1a28.png

代码

//只生产一种产品,生产不同的产品需要不同的工厂
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图

a2246f02bca769bbbe80efbc377e3163.png

代码

//用于一个系列或风格的产品生成
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问题,同时解决了 “工厂方法模式”的类爆炸问题,但在开闭原则上有一定的损害,这可能就是“折中”的意义吧,世界上本没有完美的方案,实际使用中还是要根据业务场景、团队情况等综合判断来决定使用哪种模式,并不是越复杂越好也不是越完美越好。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕哥架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值