目录
前言
简单工厂模式
工厂方法模式
抽象工厂模式
首页 Java java教程 Java设计模式中工厂模式的介绍(代码示例)

Java设计模式中工厂模式的介绍(代码示例)

Sep 12, 2018 pm 03:54 PM
java设计模式

本篇文章给大家带来的内容是关于Java设计模式中工厂模式的介绍(代码示例)有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

前言

在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法。本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式、工厂方法和抽象工厂模式。

简单工厂模式

简单工厂模式是属于创建型模式,又叫做静态工厂方法模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。调用只需要告诉工厂类所需要的类型,工厂类就会返回需要的产品类工厂的子类。 可以说是工厂模式中最简单的一种。

打个比方,我们在电脑经常玩游戏,我们只需要告诉电脑我们要玩什么游戏,电脑就会打开这个游戏,我们并不需要关心游戏是怎么运作的。
我们可以在以下的代码中进行相应的说明。

我们首先创建一个游戏总类接口,包含一个玩游戏的方法; 然后再由各自的游戏类继承该类并实现该类的方法,最后在创建一个工程类根据不同的游戏进行创建对象。
那么实现的代码如下:

代码示例:

    private static final String LOL="LOL"; 
    private static final String DNF="DNF"; 
    
    public static void main(String[] args) {
        Game game= ComputerFactory.playGame(LOL);
        Game game2= ComputerFactory.playGame(DNF);
        game.play();
        game2.play();
    }
}

interface Game{
    void play();
}

class LOL implements Game{
    @Override
    public void play() {
        System.out.println("正在玩LOL...");
    }   
}

class DNF implements Game{
    @Override
    public void play() {
        System.out.println("正在玩DNF...");
    }   
}


class ComputerFactory{
    private static final String LOL="LOL"; 
    private static final String DNF="DNF"; 
     public static Game playGame(String game){
         if(LOL.equalsIgnoreCase(game)){
             return new LOL();
         }else if(DNF.equalsIgnoreCase(game)){
             return new DNF();
         }
         return null;
     }
登录后复制

输出结果:

正在玩LOL...
正在玩DNF...
登录后复制

我们在使用简单工厂模式进行实现该功能之后,会发现我们将游戏类的实例化放到了工厂类中实现,隐藏了对象创建的细节,并且不需要知道是怎么玩的,只需要知道调用该工厂类就行了。而且方便切换,因为只需更改工厂类传递的类型值就行了。
但是我们也发现一个问题,如果我们需要新增一个游戏类,那么需要新定义一个接口,然后还要在工厂类中添加一个判断分支,如果少量的话还好,但是大量的话就比较麻烦了,并且这也违背了开放-封闭原则。

工厂方法模式

工厂方法模式是 Java 中最常用的设计模式之一,属于创建型模式。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

在简单工厂模式中,我们发现在添加子类的时候,相应的也需要在工厂类中添加一个判断分支,是违背了开放-封闭原则的。而工厂方法模式就是主要解决这个问题的。

这里还是用上述的玩游戏示例,只不过这里每个游戏都是由各自的游戏工厂类实现。主要区别就是由一个 工厂类变成了多个了,降低了耦合度。如果新增一个游戏类,相应的也只需在新增一个工厂类而已, 并且完美的遵循了开放-封闭原则。

将上述代码更改之后,相应的代码实现如下:

代码示例:

    private static final String LOL="LOL"; 
    private static final String DNF="DNF"; 
    private static final String WOW="WOW"; 

