2.1、介绍
工厂模式的核心本质:
- 实例化对象不使用 new 创建,用工厂方法代替;
- 将选择实现类、创建对象统一管理和控制,从而使调用者跟实现类解耦。
核心思想就是实现创建者和调用者的分离。
详细分类:
- 简单工厂模式(用来生产同一等级结构中的任意产品。如果增加新产品,需要覆盖已有代码。该模式中只有一个工厂,又称为静态工厂模式)
- 工厂方法模式(用来生产同一等级结构中的固定产品。可以增加任意产品。该模式中有多个工厂,并且实现了同一个接口。在新增产品的时候,没有动原来的代码,是新建了类)
- 抽象工厂模式(围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂)
这种类型的设计模式属于创建型模式。
2.2、简单工厂模式
以消费者买车为例,使用简单工厂模式,在控制台实现输出“买到五菱车!”和“买到宝马车!”。
先创建接口:Car
,里面有方法 name()
:
public interface Car {
void name();
}
创建实现类 Wuling
实现接口 Car
:
public class Wuling implements Car {
@Override
public void name() {
System.out.println("买到五菱车!");
}
}
创建实现类 Baoma
,实现接口 Car
:
public class Baoma implements Car {
@Override
public void name() {
System.out.println("买到宝马车!");
}
}
重点来了,创建车工厂类 CarFactory
,由车工厂实例化对象:
public class CarFactory {
public static Car getCar(String car) {
if (car.equals("五菱")){
return new Wuling();
} else if (car.equals("宝马")){
return new Baoma();
} else {
return null;
}
}
}
消费者买车类 Consumer
,根据车名直接调用工厂类买车:
public class Consumer {
public static void main(String[] args) {
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("宝马");
car1.name();
car2.name();
}
}
控制台结果如图:
另外,如果要买其他车,需要创建该车的实现类,并修改车工厂的代码,只是这样做会违背开闭原则。从设计原则来讲,是不支持简单工厂模式的,但在实际开发中该模式用的最多。
2.3、工厂方法模式
工厂方法模式不会违背开闭原则。
它是在简单工厂模式的基础上,创建车工厂接口,然后一一创建车实现车工厂接口:
已有接口 Car
、实现类 Wuling
、实现类 Baoma
,代码同简单工厂模式一样,现在创建接口车工程 CarFactory
:
public interface CarFactory {
Car getCar();
}
创建实现类 WulingFactory
实现车工厂接口,生产五菱车:
public class WulingFactory implements CarFactory {
@Override
public Car getCar() {
return new Wuling();
}
}
创建实现类 BaomaFactory
实现车工厂接口,生产宝马车:
public class BaomaFactory implements CarFactory {
@Override
public Car getCar() {
return new Baoma();
}
}
工厂搭建完毕,下面是消费者买车的代码 Consumer
,直接向该车的工厂调用方法:
public class Consumer {
public static void main(String[] args) {
Car car1 = new WulingFactory().getCar();
Car car2 = new BaomaFactory().getCar();
car1.name();
car2.name();
}
}
结果跟简单工厂模式一样。
如果要消费者要买其他车,需要创建该车的实现类实现接口 Car
和该车的车工厂类实现 CarFactory
。工厂方法模式满足了开闭原则,只是在代码量上比简单工厂模式要多。
2.4、抽象工厂模式
定义:抽象工厂模式提供了一个创建一系列相关或者相互依赖的接口,无需指定它们具体的类。
适用场景:
- 客户端(即应用层)不依赖产品类实例如何被创建、实现等细节。
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码。
- 提供一个产品类的库,所有产品以同样的接口出现,从而使得客户端不依赖于具体的实现。
优点:
- 具体产品在应用层的代码隔离,无需关心创建的细节;
- 将一个系列的产品统一到一起创建。
缺点:
- 规定了所有可能被创建的产品集合,产品族中扩展新产品困难;
- 增加了系统的抽象性和理解难度。
举例:使用抽象工厂模式在控制台输出小米系列产品“小米手机打电话”、“小米手机发短信”、“小米路由器打开WIFI”。
首先我们需要两个接口,一个生产手机 IphoneProduct
:
public interface IphoneProduct {
void CallUp();// 手机打电话
void SendSMS();// 手机发短信
}
一个生产路由器 RouterProduct
:
public interface RouterProduct {
void OpenWIFI();// 路由器打开WIFI
}
接口写好了,下面该小米产品实现这两个接口,创建实现类 XiaomiIphone
,实现接口 IphoneProduct
:
public class XiaomiIphone implements IphoneProduct {
@Override
public void CallUp() {
System.out.println("小米手机打电话");
}
@Override
public void SendSMS() {
System.out.println("小米手机发短信");
}
}
创建实现类 XiaomiRouter
,实现接口 RouterProduct
:
public class XiaomiRouter implements RouterProduct {
@Override
public void OpenWIFI() {
System.out.println("小米路由器打开WIFI");
}
}
下面重点来了,创建抽象产品工厂接口 ProductFactory
:
public interface ProductFactory {
// 生产手机
IphoneProduct iphoneProduct();
// 生产路由器
RouterProduct routerProduct();
}
然后再创建接口小米系列产品的工厂 XiaomiFactory
,实现 ProductFactory
接口:
public class XiaomiFactory implements ProductFactory{
// 生产小米手机
@Override
public IphoneProduct iphoneProduct() {
return new XiaomiIphone();
}
// 生产小米路由器
@Override
public RouterProduct routerProduct() {
return new XiaomiRouter();
}
}
最后,创建消费者类 Consumer
购买小米手机打电话发短信、购买小米路由器打开WIFI:
public class Consumer {
public static void main(String[] args) {
System.out.println("====== 小米系列产品 ======");
// 创建小米工厂
XiaomiFactory xiaomiFactory = new XiaomiFactory();
// 小米工厂生产手机
IphoneProduct iphoneProduct = xiaomiFactory.iphoneProduct();
iphoneProduct.CallUp();
iphoneProduct.SendSMS();
// 小米工厂生产路由器
RouterProduct routerProduct = xiaomiFactory.routerProduct();
routerProduct.OpenWIFI();
}
}
控制台运行结果如下:
如果要生产其他系列产品的手机和路由器,需要创建三个该系列的实现类,一个实现 IphoneProduct
接口,一个实现 RouterProduct
接口,一个实现 ProductFactory
接口。