设计模式(三)工厂方法模式

一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。不过,在 GoF 的《设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式只被分成了工厂方法和抽象工厂两类。实际上,前面一种分类方法更加常见,所以,在今天的讲解中,我们沿用第一种分类方法。

简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。上篇文章《设计模式(二)简单工厂模式》讲了简单工厂模式,我们今天就来看一下工厂方法模式。

工厂方法模式

工厂方法模式的结构图如下所示:

  • AbstractFactory:抽象工厂类,提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
  • Factory:工厂类,负责实现创建所有实例的内部逻辑。创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • AbstractProduct:抽象产品类,这是简单工厂模式所创建的所有对象的父类。
  • Product:具体产品类,继承自抽象产品类。

下面用代码来实现一下:

  1. 创建抽象产品
abstract class Phone {
    public abstract void start();
}
  1. 创建具体产品
class OppoPhone extends Phone {
    @Override
    public void start() {
        System.out.println("OPPO start");
    }
}

class VivoPhone extends Phone {
    @Override
    public void start() {
        System.out.println("VIVO start");
    }
}

class XiaomiPhone extends Phone {
    @Override
    public void start() {
        System.out.println("XiaoMi start");
    }
}
  1. 创建抽象工厂
abstract class PhoneFactory {
    public abstract Phone createPhone();
}
  1. 具体工厂
class OppoFactory extends PhoneFactory {
    @Override
    public Phone createPhone() {
        return new OppoPhone();
    }
}

class VivoFactory extends PhoneFactory {
    @Override
    public Phone createPhone() {
        return new VivoPhone();
    }
}

class XiaomiFactory extends PhoneFactory {
    @Override
    public Phone createPhone() {
        return new XiaomiPhone();
    }
}
  1. 调用工厂创建产品
public static void main(String[] args) {
        Phone oppoPhone = new OppoFactory().createPhone();
        oppoPhone.start();

        Phone vivoPhone = new VivoFactory().createPhone();
        vivoPhone.start();

        Phone xiaomiPhone = new XiaomiFactory().createPhone();
        xiaomiPhone.start();
    }

打印日志可以看到这种品牌的手机都启动了。至此,我们就完成了工厂方法模式的创建。

问题

由于每个具体产品对应一个具体工厂,所以会产生很多类,而且每次创建产品都需要new一个工厂出来,对系统的性能有一定的影响。

解决

为了更好的管理工厂类,而且让工厂类可重用,我们可以创建一个工厂的工厂,使用HashMap来对工厂进行缓存,在使用工厂时直接从HashMap获取缓存的工厂。

class PhoneFactoryFactory {

    enum PhoneType {
        oppo, vivo, xiaomi
    }

    static HashMap<PhoneType, PhoneFactory> map = new HashMap<>();

    static {
        map.put(PhoneType.oppo, new OppoFactory());
        map.put(PhoneType.vivo, new VivoFactory());
        map.put(PhoneType.xiaomi, new XiaomiFactory());
    }

    public static PhoneFactory getFactory(PhoneType type) {
        return map.get(type);
    }
}
public static void main(String[] args) {
        Phone oppoPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.oppo).createPhone();
        oppoPhone.start();

        Phone vivoPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.vivo).createPhone();
        vivoPhone.start();

        Phone xiaomiPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.xiaomi).createPhone();
        xiaomiPhone.start();
    }


从日志可以看到各种品牌的手机同样是启动了。

总结

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
  • 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。

缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

示例代码已上传至Github

学习更多知识,请关注我的个人博客:droidYu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值