设计模式-结构性模式

结构型模式主要关注类或对象的组合,旨在通过识别简单的结构关系来设计更复杂的结构。以下是几种常见的结构型设计模式:

1. 适配器模式(Adapter Pattern)

    • 将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
    • 适用于需要使用现有类但其接口不符合需求的情况。

假设我们有一个旧的MediaPlayer接口,它只能播放.mp3文件。现在我们需要一个新功能,能够播放.wav格式的文件。我们可以使用适配器模式来解决这个问题。

复制代码
// 已有的MediaPlayer接口
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// 实现了MediaPlayer接口的类
class AudioPlayer implements MediaPlayer {
    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("Playing mp3 file. Name: " + fileName);
        } else {
            System.out.println("Invalid media. " + audioType + " format not supported");
        }
    }
}

// 新的AdvancedMediaPlayer接口及其实现类
interface AdvancedMediaPlayer {
    void playWav(String fileName);
}

class WavPlayer implements AdvancedMediaPlayer {
    @Override
    public void playWav(String fileName) {
        System.out.println("Playing wav file. Name: " + fileName);
    }
}

// 创建适配器类
class MediaAdapter implements MediaPlayer {
    private AdvancedMediaPlayer advancedMusicPlayer;

    public MediaAdapter() {
        advancedMusicPlayer = new WavPlayer();
    }

    @Override
    public void play(String audioType, String fileName) {
        if(audioType.equalsIgnoreCase("wav")) {
            advancedMusicPlayer.playWav(fileName);
        }
    }
}

// 使用适配器
public class AdapterPatternDemo {
    public static void main(String[] args) {
        MediaPlayer audioPlayer = new AudioPlayer();

        audioPlayer.play("mp3", "song.mp3");
        audioPlayer.play("wav", "song.wav"); // 这里会显示不支持

        MediaPlayer mediaAdapter = new MediaAdapter();
        mediaAdapter.play("wav", "song.wav"); // 现在可以播放wav文件
    }
}

2. 桥接模式(Bridge Pattern)

    • 将抽象部分与它的实现部分分离,使它们都可以独立变化。
    • 适用于当不想在抽象和实现之间建立固定的绑定关系时,例如图形库中形状和颜色的组合。

假设我们有一个绘图应用程序,它可以绘制不同形状,并且这些形状可以用不同的颜色绘制。为了使形状和颜色独立变化,我们可以使用桥接模式。

复制代码
// 颜色接口
interface Color {
    void applyColor();
}

// 具体的颜色实现
class RedColor implements Color {
    @Override
    public void applyColor() {
        System.out.println("Red color applied.");
    }
}

class BlueColor implements Color {
    @Override
    public void applyColor() {
        System.out.println("Blue color applied.");
    }
}

// 抽象的形状类,持有Color对象的引用
abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    abstract void draw();
}

// 具体的形状实现
class Circle extends Shape {
    public Circle(Color color) {
        super(color);
    }

    @Override
    void draw() {
        System.out.print("Drawing Circle. ");
        color.applyColor();
    }
}

// 使用桥接模式
public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape redCircle = new Circle(new RedColor());
        redCircle.draw(); // 输出:Drawing Circle. Red color applied.
        
        Shape blueCircle = new Circle(new BlueColor());
        blueCircle.draw(); // 输出:Drawing Circle. Blue color applied.
    }
}

3. 组合模式(Composite Pattern)

    • 允许将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
    • 常用于文件系统、菜单等层次化结构的场景。

假设我们有一个组织结构,包括员工和部门。每个部门可能包含多个员工和其他部门。我们可以使用组合模式来处理这种"部分-整体"的层次结构。

复制代码
// 组件接口
interface Employee {
    void showEmployeeDetails();
}

// 叶子节点
class Developer implements Employee {
    private String name;
    private long empId;

    public Developer(String name, long empId) {
        this.name = name;
        this.empId = empId;
    }

    @Override
    public void showEmployeeDetails() {
        System.out.println("Developer Name: " + name + ", EmpId: " + empId);
    }
}

// 组合部件
class Manager implements Employee {
    private List<Employee> employees = new ArrayList<>();

    public void addEmployee(Employee emp) {
        employees.add(emp);
    }

    public void removeEmployee(Employee emp) {
        employees.remove(emp);
    }

    @Override
    public void showEmployeeDetails() {
        for (Employee emp : employees) {
            emp.showEmployeeDetails();
        }
    }
}

