工厂模式又称工厂方法模式,是一种创建型设计模式, 解决了在不指定具体类的情况下创建产品对象的问题。其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
这种设计模式也是Java开发中最常见的一种模式,它的主要意图是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
核心 Java 程序库中有该模式的应用:
- java.util.Calendar#getInstance()
- java.util.ResourceBundle#getBundle()
- java.text.NumberFormat#getInstance()
- java.nio.charset.Charset#forName()
- java.net.URLStreamHandlerFactory#createURLStreamHandler(String)(根据协议返回不同的单例对象)
- java.util.EnumSet#of()
- javax.xml.bind.JAXBContext#createMarshaller() 及其他类似的方法。
识别方法: 工厂方法可通过构建方法来识别, 它会创建具体类的对象, 但以抽象类型或接口的形式返回这些对象。
样例
生成跨平台的 GUI 元素
由按钮担任产品的角色,对话框担任创建者的角色
接口:
package creational.factorymethod;
/**
* 通用的 Button 接口
*/
public interface IButton {
void render();
void onClick();
}
具体产品:
package creational.factorymethod;
/**
* Html Button 实现类
*/
public class HtmlButton implements IButton {
@Override
public void render() {
System.out.println("<button>Test: Button</button>");
onClick();
}
@Override
public void onClick() {
System.out.println("Click~! Button says - 'Hello World'");
}
}
package creational.factorymethod;
import javax.swing.*;
import java.awt.*;
/**
* Windows Button 实现类
*/
public class WindowsButton implements IButton {
JPanel panel = new JPanel();
JFrame frame = new JFrame();
JButton button;
@Override
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();
}
@Override
public void onClick() {
button = new JButton("Exit");
button.addActionListener(e -> {
frame.setVisible(false);
System.exit(0);
});
}
}
工厂:
package creational.factorymethod;
/**
* Base factory class
*/
public abstract class Dialog {
public void renderWidow() {
IButton okButton = createButton();
okButton.render();
}
/**
* 子类将重写此方法来创建具体的按钮
* @return
*/
public abstract IButton createButton();
}
具体的创建者:
package creational.factorymethod;
public class HtmlDialog extends Dialog {
@Override
public IButton createButton() {
return new HtmlButton();
}
}
package creational.factorymethod;
public class WindowsDialog extends Dialog {
@Override
public IButton createButton() {
return new WindowsButton();
}
}
测试代码:
package creational.factorymethod;
public class Demo {
private static Dialog dialog;
public static void main(String[] args) {
configure();
runBusinessLogic();
}
static void configure() {
if (System.getProperty("os.name").equals("Windows 10")) {
dialog = new WindowsDialog();
} else {
dialog = new HtmlDialog();
}
}
static void runBusinessLogic() {
dialog.renderWidow();
}
}