工厂模式

简单工厂模式

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

image-20231229154121552

静态工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ChartFactory {

public static Chart getChart(String type){
Chart chart = null;
if(type.equals("histogram")){
chart = new HistogramChart();
}else if(type.equals("line")){
chart = new LineChart();
}else if(type.equals("pie")){
chart = new PieChart();
}
return chart;
}
}

抽象产品

1
2
3
public interface Chart {
public void display();
}

具体产品

1
2
3
4
5
6
7
8
9
10
public class LineChart implements Chart{
public LineChart() {
System.out.println("创建折线图");
}
@Override
public void display() {
System.out.println("显示折线图");
}
}

1
2
3
4
5
6
7
8
9
10
public class PieChart implements Chart{
public PieChart() {
System.out.println("创建饼状图");
}
@Override
public void display() {
System.out.println("显示饼状图");
}
}

客户端

1
2
3
4
5
6
7
8
9
public class Client {
public static void main(String[] args) {
Chart chart = null;
chart = ChartFactory.getChart("pie");
chart.display();
chart = ChartFactory.getChart("line");
chart.display();
}
}

测试

1
2
3
4
创建饼状图
显示饼状图
创建折线图
显示折线图

优点: 简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性。

缺点: 扩展性差,违背了开闭原则(开闭原则指的是:软件实现应该对扩展开放,对修改关闭)。新增产品时,需要修改工厂类。

工厂方法模式

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

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

image-20231229155019575

抽象产品

1
2
3
public interface Logger {
public void writeLog();
}

具体产品

1
2
3
4
5
6
7
public class FileLogger implements Logger{
@Override
public void writeLog() {
System.out.println("文件日志记录");
}
}

1
2
3
4
5
6
public class DatabaseLogger implements Logger{
@Override
public void writeLog() {
System.out.println("数据库日志记录");
}
}

抽象工厂

1
2
3
public interface LoggerFactory {
public Logger creatLogger();
}

具体工厂

1
2
3
4
5
6
public class DatabaseLoggerFactory implements LoggerFactory{
@Override
public Logger creatLogger() {
return new DatabaseLogger();
}
}

具体工厂

1
2
3
4
5
6
public class FileLoggerFactory implements LoggerFactory{
@Override
public Logger creatLogger() {
return new FileLogger();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
public class Clinet {
public static void main(String[] args) {
LoggerFactory loggerFactory = new DatabaseLoggerFactory();
Logger logger = loggerFactory.creatLogger();
logger.writeLog();
loggerFactory = new FileLoggerFactory();
logger = loggerFactory.creatLogger();
logger.writeLog();
}
}

测试

1
2
数据库日志记录
文件日志记录

优点: 扩展性好,符合了开闭原则,新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。比如样例实现中,当我们需要一个苹果电脑时,只需要去新增一个苹果电脑类和一个苹果工厂类即可,而无需去修改原有的代码。符合单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。

缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。

抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。可以理解成是多个工厂方法的组合。

解决问题

在工厂方法模式中,我们的具体创建者每次使用都只能创建一个同类型的对象,假如我们现在需要的是多个不同类型的对象,工厂方法就满足不了需求了。这时我们可以把多个工厂方法组合到一个类,这就是抽象工厂模式,它就是专门用来创建多个产品,也可以说是创建产品家族的。

image-20231229163124174

抽象工厂

1
2
3
4
5
6
public interface SkinFactory {
public Button creatBotton();
public TextField creatTextField();
public ComboBox creatComboBox();
}

Spring工厂,用于生成Spring产品族

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SpringSkinFactory implements SkinFactory{
@Override
public Button creatBotton() {
return new SpringButton();
}
@Override
public TextField creatTextField() {
return new SpringTextField();
}
@Override
public ComboBox creatComboBox() {
return new SpringComboBox();
}
}

Summer工厂,用于生产summer产品族

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SummerSkinFactory implements SkinFactory{
@Override
public Button creatBotton() {
return new SummerBotton();
}
@Override
public TextField creatTextField() {
return new SummerTextField();
}
@Override
public ComboBox creatComboBox() {
return new SummerComboBox();
}
}

抽象产品

1
2
3
public interface Button {
public void display();
}

抽象产品

1
2
3
public interface ComboBox {
public void display();
}

抽象产品

1
2
3
public interface TextField {
public void display();
}

Spring风格产品

1
2
3
4
5
6
7
public class SpringButton implements Button{
@Override
public void display() {
System.out.println("浅绿色按钮");
}
}

1
2
3
4
5
6
public class SpringComboBox implements ComboBox{
@Override
public void display() {
System.out.println("绿色边框组合框");
}
}
1
2
3
4
5
6
public class SpringTextField implements TextField{
@Override
public void display() {
System.out.println("绿色边框文本框");
}
}

Summer风格产品

1
2
3
4
5
6
7
public class SummerBotton implements Button{
@Override
public void display() {
System.out.println("浅蓝色按钮");
}
}

1
2
3
4
5
6
public class SummerComboBox implements ComboBox{
@Override
public void display() {
System.out.println("蓝色边框组合框");
}
}
1
2
3
4
5
6
public class SummerTextField implements TextField{
@Override
public void display() {
System.out.println("蓝色边框文本框");
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class client {
public static void main(String[] args) {
SkinFactory factory;
factory = new SpringSkinFactory();
Button button = factory.creatBotton();
TextField textField = factory.creatTextField();
ComboBox comboBox = factory.creatComboBox();
button.display();
textField.display();
comboBox.display();
factory = new SummerSkinFactory();
button = factory.creatBotton();
textField = factory.creatTextField();
comboBox = factory.creatComboBox();
button.display();
textField.display();
comboBox.display();
}
}

测试

1
2
3
4
5
6
浅绿色按钮
绿色边框文本框
绿色边框组合框
浅蓝色按钮
蓝色边框文本框
蓝色边框组合框

优点: 工厂抽象类创建了多个类型的产品,当有需求时,可以创建相关产品子类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。

缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。

三种工厂的关系

当抽象工厂模式中只有一个产品等级结构时,抽象工厂模式退化为工厂模式。

当工厂模式只有一个工厂类,且类中方法为静态方法,工厂模式退化成简单工厂模式

简单工厂模式:工厂类职责过重,违背了OCP,加入新产品需要修改工厂

工厂模式:符合OCP,加入新产品,不需要修改抽象产品和抽象工厂

抽象工厂模式:若增加新的产品等级结构,即新的产品种类,违背OCP;若增加产品族,不违背OCP。


工厂模式
http://example.com/2023/10/15/计算机基础/设计模式/03-工厂模式/
作者
PALE13
发布于
2023年10月15日
许可协议