设计模式-结构性模式

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

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();
    }
}
相关推荐
阿波茨的鹅2 小时前
C++ | 设计模式 | 代理模式
c++·设计模式·代理模式
_真相只有一个3 小时前
结构型模式 - 代理模式 (Proxy Pattern)
设计模式·代理模式
扣丁梦想家3 小时前
设计模式教程:模板方法模式(Template Method Pattern)
java·设计模式·模板方法模式
萧萧玉树4 小时前
设计模式的引入
设计模式
工一木子4 小时前
【HeadFirst系列之HeadFirst设计模式】第13天之代理模式:控制对象访问的利器!
设计模式·代理模式
多多*8 小时前
设计模式 工厂模式 工厂方法模式 抽象工厂模式
设计模式·工厂方法模式·抽象工厂模式
啥都不懂的小小白9 小时前
Java常见设计模式(上):创建型模式
java·开发语言·设计模式
花王江不语10 小时前
**模式的好处 (设计模式)
开发语言·设计模式
galaa201111 小时前
TypeScript设计模式(4):装饰器模式
设计模式