设计模式——结构型模式

目录

适配器模式

装饰器模式

代理模式

外观模式

桥接模式


适配器模式

意图:将一个类的接口转换成客户端期望的另一个接口

适用场景

  • 想使用一个已存在的类,而它的接口不符合要求

  • 想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作

示例

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();
        }
    }
}
相关推荐
灰子学技术1 天前
Envoy 使用的设计模式技术文档
设计模式
Carl_奕然2 天前
【智能体】Agent的四种设计模式之:ReAct
人工智能·设计模式·语言模型
二哈赛车手2 天前
新人笔记---多策略搭建策略执行链实现RAG检索后过滤
java·笔记·spring·设计模式·ai·策略模式
楼田莉子2 天前
仿Muduo的高并发服务器:Channel模块与Poller模块
linux·服务器·c++·学习·设计模式
geovindu2 天前
go: Strategy Pattern
开发语言·设计模式·golang·策略模式
嵌入式学习_force3 天前
02_state
设计模式·蓝牙
qcx233 天前
Warp源码深度解析(七):Token预算策略——双轨计费、上下文溢出与摘要压缩
人工智能·设计模式·rust·wrap
Cosolar3 天前
提示词工程面试题系列 - Zero-Shot Prompting 和 Few-Shot Prompting 的核心区别是什么?
人工智能·设计模式·架构
geovindu4 天前
go:Template Method Pattern
开发语言·后端·设计模式·golang·模板方法模式
钝挫力PROGRAMER4 天前
贫血模型的改进
java·开发语言·设计模式·架构