设计模式——结构型模式

目录

适配器模式

装饰器模式

代理模式

外观模式

桥接模式


适配器模式

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

适用场景

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

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

示例

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();
        }
    }
}
相关推荐
努力也学不会java9 小时前
【设计模式】状态模式
java·设计模式·状态模式
.豆鲨包9 小时前
【设计模式】单例模式
java·单例模式·设计模式
lpfasd12311 小时前
第2课:Agent系统架构与设计模式
设计模式·系统架构
青草地溪水旁14 小时前
设计模式(C++)详解—原型模式(1)
c++·设计模式·原型模式
青草地溪水旁15 小时前
设计模式(C++)详解—原型模式(2)
c++·设计模式·原型模式
青草地溪水旁15 小时前
设计模式(C++)详解—原型模式(3)
c++·设计模式·原型模式
new_daimond16 小时前
设计模式-装饰器模式详解
设计模式·装饰器模式
SamDeepThinking1 天前
用设计模式重构核心业务代码的一次实战
java·后端·设计模式