# 《Java极简设计模式》第03章:工厂方法模式(FactoryMethod)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:用最简短的篇幅介绍工厂方法模式最核心的知识,理解工厂方法模式的设计精髓,并能够灵活运用到实际项目中,编写可维护的代码。

# 一、概述

⼯⼚模式也称简单⼯⼚模式,是创建型设计模式的⼀种,这种设计模式提供了按需创建对象的最佳⽅式。同时,这种创建⽅式不会对外暴露创建细节,并且会通过⼀个统⼀的接⼝创建所需对象。

⼯⼚模式属于创建型模式的⼀种,其⽬的就是隐藏创建类的细节与过程

定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。

# 二、适用性

1.当一个类不知道它所必须创建的对象的类的时候。

2.当一个类希望由它的子类来指定它所创建的对象的时候。

3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

# 三、参与者

  1. Product(抽象产品):定义工厂方法所创建的对象的接口。
  2. ConcreteProduct(具体产品):实现Product接口的具体类。
  3. Creator(抽象工厂):声明返回Product类型的工厂方法。这个方法应该返回一个Product类型的实例。可以是具体的也可以是抽象的类或接口。
  4. ConcreteCreator(具体工厂):重写Creator中的工厂方法以返回ConcreteProduct类型的实例。

# 四、类图


# 五、示例一

Product

package io.binghe.design.factotymethod;
/**
 * 定义一个接口Work
 * @author binghe
 */
public interface Work {
    /**
     * 定义方法
     */
    void doWork();
}
1
2
3
4
5
6
7
8
9
10
11

ConcreteProduct

package io.binghe.design.factotymethod;
/**
 * Work接口的具体实现类
 * @author binghe
 */
public class TeacherWork implements Work {
    public void doWork() {
        System.out.println("老师审批作业!");
    }
}
1
2
3
4
5
6
7
8
9
10
package io.binghe.design.factotymethod;
/**
 * Work接口的具体实现类
 * @author binghe
 */
public class StudentWork implements Work {
	@Override
    public void doWork() {
        System.out.println("学生做作业!");
    }
} 
1
2
3
4
5
6
7
8
9
10
11

Creator

package io.binghe.design.factotymethod;
/**
 * 抽象工厂接口
 * @author binghe
 */
public interface IWorkFactory {
    /**
     * 定义获取Work实例对象的方法
     * @return
     */
    Work getWork();
}
1
2
3
4
5
6
7
8
9
10
11
12

ConcreteCreator

package io.binghe.design.factotymethod;
/**
 * IWorkFactory工厂的实现类
 * @author binghe
 */
public class StudentWorkFactory implements IWorkFactory {
	@Override
    public Work getWork() {
        return new StudentWork();
    }
}
1
2
3
4
5
6
7
8
9
10
11
package io.binghe.design.factotymethod;
/**
 * IWorkFactory工厂的实现类
 * @author binghe
 */
public class TeacherWorkFactory implements IWorkFactory {
	@Override
    public Work getWork() {
        return new TeacherWork();
    }
}
1
2
3
4
5
6
7
8
9
10
11

Test

package io.binghe.design.factotymethod;
/**
 * 测试类
 * @author binghe
 */
public class Test {
    public static void main(String[] args) {
        IWorkFactory studentWorkFactory = new StudentWorkFactory();
        studentWorkFactory.getWork().doWork();
        
        IWorkFactory teacherWorkFactory = new TeacherWorkFactory();
        teacherWorkFactory.getWork().doWork();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Result

学生做作业!
老师审批作业!
1
2

# 六、示例二

下⾯我⽤可以利⽤

以电脑店为例,我是⼀个纯⼩⽩,⾯对琳琅满⽬的各种电脑⼀脸懵X,根本⽆从下⼿~

电脑接⼝

public interface Computer {
 public String describe();
}
1
2
3

外星⼈游戏笔记本

public class Alienware implements Computer{
 @Override
 public String describe() {
 return "外星⼈ALIENWARE m15 R7 15.6英⼨⾼端游戏本 12代i7 32G RTX3060 QH
D 240Hz ⾼刷屏 轻薄笔记本电脑2765QB";
 }
}
1
2
3
4
5
6
7

⾼性能独显PC主机

public class Desktop implements Computer{
 @Override
 public String describe() {
 return "外星⼈ALIENWARE R13 ⽔冷电竞游戏⾼端台式机 第12代i7 32G 512GB+2
T RTX3070 办公台式机 9776W";
 }
}
1
2
3
4
5
6
7

Macbook办公轻薄本

public class Macbook implements Computer{
 @Override
 public String describe() {
 return "Apple MacBook Pro 13.3 ⼋核M1芯⽚ 8G 256G SSD 深空灰 笔记本电
脑 轻薄本 MYD82CH/A";
 }
}
1
2
3
4
5
6
7

2U戴尔服务器

public class Server implements Computer{
 @Override
 public String describe() {
 return "戴尔(DELLR740R7502U机架式服务器主机双路GPU深度学习 R7401
*银牌4210R 1020线程〗 8G内存⼁1TB SATA硬盘 ⼁H350戴尔(DELL;
 }
}
1
2
3
4
5
6
7

此时顾客将⾯对⼏⼗种不同性能,不同规格不同种类的电脑,难道顾客必须了解所有细节才能决定使⽤哪⼀个吗?

这⾥就破坏了“迪⽶特法则(知道的越少越好)”,⼤多数客户并不需要了解每⼀台细节,我们要把选择权交还给电脑店这⼀⽅。

控制权在顾客⽅是不对的

image-20241119153346659

我们需要⼀个⼯⼚类,帮助顾客进⾏决策,这样控制权掌握

image-20241119153423247

正确的做法

增加⼀个售货员帮助⽤户实现决策,根据客户的不同要求提供对应的产品。这个售货员就是充当了“⼯⼚"的⻆⾊。⼯⼚模式的特点:提供⽅法,返回接⼝

public class ShopAssistant {
 public Computer suggest(String purpose){
 Computer computer = null;
 if(purpose.equals("⽹站建设")){
 return new Server();
 }else if(purpose.equals("电竞⽐赛")){
 return new Desktop();
 }else if(purpose.equals("⽇常办公")){
 return new Macbook();
 }else if(purpose.equals("3A游戏")){
 return new Alienware();
 }
 return computer;
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

站在顾客这⼀⽅,获取对象的过程变得⾮常简单,通过售货员这个⼯⼚帮助我们获取需要的对象,同时不再关注对象创建的过程与细节

public class Customer {
 public static void main(String[] args) {
 ShopAssistant shopAssistant = new ShopAssistant();
 Computer c = shopAssistant.suggest("3A游戏");
 System.out.println(c.describe());
 }
}
1
2
3
4
5
6
7

项⽬中的作⽤

难道让⽤户⾃⼰选择使⽤那个语⾔吗?

在界⾯上提供个下拉选择框,让⽤户⾃⼰选择语⾔?

image-20241119153631863