    public static void main(String[] args) {

        Game game3=new LOLFactory().playGame(LOL);
        Game game4=new DNFFactory().playGame(DNF);
        Game game5=new WOWFactory().playGame(WOW);
        game3.play();
        game4.play();
        game5.play();       
    }
    
interface Game{
    void play();
}


class LOL implements Game{
    @Override
    public void play() {
        System.out.println("正在玩LOL...");
    }   
}

class DNF implements Game{
    @Override
    public void play() {
        System.out.println("正在玩DNF...");
    }   
}

class WOW  implements Game{
    @Override
    public void play() {
        System.out.println("正在玩WOW...");
    }   
}


interface ComputerFactory2{
    Game playGame(String game);
}

class LOLFactory implements ComputerFactory2{
    @Override
    public Game playGame(String game) {
        return new LOL();
    }
}

class DNFFactory implements ComputerFactory2{
    @Override
    public Game playGame(String game) {
        return new DNF();
    }
}

class WOWFactory implements ComputerFactory2{
    @Override
    public Game playGame(String game) {
        return new WOW();
    }
}
登录后复制

输出结果:

正在玩LOL...
正在玩DNF...
正在玩WOW...
登录后复制

可以看到使用工厂方法模式之后,我们的代码更加清晰了,扩展性也变高了,如果想增加一个产品,只要扩展一个工厂类就可以。但是随之而来的是在系统中增加了复杂度,每增加一个产品时,都需要增加一个具体类和对象实现工厂类。
所以在是否使用该模式需注意。
使用该模式比较经典的使用案例是大名鼎鼎的hibernate框架在选择数据库方言这块。但是如果直接简单的new一个对象的话,则不必使用了,若使用反而会增加系统的复杂度。

抽象工厂模式

抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。也就是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式相比工厂方法模式来说更加复杂,也更难理解,但是更容易扩展。
抽象工厂模式就将同一类的产品子类归为一类,让他们继承同一个抽象子类,然后把它们当作一组,然后再把多个组组成一个族。
打个比方,还是上述的玩游戏,我们可以把LOLWOW当作PVP类型的游戏,也可以把DNFWOW当作PVE类型的游戏。

那么相应更改的代码如下:

代码示例:

    private static final String LOL="LOL"; 
    private static final String DNF="DNF"; 
    private static final String WOW="WOW"; 
    
    public static void main(String[] args) {

        ComputerFactory3 cf3=new PVPFactory();
        cf3.playGame().play();
        cf3.playGame2().play();
        ComputerFactory3 cf4=new PVEFactory();
        cf4.playGame().play();
        cf4.playGame2().play();         
    }       
}


interface Game{
    void play();
}


class LOL implements Game{
    @Override
    public void play() {
        System.out.println("正在玩LOL...");
    }   
}

class DNF implements Game{
    @Override
    public void play() {
        System.out.println("正在玩DNF...");
    }   
}

class WOW  implements Game{
    @Override
    public void play() {
        System.out.println("正在玩WOW...");
    }   
}


interface ComputerFactory3{
     Game playGame();
     Game playGame2();
}

class PVPFactory implements ComputerFactory3{

    @Override
    public Game playGame() {
        return new LOL();
    }

    @Override
    public Game playGame2() {
        return new WOW();
    }   
}

class PVEFactory implements ComputerFactory3{

    @Override
    public Game playGame() {
        return new DNF();
    }

    @Override
    public Game playGame2() {
        return new WOW();
    }
    
}
登录后复制

输出结果:

正在玩LOL...
正在玩WOW...
正在玩DNF...
正在玩WOW...
登录后复制

在抽象工厂模式中,可以在不需要知道产品是怎么样的,只需知道是哪个工厂类就行了。我们也可以根据子类的共同的特性而将它们设计在一起,组成一个相同类型组,可以很方便的直接调用。但是相对的,产品族比较难以扩展,增加一个产品,需要增加相应的接口和实现类。例如某个品牌的手机,有不同系列,每个系列有不同的型号,如果只是增加型号的话,比较容易,但是相对的,增加某个系列就比较麻烦了。
所以我们在使用抽象工厂模式,也需要相应的结合实际场景来使用。

相关推荐:

Java设计模式是什么?Java设计模式中单例模式的介绍

以上是Java设计模式中工厂模式的介绍(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

公司安全软件导致应用无法运行?如何排查和解决? 公司安全软件导致应用无法运行?如何排查和解决? Apr 19, 2025 pm 04:51 PM

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

如何使用MapStruct简化系统对接中的字段映射问题? 如何使用MapStruct简化系统对接中的字段映射问题? Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

如何优雅地获取实体类变量名构建数据库查询条件? 如何优雅地获取实体类变量名构建数据库查询条件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

Java对象如何安全地转换为数组? Java对象如何安全地转换为数组? Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

如何将姓名转换为数字以实现排序并保持群组中的一致性? 如何将姓名转换为数字以实现排序并保持群组中的一致性? Apr 19, 2025 pm 11:30 PM

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? 电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? Apr 19, 2025 pm 11:27 PM

电商平台SKU和SPU表设计详解本文将探讨电商平台中SKU和SPU的数据库设计问题,特别是如何处理用户自定义销售属...

使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? 使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名以构建查询条件,是一个常见的难题。本文将针...

See all articles