什么是抽象工厂模式
抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。
可以简单理解成是围绕一个超级工厂来创建其他工厂(这个超级工厂是其他工厂的工厂)。
适用场景:
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 强调一系列相关的产品对象(属于同一产品簇)一起使用创建对象需要大量的重复代码。
- 提供一个产品类的苦,所有的产品以同样的接口出现,从而使得客户端不依赖于具体实现。
- 抽象工厂模式适用于稳定的结构(即,不经常做出改变的一个工厂),如果要做更改,需要修改一个接口及其所有实现类。
优点:
- 具体产品在应用层的代码隔离,无需关心创建的细节。
- 将一个系列的产品统一到一起创建。
缺点:
- 规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难。
- 增加了系统的抽象性和理解难度。
为什么要使用抽象工厂模式
新时期有新问题
2021年6月2日后,智能终端可以使用Harmony OS了,一个设备可以轻松调用另一设备的算力、硬件,当然可以自由使用其他设备的应用。
这样,我们手头的播放器就不止两款了,假设现在有一个手机和一个平板电脑,上面都安装了bilibili和youku两个播放器。
我们要使用这四个播放器,可以使用简单工厂来实现:
简单工厂模式实现:
我们将一个终端看作一个工厂,这样就有两个工厂
两个工厂类:
public class PhonePlayerFactory {
public Iplayer getPlayer(String player) {
Iplayer iplayer;
if ("bilibili".equals(player)) {
iplayer = new PhoneBilibili();
} else if ("youku".equals(player)) {
iplayer = new PhoneYouku();
} else {
iplayer = null;
}
return iplayer;
}
}
public class PadPlayerFactory {
public Iplayer getPlayer(String player) {
Iplayer iplayer;
if ("bilibili".equals(player)) {
iplayer = new PadBilibili();
} else if ("youku".equals(player)) {
iplayer = new PadYouku();
} else {
iplayer = null;
}
return iplayer;
}
}
客户端:
public class User {
public static void main(String[] args) {
PadPlayerFactory padPlayerFactory = new PadPlayerFactory();
PhonePlayerFactory phonePlayerFactory = new PhonePlayerFactory();
String type = getType();
Iplayer player1 = padPlayerFactory.getPlayer(type);
Iplayer player2 = phonePlayerFactory.getPlayer(type);
player1.play();
player2.play();
}
private static String getType() {
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
}
存在的问题
- 两个Factory明明做的是相同的事,但却没有统一标准。
为了解决这个问题,我们就需要一个能创建工厂的工厂,即,抽象工厂。
抽象工厂模式实现:
- 用一个接口来规范一个工厂可以生产出bilibili和youku两个播放器,即IPlayerFactory。
- 由两个具体工厂来实现该规范,即PhonePlayerFactory和PadPlayerFactory。
工厂接口:
public interface IPlayerFactory {
IPlayer getBilibiliPlayer();
IPlayer getYoukuPlayer();
}
两个工厂实现类:
public class PhonePlayerFactory implements IPlayerFactory {
@Override
public IPlayer getBilibiliPlayer() {
return new PhoneBilibili();
}
@Override
public IPlayer getYoukuPlayer() {
return new PhoneYouku();
}
}
public class PadPlayerFactory implements IPlayerFactory {
@Override
public IPlayer getBilibiliPlayer() {
return new PadBilibili();
}
@Override
public IPlayer getYoukuPlayer() {
return new PadYouku();
}
}
播放器接口:
public interface IPlayer {
void play();
}
四个播放器:
public class PhoneBilibili implements IPlayer {
@Override
public void play() {
System.out.println("手机Bilibili播放。");
}
}
public class PhoneYouku implements IPlayer {
@Override
public void play() {
System.out.println("手机Youku播放。");
}
}
public class PadBilibili implements IPlayer {
@Override
public void play() {
System.out.println("平板电脑bilibili播放。");
}
}
public class PadYouku implements IPlayer {
@Override
public void play() {
System.out.println("平板电脑Youku播放。");
}
}
客户端:
import java.util.Scanner;
public class User {
public static void main(String[] args) {
String type = getType();
IPlayerFactory playerFactory;
if ("pad".equals(type)) {//这里可以再封装出一个工厂,用于生产工厂。
playerFactory = new PadPlayerFactory();
} else if ("phone".equals(type)) {
playerFactory = new PhonePlayerFactory();
}else {
System.out.println("无此设备");
return;
}
type = getType();
IPlayer player;
if ("bilibili".equals(type)) {
player = playerFactory.getBilibiliPlayer();
} else if ("youku".equals(type)) {
player = playerFactory.getYoukuPlayer();
} else {
System.out.println("没有此播放器");
return;
}
player.play();
}
private static String getType() {
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
}