工厂方法模式:是23中基本设计模式之一,它定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化延迟到了子类。
注: 这里所谓的 “决定” 并不是指模式允许子类本身在运行时做决定,而是在编写创建者类时,不需要知道实际创建的产品是哪一个,选择了使用哪个子类,就等于决定了创建的产品是什么了。
工厂方法模式的四要素:
- 创建者。
- 创建者实现。
- 产品。
- 产品实现。
来看一下它的类图:
下面我们通过实例来强化学习一下:
我们以去专卖店买笔记本做了例子,这里的产品肯定就是笔记本了,因为笔记本的种类很多,所以我们定义一个笔记本的抽象基类,这样可以统一产品的引用类,与具体的实现类隔离开来。
如果现在只考虑去一家专卖店(代号:A)买笔记本,可以运用上一篇 简单工厂模式 实现,通过工厂返回这个专卖店所有的电脑型号。
- 定义一个抽象的产品类 Laptop (笔记本电脑);
- 实现两个继承 Laptop 的具体笔记本电脑:A1Laptop、A2Laptop;
- 通过一个工厂 ALaptopFactory 根据类型名返回不同的笔记本的具体实现;
但是实际生活中,有很多不同的专卖店,每家专卖店买的电脑品牌也大有不同,这里我们就可以运用到工厂方法模式。有了不同专卖店的概念,每家专卖店都有自己的品牌及其系列电脑。这里我们将专卖店作为超类,让不同品牌的专卖店都继承它,但是由每个品牌的专卖店决定提供什么型号的电脑。
- 将笔记版专卖店定义一个抽象的类 LaptopStore;
- 让 ALaptopFactory 继承 LaptopStore;
- 扩展一个新的专卖店(代号:B) BLaptopFactory(它对应的产品为 B1Laptop、B2Laptop);
此时我们就利用了工厂模式设计实现了我们的需求。具体代码如下:
抽象专卖店类:
package com.dz.demo.pattern.factorypattern.factory;
import com.dz.demo.pattern.factorypattern.product.Laptop;
/**
* Created by dzwang on 2019/3/25.
*/
public abstract class LaptopStore {
public Laptop buyLaptop(String type) {
Laptop laptop = chooseLaptop(type);
System.out.println("I want to buy " + type);
laptop.information();
return laptop;
}
abstract Laptop chooseLaptop(String type);
}
继承于它的两个实现类:
// A专卖店
public class ALaptopFactory extends LaptopStore {
Laptop chooseLaptop(String type) {
Laptop laptop = null;
if (type.equals("A1")) {
laptop = new A1Laptop();
} else if (type.equals("A2")) {
laptop = new A2Laptop();
}
return laptop;
}
}
// B专卖店
public class BLaptopFactory extends LaptopStore {
Laptop chooseLaptop(String type) {
Laptop laptop = null;
if (type.equals("B1")) {
laptop = new B1Laptop();
} else if (type.equals("B2")) {
laptop = new B2Laptop();
}
return laptop;
}
}
定义抽象的产品基类:
public abstract class Laptop {
public abstract void information();
}
具体的产品类:
// A专卖店 A1型号笔记本
public class A1Laptop extends Laptop {
public void information(){
System.out.println("name:A1");
System.out.println("price:¥5000");
}
}
// A专卖店 A2型号笔记本
public class A2Laptop extends Laptop{
public void information(){
System.out.println("name:A2");
System.out.println("price:¥8000");
}
}
// B专卖店 B1型号笔记本
public class B1Laptop extends Laptop{
public void information(){
System.out.println("name:B1");
System.out.println("price:¥6000");
}
}
// B专卖店 B2型号笔记本
public class B2Laptop extends Laptop {
public void information() {
System.out.println("name:B2");
System.out.println("price:¥9000");
}
}
具体测试如下:
public class FactoryDemo {
public static void main(String[] args) {
/**
* Customer 1 want to buy A1
*/
LaptopStore laptopStore = new ALaptopFactory();
laptopStore.buyLaptop("A1");
/**
* Customer 2 want to buy B2
*/
laptopStore = new BLaptopFactory();
laptopStore.buyLaptop("B2");
}
}
// 运行结果如下:
// I want to buy A1
// name:A1
// price:¥5000
// I want to buy B2
// name:B2
// price:¥9000
工厂方法模式中具体类的实现和简单工厂模式其实很类似,不同的是工厂方法模式中的具体类扩展自一个类。
- 工厂方法模式创建的是一个框架,让子类决定如何去实现。
- 简单工厂是将对象的创建进行封装。
我们从中可以学习到:
- 将创建对象的代码进行封装,集中在一个类中或者方法中,可以有效的管理代码,方便后期维护和扩展。
- 在这里我们是针对接口的编程,而不是针对实现编程,其实也就是设计模式六大原则中的(依赖倒置原则)。