设计模式 - 工厂方法模式 - 基于 Java 实现

设计模式 - 工厂方法模式 - 基于 Java 实现,第1张

常见和工厂有关的设计模式

和工厂相关的设计模式主要有三种,工厂方法模式,抽象工厂模式;

在前面的博客中介绍了简单工厂模式,本篇博客主要介绍的是工厂方法模式

什么是工厂方法模式

工厂方法模式是简单工厂的进一步的深化,在工厂方法模式中,不再提供统一的工厂类来创建不同的对象,针对不同的类,选择使用了不同的工厂;可以这样理解:每一个类都是有自己的工厂来创建自己的对象(实例)的;

工厂方法模式的定义:

定义一个用于创建对象的接口(ReaderFactory),让子类(***Factory)决定哪儿个类进行实例化,工厂方法模式让一个类的实例化延迟到其子类;

工厂方法是一种创建设计模式,即与对象创建有关。在工厂方法模式中,创建对象而不将创建逻辑暴露给调用者,调用者使用相同的通用接口来创建新类型的对象;

工厂模式是创建对象的核心设计原则之一,它允许客户端以不与库的类层次结构紧密耦合的方式创建库的对象(如下所述)

工厂方法模式的实现 应用场景的假设以及代码实现

设计一种图片加载器的功能,这个图片加载功能抽象到接口中,不同的图片加载器类实现这个接口中的加载图片的接口即可,这样一来,所有的图片加载实现类都拥有了加载相关图片的功能。这个时候想要创建出来不同的图片加载器实例,一般使用 new 进行创建,但是这样一来,程序之间的耦合度就变高了,所以可以考虑工厂模式,简单工厂模式下面,在新添加功能的时候,会违反开闭原则,所以选择使用工厂方法的模式,给每个类都创建一个工厂类,一个工厂类实现一种实例,得到了解耦合的作用,同时保证了开闭原则;

首先完成加载器接口的设计,在这个接口中存在一个 Read() 方法,这个方法用来加载各种图片:

public interface Reader {
    void read();
}

接口只是定义了图片加载的功能,具体的实现类如下面所示:

实现 Reader 接口,实现了加载 gif 图片的功能:

public class GifReader implements Reader{
    @Override
    public void read() {
        System.out.println("加载 Gif 图片");
    }
}

实现 Reader 接口,实现了加载 jpg 图片的功能:

public class JpgReader implements Reader{
    @Override
    public void read() {
        System.out.println("加载 jpg 图片");
    }
}

实现 Reader 接口,实现了加载 png 图片的功能:

public class PngReader implements Reader{
    @Override
    public void read() {
        System.out.println("加载 png 图片");
    }
}

至此,需要实现的功能接口以及实现功能接口的相关类已经创建出来的,但是此时使用不同的图片加载器类创建对象使得,程序之间的耦合度是比较高的,此时使用工厂模式的工厂方法模式,给每一个类创建一个工厂,也就是一个工厂只是创建特定的类的实例;

首先创建工厂接口,所有类对应的自己的工厂(工厂就是各个工厂类)都实现这个 getReader() 方法;

public interface ReaderFactory {
    Reader getReader();
}

给每一个图片加载类都创建出来一个对应的工厂,这个工厂用来生产图片加载器类的实例:
GifReaderFactory 的实现:

public class GifReaderFactory implements ReaderFactory{
    @Override
    public Reader getReader() {
        return new GifReader();
    }
}

JpgReaderFactory 的实现:

public class JpgReaderFactory implements ReaderFactory{
    @Override
    public Reader getReader() {
        return new JpgReader();
    }
}

PngReaderFactory 的实现:

public class PngReaderFactory implements ReaderFactory{
    @Override
    public Reader getReader() {
        return new PngReader();
    }
}

用于生产各个图片加载器的工厂都创建好之后,可以不使用 new 关键就可以创建出来相关的图片加载器对象了,具体的使用方法如下所示,也就是测试代码:

public class TestFactoryMethodModel {
    public static void main(String[] args) {
        /**
         *  代码的执行逻辑:
         *      1、使用工厂方法模式下不同的工厂创建出来一个工厂对象
         *      2、使用工厂对象生产出来一个用来加载特定图片的加载图片类的实例
         *      3、加载图片类的实例创建创建出来了,调用 read() 方法,加载图片
         *      
         *      想要获得图片加载器对象,前提是得到工厂类对象,用工厂类对象调用方法得到图片加载器对象;
         *      工厂方法模式重点是,创建不同图片加载器对象,加载图片的对象创建出来之后,调用相关的方法执行加载图片即可;
         */
        ReaderFactory jpgReaderFactory = new JpgReaderFactory();
        Reader jpgReader = jpgReaderFactory.getReader();
        jpgReader.read();

        ReaderFactory pngReaderFactory = new PngReaderFactory();
        Reader pngReader = pngReaderFactory.getReader();
        pngReader.read();

        ReaderFactory factory = new GifReaderFactory();
        Reader reader = factory.getReader();
        reader.read();
    }
}

执行结果:

加载 jpg 图片
加载 png 图片
加载 Gif 图片

上面测试代码可能看不出来工厂方法的强大之处:请看下面的测试代码:

// 使用到多态,ReaderFactory factory = new GifReaderFactory(); 这一句diamante 中的 new 关键词后面的 GifReaderFactory 修改成为 JpgReaderFactory 或者 PngReaderFactory 的时候,创建出来的就是jpg 或者 png 的图片加载器
// 想要得到其他的图片加载器,相关的图片加载器实现 Reader 接口,对应的图片加载器类工厂实现 ReaderFactory 接口 ,在测试中,只是需要修改 new 关键字后面的这个类即可,其他的代码都是不需要改动的,符合开闭原则,是一种比较好的设计
public class TestFactoryMethodModel {
    public static void main(String[] args) {
        ReaderFactory factory = new GifReaderFactory();
        Reader reader = factory.getReader();
        reader.read();
    }
}
简单工厂模式与工厂方法模式对比

简单工厂模式是所有的实现类共同使用一个工厂类,但是如果想要增加新的功能的时候,需要修改工厂类的代码,是不符合开闭原则的,也就是不符合开放扩展,关闭修改的;每次添加新功能的时候,就修改一次工厂类的代码的的设计是十分糟糕的;

工厂方法模式相对来说,写的代码多了一些,也就是所谓的每一个实现类都拥有自己的工厂,虽然代码量增加了,但是在增加了新的功能的时候,不需要修改原来的代码,可以扩展使用,较好的符合开闭原则;

小结

本文重点介绍了工厂方法模式,介绍了工厂方法模式的额使用背景,以及具体的代码实现,比较了简单工厂模式以及工厂方法模式之间的区别;需要注意的是,无论是简单工厂模式还是工厂方法模式,都是为了程序之间解耦合使用的,使得程序的维护成本降低;

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/872107.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存