目录
适配器模式
意图:将一个类的接口转换成客户端期望的另一个接口
适用场景:
想使用一个已存在的类,而它的接口不符合要求
想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
示例
java
// 目标接口
interface MediaPlayer {
void play(String audioType, String fileName);
}
// 被适配者
interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
// 具体被适配者
class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("播放VLC文件: " + fileName);
}
@Override
public void playMp4(String fileName) {
// 什么也不做
}
}
class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// 什么也不做
}
@Override
public void playMp4(String fileName) {
System.out.println("播放MP4文件: " + fileName);
}
}
// 适配器
class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
// 客户端
class AudioPlayer implements MediaPlayer {
private MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// 内置支持MP3
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("播放MP3文件: " + fileName);
}
// 使用适配器支持其他格式
else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("无效的媒体格式: " + audioType);
}
}
}
装饰器模式
意图:动态地给一个对象添加一些额外的职责
适用场景:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
处理那些可以撤销的职责
当不能采用子类化的方法进行扩展时
示例
java
// 组件接口
interface Shape {
void draw();
}
// 具体组件
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 抽象装饰器
abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
public void draw() {
decoratedShape.draw();
}
}
// 具体装饰器
class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder();
}
private void setRedBorder() {
System.out.println("边框颜色: 红色");
}
}
// 客户端使用
public class DecoratorDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("普通圆形:");
circle.draw();
System.out.println("\n红色边框圆形:");
redCircle.draw();
System.out.println("\n红色边框矩形:");
redRectangle.draw();
}
}
代理模式
意图:为其他对象提供一种代理以控制对这个对象的访问
适用场景:
远程代理:为一个对象在不同的地址空间提供局部代表
虚拟代理:根据需要创建开销很大的对象
保护代理:控制对原始对象的访问
智能指引:在访问对象时执行一些附加操作
示例
java
// 主题接口
interface Image {
void display();
}
// 真实主题
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("加载图片: " + fileName);
}
@Override
public void display() {
System.out.println("显示图片: " + fileName);
}
}
// 代理
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
// 客户端使用
public class ProxyDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
// 图片将从磁盘加载
image.display();
System.out.println("");
// 图片不需要从磁盘加载
image.display();
}
}
外观模式
意图:为子系统中的一组接口提供一个一致的界面
适用场景:
要为一个复杂子系统提供一个简单接口时
客户端与抽象类的实现部分之间存在着很大的依赖性时
需要构建一个层次结构的子系统时
java
// 子系统类
class CPU {
public void freeze() {
System.out.println("CPU冻结");
}
public void jump(long position) {
System.out.println("CPU跳转到位置: " + position);
}
public void execute() {
System.out.println("CPU执行");
}
}
class Memory {
public void load(long position, byte[] data) {
System.out.println("内存加载数据到位置: " + position);
}
}
class HardDrive {
public byte[] read(long lba, int size) {
System.out.println("硬盘读取数据,LBA: " + lba + ", 大小: " + size);
return new byte[size];
}
}
// 外观类
class ComputerFacade {
private static final long BOOT_ADDRESS = 0x0000;
private static final long BOOT_SECTOR = 0x0000;
private static final int SECTOR_SIZE = 1024;
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
System.out.println("计算机启动中...");
cpu.freeze();
memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
cpu.jump(BOOT_ADDRESS);
cpu.execute();
System.out.println("计算机启动完成");
}
}
// 客户端使用
public class FacadeDemo {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.start();
}
}
桥接模式
意图:将抽象部分与它的实现部分分离,使它们都可以独立地变化
适用场景:
不希望在抽象和它的实现部分之间有一个固定的绑定关系
类的抽象以及它的实现都应该可以通过子类化加以扩展
对一个抽象的实现部分的修改应对客户不产生影响
java
// 实现接口
interface DrawingAPI {
void drawCircle(double x, double y, double radius);
}
// 具体实现A
class DrawingAPI1 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1绘制圆 at %.2f:%.2f 半径 %.2f%n", x, y, radius);
}
}
// 具体实现B
class DrawingAPI2 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2绘制圆 at %.2f:%.2f 半径 %.2f%n", x, y, radius);
}
}
// 抽象
abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw();
public abstract void resizeByPercentage(double pct);
}
// 精确抽象
class CircleShape extends Shape {
private double x, y, radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
@Override
public void resizeByPercentage(double pct) {
radius *= (1.0 + pct / 100.0);
}
}
// 客户端使用
public class BridgeDemo {
public static void main(String[] args) {
Shape[] shapes = new Shape[] {
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2())
};
for (Shape shape : shapes) {
shape.resizeByPercentage(2.5);
shape.draw();
}
}
}