嘻哈说:设计模式之工厂方法模式

栏目: 后端 · 发布时间: 7年前

内容简介:因为本节的工厂方法模式与抽象工厂模式存在关联度,所以会在下一节《抽象工厂模式》中混成一首歌发。现实中的工厂,是用来生产产品的,而代码中的工厂,则是创建对象的,用来创建对象,那肯定就是

这首歌还没写不能发

因为本节的工厂方法模式与抽象工厂模式存在关联度,所以会在下一节《抽象工厂模式》中混成一首歌发。

2、简单工厂模式的定义

现实中的工厂,是用来生产产品的,而代码中的工厂,则是创建对象的,

用来创建对象,那肯定就是 创建型模式 了。

我们经常会用到三种和工厂相关的设计模式:简单工厂模式、工厂方法模式、抽象工厂模式。

这节咱们要说的是——工厂方法模式。

不过,再说工厂方法之前,我们要先说下简单工厂模式。我们从简单的开始入手,由简入繁。

简单工厂模式呢,它不属于Gof23种 设计模式 之一,但它在实际的项目中经常被用到,所以我们还是很有必要学习,并且它的思想也非常简单,可以说是工厂方法模式的一个引导。

我们来看一下简单工厂方法的定义。

又称为静态工厂模式, 由一个工厂对象决定创建出哪一种产品类的实例。

注意这里的定义,是 一个工厂对象

怎么实现呢?实现的套路是什么?

定义一个工厂类,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类。

3、场景

场景与建造者模式有点类似,还是熟悉的饺子,还是熟悉的配方,还是熟悉的味道,扯远了...

美食饺子

番茄餐厅的后厨。

厨师长:老板,我听说隔壁餐厅买来了一个机器,包饺子神器,一输入参数,饺子直接出锅,高科技呀,跟饺子工厂似的。

老板:你的意思是咱们也去买个?

厨师长:嗯,我是想提这个建议的,一键出饺子,想想心里还有点小激动呢。

老板:你不会是为了图省事吧?

求生欲极强的厨师长:当然不是,我是觉得饺子神器效率高,能够给我们饭店带来更大的价值。

老板:嗯,那我同意了,钱从你工资里扣。

委屈的厨师长:老板,这样不合适吧?我上有老,下有...

老板:打住,逗你的,看把你给吓得。效率提高但味道降低,这种神器咱们饭店不会用的。

我们今天的例子,就是饺子工厂,可以生产各种饺子馅、皮。

4、简单工厂模式

嘻哈说:设计模式之工厂方法模式

简单工厂模式的UML类图。

package com.fanqiekt.factory.simple;

/**
 * 饺子馅
 *
 * @Author: 番茄课堂-懒人
 */
public interface IStuffing {

    void make();

}
复制代码

IStuffing:产品(饺子馅)的接口,共有的父类。

make()就是制造饺子皮的方法。

package com.fanqiekt.factory.simple;

/**
 * 猪肉大葱馅
 * @Author: 番茄课堂-懒人
 */
public class PorkStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("制作猪肉大葱馅");
    }

}
复制代码
package com.fanqiekt.factory.simple;

/**
 * 茴香鸡蛋馅
 * @Author: 番茄课堂-懒人
 */
public class FoeniculumVulgareStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("制作茴香鸡蛋馅");
    }

}
复制代码
package com.fanqiekt.factory.simple;

/**
 * 韭菜鸡蛋馅
 * @Author: 番茄课堂-懒人
 */
public class ChineseChivesStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("制作韭菜鸡蛋馅");
    }

}
复制代码

具体的产品类,饺子馅中的大户:猪肉大葱馅、茴香鸡蛋馅、韭菜鸡蛋馅。

package com.fanqiekt.factory.simple;

/**
 * 饺子馅工厂类
 * @Author: 番茄课堂-懒人
 */
public class StuffingFactory {
    public static IStuffing getStuffing(String key){
        IStuffing stuffing = null;
        switch (key){
            case "猪肉大葱":
                stuffing = new PorkStuffing();
                break;
            case "韭菜鸡蛋":
                stuffing = new ChineseChivesStuffing();
                break;
            case "茴香鸡蛋":
                stuffing = new FoeniculumVulgareStuffing();
                break;
        }
        return stuffing;
    }
}
复制代码

StuffingFactory:饺子馅工厂类。

