书中提到了这种写法,Mosaic create(Supplier<? extends Tile> tileFactory)
1. 方法声明的含义解析
关键部分:
-
Mosaic:- 此方法的返回类型是一个
Mosaic对象。
- 此方法的返回类型是一个
-
create:- 这是方法名称,表明这个方法的作用是 “创建” 一个 Mosaic 对象。
-
Supplier<? extends Tile> tileFactory:- 参数类型是
Supplier,它是一个函数式接口,允许 惰性提供(lazy supply) 一个Tile的实现。 ? extends Tile是 泛型通配符,表示调用者可以传递一个Supplier,该Supplier返回类型可以是Tile或其子类。
- 参数类型是
翻译成自然语言:
这个方法是一个静态工厂方法,用于创建一个 Mosaic 对象。调用方需要向方法提供一个 Supplier,该 Supplier 能够生成一个 Tile 的实例(可能是某个具体子类的实例,而非Tile本身)。
2. 为什么使用 Supplier<? extends Tile>
问题背景:
在传统的工厂设计模式中,创建一个 Mosaic 通常会直接传入一个具体的 Tile 对象,例如:
Mosaic mosaic = new Mosaic(new ConcreteTile());
然而,这种方式存在以下问题:
-
强耦合性:
调用方需要直接提供ConcreteTile的实例。如果想动态决定实例化逻辑(如:参数配置、动态初始化),则需要大量冗余代码。 -
缺乏灵活性:
如果需要按需生成不同的Tile子类,或者需要延迟构造(Lazy Initialization),传统构造方法难以高效实现。
Supplier 提供的优势:
Java 8 引入 java.util.function.Supplier 这一函数式接口,能够为我们提供更灵活的创建方式:
-
延迟生成(Lazy Evaluation):
Supplier是一个无参方法的函数式接口,只在真正需要Tile对象时才会调用。例如,只有在 Mosaic 确保需要一个Tile后,它才会调用tileFactory.get()生成实例,避免浪费资源。
-
灵活支持多态(子类):
- 使用
? extends Tile表示,tileFactory可以生产Tile或其子类。调用者无需关心 Mosaic 的具体实现,只需要提交合适的工厂方法即可。
- 使用
-
高扩展性:
- 不同的
Supplier可以实现不同的对象创建方式(如具体子类的选择、对象池的复用、动态参数配置等)。
- 不同的
3. 实际使用中的优势
-
简单且灵活的对象生成:
你不需要绑定具体的Tile实例,可以根据需求动态提供Supplier。 -
接口表达意图:
通过使用Supplier,明确了Mosaic的实现只需要知道如何生成Tile,它无需了解Tile的具体实现细节。这符合 “依赖倒置原则”。 -
更好的兼容 Java 的流式 API 和函数式编程:
Supplier是标准函数式接口,极其方便配合Stream、Optional等 Java 8+ 的特性使用。
4. 示例:Mosaic 和 Tile 的实际应用场景
假设你正在开发一个拼图游戏,每个拼图由若干 Tile(小方块)组成,而 Mosaic 是由这些方块拼接起来的大图片。
Tile 有多个具体实现(例如 ColorTile, ImageTile)。
基类和子类定义:
// Tile 是拼图的基础
public interface Tile {
void draw(); // 每个 Tile 都可以被绘制
}
// ColorTile 是 Tile 的具体实现,绘制一块特定的颜色
public class ColorTile implements Tile {
private final String color;
// 构造器
public ColorTile(String color) {
this.color = color;
}
@Override
public void draw() {
System.out.println("Drawing a tile with color: " + color);
}
}
// ImageTile 是另一种 Tile,它绘制图片
public class ImageTile implements Tile {
private final String imagePath;
public ImageTile(String imagePath) {
this.imagePath = imagePath;
}
@Override
public void draw() {
System.out.println("Drawing a tile with image: " + imagePath);
}
}
Mosaic 定义:
import java.util.List;
import java.util.ArrayList;
import java.util.function.Supplier;
public class Mosaic {
private final List<Tile> tiles = new ArrayList<>();
// 私有化构造器,强制使用静态方法构造
private Mosaic(List<Tile> tiles) {
this.tiles.addAll(tiles);
}
// 静态工厂方法
public static Mosaic create(Supplier<? extends Tile> tileFactory) {
List<Tile> tiles = new ArrayList<>();
// 示例:创建 5 个 Tile,通过 tileFactory 提供不同的类型
for (int i = 0; i < 5; i++) {
tiles.add(tileFactory.get());
}
return new Mosaic(tiles);
}
// 为 Mosaic 上的所有 Tile 绘制图像
public void draw() {
tiles.forEach(Tile::draw);
}
}
使用 Mosaic.create 建立不同的 Mosaic 拼图:
1. 提供 ColorTile 工厂
Mosaic colorMosaic = Mosaic.create(() -> new ColorTile("Red"));
colorMosaic.draw();
/*
输出:
Drawing a tile with color: Red
Drawing a tile with color: Red
Drawing a tile with color: Red
Drawing a tile with color: Red
Drawing a tile with color: Red
*/
2. 提供 ImageTile 工厂
Mosaic imageMosaic = Mosaic.create(() -> new ImageTile("image.jpg"));
imageMosaic.draw();
/*
输出:
Drawing a tile with image: image.jpg
Drawing a tile with image: image.jpg
Drawing a tile with image: image.jpg
Drawing a tile with image: image.jpg
Drawing a tile with image: image.jpg
*/
3. 动态选择 Tile 类型
你可以通过业务逻辑动态决定生成哪种 Tile:
Mosaic mixedMosaic = Mosaic.create(() -> {
if (Math.random() > 0.5) {
return new ColorTile("Blue");
} else {
return new ImageTile("pattern.jpg");
}
});
mixedMosaic.draw();
/*
输出(随机):
Drawing a tile with color: Blue
Drawing a tile with color: Blue
Drawing a tile with image: pattern.jpg
Drawing a tile with color: Blue
Drawing a tile with image: pattern.jpg
*/
总结
Mosaic create(Supplier<? extends Tile> tileFactory) 采用了现代 Java 编程的最佳实践:
- 函数式接口的优雅性:通过
Supplier提供控制反转,让调用者决定如何生成Tile实例。 - 灵活多态机制:利用
? extends Tile,Mosaic 可以兼容Tile的任意子类,不必限制为Tile本身。 - 惰性(Lazy)评估:只有在实际需要时才会创建
Tile对象(tileFactory.get())。
1012

被折叠的 条评论
为什么被折叠?