// 使用组合模式
public class CompositePatternDemo {
    public static void main(String[] args) {
        Employee dev1 = new Developer("John", 1001L);
        Employee dev2 = new Developer("Jane", 1002L);

        Manager manager = new Manager();
        manager.addEmployee(dev1);
        manager.addEmployee(dev2);

        Employee dev3 = new Developer("Doe", 1003L);
        manager.addEmployee(dev3);

        manager.showEmployeeDetails();
    }
}

4. 装饰模式(Decorator Pattern)

    • 动态地给一个对象添加一些额外的职责,就增加功能来说,比生成子类更为灵活。
    • 适用于需要动态地为对象添加功能而不改变原有代码的情况,如Java中的I/O流。

装饰模式允许你通过创建一个包装对象动态地向一个对象添加功能,而不需要修改其结构。

复制代码
// 基础组件接口
interface Coffee {
    double getCost(); // 获取成本
    String getDescription(); // 获取描述
}

// 具体组件实现
class SimpleCoffee implements Coffee {
    @Override
    public double getCost() { return 10; } // 简单咖啡的成本

    @Override
    public String getDescription() { return "Simple Coffee"; }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee c) {
        this.decoratedCoffee = c;
    }

    @Override
    public double getCost() { return decoratedCoffee.getCost(); }

    @Override
    public String getDescription() { return decoratedCoffee.getDescription(); }
}

// 牛奶装饰器
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee c) { super(c); }

    @Override
    public double getCost() { return super.getCost() + 2; }

    @Override
    public String getDescription() { return super.getDescription() + ", Milk"; }
}

// 使用装饰模式
public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Coffee myCoffee = new MilkDecorator(new SimpleCoffee());
        System.out.println("Cost: " + myCoffee.getCost());
        System.out.println("Description: " + myCoffee.getDescription());
    }
}

5. 外观模式(Facade Pattern)

    • 为子系统中的一组接口提供一个一致的界面,定义了一个高层接口,这个接口使得这一子系统更加容易使用。
    • 适用于简化复杂系统的接口,如数据库连接管理。

外观模式提供了一个统一的接口,用来访问子系统中的一群接口。它提供了一个高层次的接口,使得子系统更易于使用。

复制代码
// 子系统类
class CPU {
    public void processData() { System.out.println("Processing data."); }
}

class Memory {
    public void load() { System.out.println("Loading data from memory."); }
}

class HardDrive {
    public void readData() { System.out.println("Reading data from hard drive."); }
}

// 外观类
class ComputerFacade {
    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 startComputer() {
        memory.load();
        hardDrive.readData();
        cpu.processData();
    }
}

// 使用外观模式
public class FacadePatternDemo {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.startComputer();
    }
}

6. 享元模式(Flyweight Pattern)

    • 运用共享技术有效地支持大量细粒度的对象。
    • 适用于需要创建大量相似对象且内存占用成为问题的情况,如文本编辑器中的字符对象。

享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能。它通过共享尽可能多的对象来做到这一点。

复制代码
// 享元接口
interface Shape {
    void draw(String color);
}

// 具体享元类
class Circle implements Shape {
    private String color;

    public Circle(String color) {
        this.color = color;
    }

    @Override
    public void draw(String fillColor) {
        System.out.println("Drawing Circle [Color: " + color + ", FillColor: " + fillColor + "]");
    }
}

// 享元工厂
class ShapeFactory {
    private static final HashMap<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle)circleMap.get(color);

        if(circle == null) {
            circle = new Circle(color);
            circleMap.put(color, circle);
            System.out.println("Creating circle of color: " + color);
        }
        return circle;
    }
}

// 使用享元模式
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();

        Shape shape1 = shapeFactory.getCircle("Red");
        shape1.draw("Dark Red");

        Shape shape2 = shapeFactory.getCircle("Red"); // 不会创建新对象
        shape2.draw("Light Red");
    }
}

7. 代理模式(Proxy Pattern)

    • 为其他对象提供一种代理以控制对这个对象的访问。
    • 适用于需要在访问对象时加入额外处理逻辑的情况,如远程调用、权限检查等。

代理模式为其他对象提供一种代理以控制对这个对象的访问。

复制代码
// 主题接口
interface Image {
    void display();
}

// 真实主题类
class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }

    private void loadFromDisk(String fileName) {
        System.out.println("Loading " + 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 ProxyPatternDemo {
    public static void main(String[] args) {
        Image image = new ProxyImage("test_10mb.jpg");

        // 图像将从磁盘加载
        image.display();
        System.out.println("");
        // 图像不会从磁盘加载
        image.display();
    }
}
相关推荐
晨米酱17 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤2 天前
工厂模式
设计模式