简单工厂中只有一个工厂类,并且提供了一个静态公有方法,可以根据参数的不同返回不同类的实例。

这也是简单方法为什么要被称之为静态工厂模式的原因。

package com.fanqiekt.factory.simple;

/**
 * 客户端
 * @Author: 番茄课堂-懒人
 */
public class Client {

    public static void main(String args[]){
        IStuffing stuffing = StuffingFactory.getStuffing("猪肉大葱");
        stuffing.make();

        System.out.println("------------");

        stuffing = StuffingFactory.getStuffing("韭菜鸡蛋");
        stuffing.make();

        System.out.println("------------");

        stuffing = StuffingFactory.getStuffing("茴香鸡蛋");
        stuffing.make();
    }

}
复制代码

客户端类。

我们可以看出,简单工厂不愧为简单工厂,就是赤裸裸的简单。

但简单并不普通,它完美的展现了工厂方法的思想,让工厂创建对象,而不是对象A去创建对象B。

这样可以避免对象A与对象B之间的耦合。

我们运行一下,看结果。

制作猪肉大葱馅
------------
制作韭菜鸡蛋馅
------------
制作茴香鸡蛋馅
复制代码

5、工厂方法模式的定义

如果按照简单工厂的写法,在不使用 java 的反射的前提下,扩展性是很差的。

如果添加一种饺子馅,必须修改工厂中的判断。

所以我们来介绍一下另外一种工厂模式——工厂方法模式,下面,我们有请男主出场。

我们先来看看,工厂方法模式的官方定义:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。

从定义中,我们可以看出实现的套路:定一个创建对象的接口,然后每个工厂去实现该接口实例化特定的对象,这样就使一个类的实例化延迟到其子类。

每一个产品都有相应的工厂,这就是与简单工厂模式最大的区别。

然后,调用者可以自由的 选择使用哪个工厂去创建对象。

6、工厂方法模式

嘻哈说:设计模式之工厂方法模式

工厂方法模式的UML类图。

产品(饺子馅)与简单工厂模式的代码一致,这里就不贴出来了。

package com.fanqiekt.factory.method;

/**
 * 工厂接口
 * @Author: 番茄课堂-懒人
 */
public interface IFactory {

    IStuffing getStuffing();

}
复制代码

IFactory:工厂的接口。

定义一个用于创建对象的接口。

getStuffing()获得产品(饺子馅)的方法,交给具体的子类来实现。使一个类的实例化延迟到其子类。

package com.fanqiekt.factory.method;

/**
 * 猪肉大葱馅工厂
 * @Author: 番茄课堂-懒人
 */
public class PorkFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new PorkStuffing();
    }
}
复制代码
package com.fanqiekt.factory.method;

/**
 * 茴香鸡蛋馅工厂
 * @Author: 番茄课堂-懒人
 */
public class FoeniculumVulgareFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new FoeniculumVulgareStuffing();
    }
}
复制代码
package com.fanqiekt.factory.method;

/**
 * 韭菜鸡蛋馅工厂
 * @Author: 番茄课堂-懒人
 */
public class ChineseChivesFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new ChineseChivesStuffing();
    }
}
复制代码

具体的工厂类。

为每个产品(饺子馅)提供一个工厂类:猪肉大葱馅工厂、茴香鸡蛋馅工厂、韭菜鸡蛋馅工厂。

这样的设计,扩展起来也非常的方便,例如增加三鲜馅,只需要增加产品类(三鲜馅)、工厂类(三鲜馅)就可以了。不会影响其他。

7、区别

简单工厂模式,只有一个工厂类,根据参数的不同返回不同类的实例。

工厂方法模式,定义一个创建对象的接口,存在实现该接口的多个工厂类。调用者选择使用哪个工厂。

8、END

从下一节课程开始,《嘻哈说——设计模式》系列的课程将不在其他渠道发布,改为公众号《番茄课堂》独家发布,期待大家的关注。

今天就先说到这里,下一节说《抽象工厂模式》,感谢大家支持。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Concurrency in Practice

Java Concurrency in Practice

Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes、Doug Lea / Addison-Wesley Professional / 2006-5-19 / USD 59.99

This book covers: Basic concepts of concurrency and thread safety Techniques for building and composing thread-safe classes Using the concurrency building blocks in java.util.concurrent Pe......一起来看看 《Java Concurrency in Practice》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具