用Java工厂方法模式制作一个简单的搜索框!!!


前言

        上一次,我们用了静态工厂模式,制作了一个文件类型转换的小程序,相信大家也简单的体会到了设计模式带来的好处,但是,在静态工厂模式,我们把所有的判断全部放在抽象工厂里,这样当我们的产品越来越多时,判断也变得越来越多,十分不利于维护。为此,我们可以扩展一下思维,静态工厂模式里我们只抽象了产品,但是没有抽象工厂,我们是否可以按照这种思想,把工厂也抽象出来呢?答案显而易见,当然可以,我们把工厂也抽象出来以后,就成了这次我们要介绍的工厂方法模式。


一、工厂方法模式是什么?

        工厂方法模式的定义:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
由定义可知,我们便得到了4个角色。
1.Product:抽象产品、2.ConcreteProduct:具体产品、3.Factory:抽象工厂、4.ConcreteFactory:具体工厂

二、应用实例

        我们和上次一样,还是用一个小程序来让大家感受一下工厂方法模式的实现过程。
        有这样一个小需求,小弓同学想做一个快速搜索栏,因为浏览器打开后,有很多新闻或者广告弹窗,小弓同学觉得很烦,而且小弓同学作为软件工程的学生,需要经常查阅资料,他想有一个可以直接可以输入问题的文本框就好了,于是他说干就干,用他刚学会的工厂方法模式,制作了一个简单的搜索框,我们来看看他是怎么实现的吧~~

1.画类图

        在编码前,画类图是必须要完成的。根据需求简单的搜索框,(我们以CSDN和B站为例),来画工厂方法模式的类图。
工厂方法模式类图

2.根据类图写代码

        有了上次静态工厂设计模式的经验,我们可以总结出,应该先写抽象层(抽象产品、抽象工厂),再去写具体层(具体产品、具体工厂),并且产品和工厂也有先后关系,应该先写产品的代码,再写工厂的代码。好了,废话不多说,打开我们的“作案工具”idea开始造吧!!!
        首先,我们先写抽象产品的抽象类。

/**
 * 搜索引擎抽象类
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public abstract class Search {
    /**
     * 搜索的抽象方法
     * @param content 搜索的内容
     */
    public abstract void toSearch(String content);
}

        接着,我们来写具体实现这个抽象类的子类。

import java.awt.*;
import java.net.URI;

/**
 * CSDN搜索引擎类
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public class CSDNSearch extends Search {
    @Override
    public void toSearch(String content) {
        try {
            String url = "https://so.csdn.net/so/search?q=" + content; // CSDN搜索
            URI uri = URI.create(url);
            // 获取当前系统桌面扩展
            Desktop desktop = Desktop.getDesktop();
            // 判断系统桌面是否支持要执行的功能,获取系统默认浏览器打开链接
            if (desktop.isSupported(Desktop.Action.BROWSE)) {
                desktop.browse(uri);
                System.out.println("亲,已为您搜索到" + content + "的所有内容!!!");
            }
        } catch (java.lang.NullPointerException e) {
            System.out.println("亲,您的url为空:");
            e.printStackTrace();
        } catch (java.io.IOException e) {
            System.out.println("亲,无法获取系统默认浏览器:");
            e.printStackTrace();
        }
    }
}
import java.awt.*;
import java.net.URI;

/**
 * B站搜索引擎类
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public class BSearch extends Search {
    @Override
    public void toSearch(String content) {
        try {
            String url = "https://search.bilibili.com/all?keyword=" + content; // B站搜索
            URI uri = URI.create(url);
            // 获取当前系统桌面扩展
            Desktop desktop = Desktop.getDesktop();
            // 判断系统桌面是否支持要执行的功能,获取系统默认浏览器打开链接
            if (desktop.isSupported(Desktop.Action.BROWSE)) {
                desktop.browse(uri);
                System.out.println("亲,已为您搜索到" + content + "的所有内容!!!");
            }
        } catch (java.lang.NullPointerException e) {
            System.out.println("亲,您的url为空:");
            e.printStackTrace();
        } catch (java.io.IOException e) {
            System.out.println("亲,无法获取系统默认浏览器:");
            e.printStackTrace();
        }
    }
}

        产品这边我们就写好了,然后我们写工厂相关的代码。
        首先创建一个工厂接口(不一定非要是接口,仍然使用抽象类也可以,根据具体情况,具体对待就行)。

/**
 * 搜索工厂接口
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public interface SearchFactory {
    /**
     * 创建搜索引擎的抽象方法
     * @return 搜索引擎
     */
    Search createSearch();
}

        然后,我们写具体的工厂,就是可以生产“CSDN”、“B站”的工厂。

