《设计模式》—— 2 工厂模式

特别说明:本篇的简单工厂和工厂方法大部分内容参考自 工厂设计模式(三种)_简书

所以复制过来的文字仅作为笔记,本文的重点是每一级目录后的个人总结,其中的核心是每一种方法的缺点,这是促进方法改进的根本原因。

1 什么是工厂设计模式

工厂设计模式,顾名思义,就是用来生产对象的,在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦
本篇主要介绍三种工厂设计模式的使用:
1. 简单工厂
实现:将对象的创建放在一个工厂类中。
缺点:添加新对象类型时,需要修改工厂类。
适用场景:对象种类较少。
2. 工厂方法:添加新对象类型时,需要创建很多工厂。
实现:对象由工厂创建,将工厂抽象成一个接口或抽象类。添加新对象时,就添加一个新的工厂子类。
缺点:添加新对象类型时,需要添加新的工厂子类。
适用场景:对象种类较多。
3. 抽象工厂
实现:每添加一个新系列,需要创建对应的原料(Cpu3实现 Cpu抽象类、Screen3实现Screen抽象类)和工厂(工厂3,实现工厂抽象类)。
缺点:每添加一个新系列时,都需要创建新的原料类、新的工厂类,还是工厂方法的缺点。
适用场景:对象之间因依赖关系,成为一组。

由三个方法的缺点可以看出:

  • 要么选择简单工厂模式这种:添加新对象时,不需要添加工厂类,只需修改工厂类。
  • 要么选择工厂方法和抽象工厂这种:添加新对象时,需要添加工厂类。

2 简单工厂设计模式

2.1 介绍和举例

定义:一个工厂方法,依据传入的参数,生成对应的产品对象;
角色:
1. 抽象产品
2. 具体产品
3. 具体工厂
4. 产品使用者
使用说明:先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨;
代码如下:
水果接口

public interface Fruit {
    void whatIm();
}

具体类 苹果

public class Apple implements Fruit {
    @Override
    public void whatIm() {
        //苹果
    }
}

具体类 梨

public class Pear implements Fruit {
    @Override
    public void whatIm() {
        //梨
    }
}

具体工厂 水果工厂

public class FruitFactory {

    public Fruit createFruit(String type) {

        if (type.equals("apple")) {//生产苹果
            return new Apple();
        } else if (type.equals("pear")) {//生产梨
            return new Pear();
        }

        return null;
    }
}

产品使用

FruitFactory mFactory = new FruitFactory();
 Apple apple = (Apple) mFactory.createFruit("apple");//获得苹果
 Pear pear = (Pear) mFactory.createFruit("pear");//获得梨

就这样,一个非常简单的工厂设计模式就完成了,但是有没有发现什么问题呢?
对,那就是如果我想吃香蕉,想吃橘子呢,我万一什么都想吃呢??所以,以上的这种方式,每当我想添加一种水果,就必然要修改工厂类,这显然违反了开闭原则,亦不可取;所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适;所以我们来看下一种方式;

2.2 简单工厂 总结

简单工厂模式,核心是工厂类(即FruitFactory )。
理论优点:解耦合,将对象的创建(工厂创建水果)和使用(苹果,whatIam)分开。
编程好处:将创建水果的代码封装进工厂类中,以后想添加水果时,只需要修改工厂类即可。
编程缺点:注意“编程好处”中的“修改工厂类”,每当我想添加一种水果,就必然要修改工厂类,这违反了开闭原则(对扩展开放,对修改封闭)。
该方法适用场景:产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适;

3 工厂方法

3.1 介绍和示例

定义:将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定;
角色:
抽象产品类
具体产品类
抽象工厂类
具体工厂类

使用说明:和上例中一样,产品类抽象出来,这次我们把工厂类也抽象出来,生产什么样的产品由子类来决定;
代码如下:
水果接口 苹果类和梨类 代码和上例一样
工厂接口

public interface FruitFactory {
    Fruit createFruit();//生产水果
}

苹果工厂

public class AppleFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Apple();
    }
}

梨工厂

public class PearFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Pear();
    }
}

使用

AppleFactory appleFactory = new AppleFactory();
PearFactory pearFactory = new PearFactory();
Apple apple = (Apple) appleFactory.createFruit();//获得苹果
Pear pear = (Pear) pearFactory.createFruit();//获得梨

3.2 工厂方法 总结

理论优点

  • 解耦合,将对象的创建和使用分开。
  • 遵循了开闭原则。

编程缺点:需要很多产品时,需要创建很多工厂

4 抽象工厂

4.1 介绍和示例

定义:为创建一组相关或者是相互依赖的对象(即下文中的组1:825的处理器,6英寸屏幕。组2:650的处理器和5寸的屏幕)提供的一个接口(即下文中的getCpu()、getScreen()),而不需要指定它们的具体类。
角色:和工厂方法一样
抽象工厂和工厂方法的模式基本一样,区别在于,工厂方法是生产一个具体的产品,而抽象工厂可以用来生产一组相同,有相对关系的产品;重点在于一组,一批,一系列;举个例子,假如生产小米手机,小米手机有很多系列,小米note、红米note等;假如小米note生产需要的配件有825的处理器,6英寸屏幕,而红米只需要650的处理器和5寸的屏幕就可以了;用抽象工厂来实现:
cpu接口和实现类

public interface Cpu {
    void run();

    class Cpu650 implements Cpu {
        @Override
        public void run() {
            //625 也厉害
        }
    }

    class Cpu825 implements Cpu {
        @Override
        public void run() {
            //825 处理更强劲
        }
    }
}

屏幕接口和实现类

public interface Screen {

    void size();

    class Screen5 implements Screen {

        @Override
        public void size() {
            //5寸
        }
    }

    class Screen6 implements Screen {

        @Override
        public void size() {
            //6寸
        }
    }
}

工厂接口

public interface PhoneFactory {

    Cpu getCpu();//使用的cpu

    Screen getScreen();//使用的屏幕
}

具体工厂实现类:小米手机工厂

public class XiaoMiFactory implements PhoneFactory {
    @Override
    public Cpu getCpu() {
        return new Cpu.Cpu825();//高性能处理器
    }

    @Override
    public Screen getScreen() {
        return new Screen.Screen6();//6寸大屏
    }
}

具体工厂实现类:红米手机工厂

public class HongMiFactory implements PhoneFactory {

    @Override
    public Cpu getCpu() {
        return new Cpu.Cpu650();//高效处理器
    }

    @Override
    public Screen getScreen() {
        return new Screen.Screen5();//小屏手机
    }
}

以上例子可以看出,抽象工厂可以解决一系列的产品生产的需求,对于大批量,多系列的产品,用抽象工厂可以更好的管理和扩展;

4.2 抽象工厂总结

在这里插入图片描述
抽象工厂的目的:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。其中“一系列相关对象”即(Cpu1、Screen1)、(Cpu2、Screen2),这是两个系列。接口即工厂父类中的抽象方法(getCpu()、getScreen())。所以,抽象工厂是为了解决一组相关对象的创建。
编程实现:每添加一个新系列,需要创建对应的原料(Cpu3、Screen3)和工厂(工厂3)。 文章抽象工厂模式_菜鸟教程中,最后部分有添加新系列时的程序示例。
缺点:从“编程实现”中可以看出,抽象工厂并没有解决工厂方法的缺点(即添加很多新对象类型时,需要创建很多工厂)。

参考文献

[1] 工厂设计模式(三种)_简书
[2] 抽象工厂模式_菜鸟教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

张之海

若有帮助,客官打赏一分吧

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

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

打赏作者

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

抵扣说明:

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

余额充值