设计模式之工厂模式详解

模式的分类

创建模式 提供了创建对象的机制 可以提高灵活性和现有代码的重要性

结构模式 解释了对象与类组装更大的结构 同时又保持结构的灵活性和效率

行为模式 负责相互之间的沟通以及对象有效的责任分配

工厂模式

工厂模式 如果比如物流业务,只限于卡车运输,那么直开发卡车接口,只用卡车类,再相加轮船运输,就会耦合度非常大,代码改起来非常麻烦。所以要用到工厂模式

在这里插入图片描述
如果说轮船跟卡车都要用到Transport类,而Transport接口有一个deliver()交付方法,卡车运输走卡车运输交付,轮船运输走轮船运输交付,返回不同的对象,简单明了
在这里插入图片描述
这样一个流程图,调用工厂方法,简称客户端的代码,不用了解各个返回对象的差别,客户端将所有Transport接口产品统称为抽象类(抽象的运输),客户端知道所有的运输方法都有交付的方法,但是并不用关心具体的实现方法。

在这里插入图片描述
1.Product产品接口,将会对接口进行声明,对于所有的创建者以及子类的构建,接口都是完全通用的
2.ConcreteProduct是产品接口不同的实现
3.Creator创建者,虽然是创建者类但是是声明返回产品对象工厂方法,方法类型必须与产品的接口的方法相匹配,就是把产品接口的不同实现拆分开来。可以将工厂方法声明为抽象方法,强制每个不同的类以不同的方式实现该方法。

工厂方法模式适合应用的场景

1.如果无法知道对象确切类别以及其依赖关系的时候,可以使用工厂方法。

2.工厂方法将创建产品的代码与实际使用的产品代码分离,从而不能影响其他的代码情况下扩展产品创建部分代码。

3.假如要添加一个新的产品,只需要开发新的创建子类,然后重写其中工厂方法就行了。

4.如果用户希望扩展软件库或框架的组件,可以使用工厂方法。

	4.1比如你要用一个开源的UI框架编写应用,你要用到圆形按钮,但是之后长方形按钮,这你就需要使用圆形按钮继承标准的按钮类,但是你要告诉这个UI框架UIFramework类使用新的子类按钮代替默认按钮。

		为了实现功能,可以根据基础框架类子类圆形按钮UIWithRoundButtons,并重写创建按钮方法,基础类中返回按钮对象,现在新开发的对象,现在可以使用新的圆形按钮类代替ui框架类。

5.如果希望复用现有的对象来节省系统资源,而不是每次都会重新创建对象,可使用工厂方法。

工厂模式的优点以及缺点

可以避免创建者与具体产品之间的紧密耦合。
单一的职责,可以将产品创建代码放在程序的单一设置,从而更容易维护。
开闭原则,无需更改现有客户端的代码,就可以开发新的具体产品类型。
缺点:工厂模式需要引进许多新的子类,代码会变的复杂,最好的情况是该将模式引入创建者类的现有的层次结构中。

与其他模式的关系

1.再许多设计中工厂模式较为简单,随后演化为抽象工厂模式,原型模式或生成器模式更加灵活但是更加复杂。
2.抽象工厂模式基于一组工厂模式,也可以使用原型模式来生成这些类的方法。
3.可以使用工厂模式和迭代器模式让子类集合返回不同类型的迭代器,并使迭代器与集合相匹配。
4.原型模式不基于继承,因此没有继承的缺点,但是原型模式需要复杂的初始化,工厂模式基于继承所有不需要初始化。
5.工厂模式是模板方法模式的一种特殊形式,同时,工厂模式可以作为一个大型模板方法中的一个步骤。

代码示例

buttons/Button.java: 通用产品接口

package refactoring_guru.factory_method.example.buttons;

/**
 * Common interface for all buttons.
 */
public interface Button {
    void render();
    void onClick();
}

buttons/HtmlButton.java: 具体产品

package refactoring_guru.factory_method.example.buttons;

/**
 * HTML button implementation.
 */
public class HtmlButton implements Button {

    public void render() {
        System.out.println("<button>Test Button</button>");
        onClick();
    }

    public void onClick() {
        System.out.println("Click! Button says - 'Hello World!'");
    }
}

buttons/WindowsButton.java: 另一个具体产品

package refactoring_guru.factory_method.example.buttons;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Windows button implementation.
 */
public class WindowsButton implements Button {
    JPanel panel = new JPanel();
    JFrame frame = new JFrame();
    JButton button;

    public void render() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel("Hello World!");
        label.setOpaque(true);
        label.setBackground(new Color(235, 233, 126));
        label.setFont(new Font("Dialog", Font.BOLD, 44));
        label.setHorizontalAlignment(SwingConstants.CENTER);
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));
        frame.getContentPane().add(panel);
        panel.add(label);
        onClick();
        panel.add(button);

        frame.setSize(320, 200);
        frame.setVisible(true);
        onClick();
    }

    public void onClick() {
        button = new JButton("Exit");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                System.exit(0);
            }
        });
    }
}

factory/Dialog.java: 基础创建者

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;

/**
 * Base factory class. Note that "factory" is merely a role for the class. It
 * should have some core business logic which needs different products to be
 * created.
 */
public abstract class Dialog {

    public void renderWindow() {
        // ... other code ...

        Button okButton = createButton();
        okButton.render();
    }

    /**
     * Subclasses will override this method in order to create specific button
     * objects.
     */
    public abstract Button createButton();
}

factory/HtmlDialog.java: 具体创建者

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.HtmlButton;

/**
 * HTML Dialog will produce HTML buttons.
 */
public class HtmlDialog extends Dialog {

    @Override
    public Button createButton() {
        return new HtmlButton();
    }
}

factory/WindowsDialog.java: 另一个具体创建者

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.WindowsButton;

/**
 * Windows Dialog will produce Windows buttons.
 */
public class WindowsDialog extends Dialog {

    @Override
    public Button createButton() {
        return new WindowsButton();
    }
}

Demo.java: 客户端代码

package refactoring_guru.factory_method.example;

import refactoring_guru.factory_method.example.factory.Dialog;
import refactoring_guru.factory_method.example.factory.HtmlDialog;
import refactoring_guru.factory_method.example.factory.WindowsDialog;

/**
 * Demo class. Everything comes together here.
 */
public class Demo {
    private static Dialog dialog;

    public static void main(String[] args) {
        configure();
        runBusinessLogic();
    }

    /**
     * The concrete factory is usually chosen depending on configuration or
     * environment options.
     */
    static void configure() {
        if (System.getProperty("os.name").equals("Windows 10")) {
            dialog = new WindowsDialog();
        } else {
            dialog = new HtmlDialog();
        }
    }

    /**
     * All of the client code should work with factories and products through
     * abstract interfaces. This way it does not care which factory it works
     * with and what kind of product it returns.
     */
    static void runBusinessLogic() {
        dialog.renderWindow();
    }
}

OutputDemo.txt: 执行结果 (Html­Dialog)

<button>Test Button</button>
Click! Button says - 'Hello World!'

OutputDemo.png: 执行结果 (Windows­Dialog)
在这里插入图片描述

刚刚学习完分享一下经验,也对自己做一个记录,一起加油,这里是不会写代码的安慕希。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值