/**
 * CSDN搜索工厂
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public class CSDNSearchFactory implements SearchFactory {
    @Override
    public Search createSearch() {
        return new CSDNSearch();
    }
}
/**
 * B站搜索工厂
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public class BSearchFactory implements SearchFactory {
    @Override
    public Search createSearch() {
        return new BSearch();
    }
}

        到这里呢,我们就已经把最核心的代码写完了,但是我们还没有实现搜索框的绘制,关于搜索框的绘制,不属于设计模式里的重要内容,小弓同学就简单的在下方为大家用javaFX绘制了一个搜索框,如果觉得不美观的同学,可以自己去搜索javaFX的使用,去美化它,这里不做过多赘述。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;

/**
 * 搜索框类
 * 作者:Cool_foolisher
 * 开始日期:2023-4-7
 * 结束日期:2023-4-7
 */
public class Main extends Application {
    private Button button; // 搜索按钮
    private Scene scene; // 场景
    private TextField searchText; // 文本框
    private ComboBox<String> comboBox; // 下拉框
    private SearchFactory searchFactory; // 搜索引擎工厂
    private Search search; // 搜索引擎
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        comboBox = new ComboBox<>();
        comboBox.getItems().add("CSDN");
        comboBox.getItems().add("B站");
        comboBox.setStyle("-fx-font-size:19px"); // 修改字体大小
        comboBox.getSelectionModel().select(0); // 修改默认显示选项
        searchText = new TextField();
        searchText.setFont(new Font("宋体",20));
        button = new Button();
        button.setText("快速搜索");
        button.setFont(new Font("宋体",20));
        button.setOnMouseClicked(event -> {
            String searchContext = searchText.getText().trim();
            String choose = comboBox.getValue();
            if ("CSDN".equals(choose)) {
                searchFactory = new CSDNSearchFactory();
                search = searchFactory.createSearch();
                search.toSearch(searchContext);
            } else if ("B站".equals(choose)) {
                searchFactory = new BSearchFactory();
                search = searchFactory.createSearch();
                search.toSearch(searchContext);
            } else {
                System.out.println("亲,暂不支持该搜索引擎!!!");
            }
        });
        // 面板
        FlowPane stackPane = new FlowPane();
        stackPane.getChildren().add(comboBox);
        stackPane.getChildren().add(searchText);
        stackPane.getChildren().add(button);
        // 场景
        scene = new Scene(stackPane,500,42);
        // 窗口
        primaryStage.setTitle("小弓快速搜索框");
        primaryStage.setResizable(false);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

        下面是程序运行时的效果图。
快速搜索框的效果图

三、总结

        以上就是工厂方法模式的全部内容,可以说工厂方法模式是静态工厂模式的扩展,顺便说一下,工厂方法模式是属于我们23种设计模式的哦,它是创建型模式里最常用的设计模式。这么厉害的它有以下优点
        1.它能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节完全封装在具体工厂内部。
        2.在系统中加入新的产品时,无需修改抽象工厂和抽象产品的接口或抽象类,也无需修改其他具体工厂和具体产品,只需要添加一个具体产品和具体工厂即可,简而言之,就是易扩展,这也完全符合开闭原则。
        当然,在完美的事物,也会有相应的缺点
        1.在添加新产品时,需要写新的具体产品类及对应的工厂,在一定程度上增加了系统的复杂性,给系统带来额外的开销。
        2.为了提高代码的可扩展性,引入了大量的抽象层,增加了代码的抽象性和理解难度。

结束语

        对于搜索功能不一定非得是“CSDN”和“B站”,有其他需要的化,可以根据自己的需求按照上述步骤去完成。如果觉得我的这篇文章对您有帮助,欢迎大家动动小手给我点赞,对于工厂方法模式有疑问的话,欢迎大家在评论留言!!!本人也是刚刚学习编程的小菜鸟,文章如有写的不对的地方,也欢迎大佬的指正!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学徒钝子生

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值