enyang
enyang
Published on 2025-11-22 / 2 Visits
0
0

设计模式 <3> —— 结构型模式 (Structural Patterns)

结构型设计模式主要解决类和对象之间的组合关系。它关注如何通过不同的方式组合类和对象,使系统的结构更加灵活和高效。通过这些模式,我们可以优化代码结构,减少系统间的耦合性,增加代码的可维护性和可扩展性。

1. 适配器模式 (Adapter Pattern)

适配器模式的主要目的是将某个类的接口转化为客户端期望的接口,使得本来由于接口不兼容而不能一起工作的类可以协同工作。

实现方式

  • 定义一个目标接口,客户端通过该接口与适配器交互。

  • 创建一个适配器类,将源类的接口转换为目标接口。

Java实现

// 目标接口
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// 源类:VLC播放器
class VLCPlayer implements MediaPlayer {
    public void play(String audioType, String fileName) {
        System.out.println("Playing VLC file. Name: " + fileName);
    }
}

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

    public MediaAdapter(String audioType) {
        if(audioType.equalsIgnoreCase("mp4")){
            advancedMusicPlayer = new MP4Player();
        }
        else if(audioType.equalsIgnoreCase("vlc")){
            advancedMusicPlayer = new VLCPlayer();
        }
    }

    public void play(String audioType, String fileName) {
        if(audioType.equalsIgnoreCase("vlc")){
            advancedMusicPlayer.playVlc(fileName);
        }
        else if(audioType.equalsIgnoreCase("mp4")){
            advancedMusicPlayer.playMP4(fileName);
        }
    }
}

// 高级播放器接口
interface AdvancedMediaPlayer {
    void playVlc(String fileName);
    void playMP4(String fileName);
}

// 具体的高级播放器:MP4播放器
class MP4Player implements AdvancedMediaPlayer {
    public void playVlc(String fileName) {
        // 什么都不做
    }

    public void playMP4(String fileName) {
        System.out.println("Playing MP4 file. Name: " + fileName);
    }
}

public class AdapterDemo {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();

        audioPlayer.play("mp4", "beyond the horizon.mp4");
        audioPlayer.play("vlc", "far far away.vlc");
        audioPlayer.play("avi", "mind me.avi");
    }
}
  • AudioPlayer 充当客户端与适配器之间的连接角色,它只关心播放文件而不关心具体的播放器实现。

  • MediaAdapter 类将 VLC 和 MP4 播放器适配为统一的接口 MediaPlayer

2. 桥接模式 (Bridge Pattern)

桥接模式将抽象部分与实现部分分离,使得二者可以独立地变化。它将接口与实现的继承关系解耦,提高系统的灵活性。

实现方式

  • 创建一个桥接接口,定义抽象部分的操作。

  • 将实现部分封装到独立的类中,实现接口。

  • 通过桥接接口,将抽象类与实现类进行关联。

Java实现

// 抽象部分
interface Shape {
    void draw();
}

// 具体抽象类
class Circle implements Shape {
    private Color color;

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

    public void draw() {
        System.out.print("Drawing a Circle, Color: ");
        color.fill();
    }
}

// 实现部分
interface Color {
    void fill();
}

// 具体实现类:Red
class Red implements Color {
    public void fill() {
        System.out.println("Red");
    }
}

// 具体实现类:Blue
class Blue implements Color {
    public void fill() {
        System.out.println("Blue");
    }
}

public class BridgeDemo {
    public static void main(String[] args) {
        Shape redCircle = new Circle(new Red());
        redCircle.draw();  // 输出: Drawing a Circle, Color: Red

        Shape blueCircle = new Circle(new Blue());
        blueCircle.draw();  // 输出: Drawing a Circle, Color: Blue
    }
}
  • Shape 类与 Color 类通过桥接接口解耦。Circle 是一个抽象类,RedBlue 是具体的实现类。

  • 使用桥接模式,可以方便地将抽象部分与实现部分独立扩展。


3. 组合模式 (Composite Pattern)

组合模式使得客户端可以以一致的方式对待单个对象和对象集合。它将对象组合成树形结构来表示“部分-整体”层次结构,能够让客户端对单个对象和复合对象(容器)进行相同的处理。

实现方式

  • 定义一个组件接口,声明所有对象的公共方法。

  • 叶子节点类实现组件接口,表示单一对象。

  • 容器节点类实现组件接口,包含多个叶子节点或者子节点。

Java实现

// 组件接口
interface Component {
    void operation();
}

// 叶子节点类
class Leaf implements Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    public void operation() {
        System.out.println("Leaf " + name + " operation.");
    }
}

// 容器节点类
class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public void operation() {
        for (Component component : children) {
            component.operation();
        }
    }
}

public class CompositeDemo {
    public static void main(String[] args) {
        Composite root = new Composite();
        Composite branch1 = new Composite();
        Composite branch2 = new Composite();

        Leaf leaf1 = new Leaf("Leaf1");
        Leaf leaf2 = new Leaf("Leaf2");

        root.add(branch1);
        root.add(branch2);

        branch1.add(leaf1);
        branch2.add(leaf2);

        root.operation();
    }
}
  • Composite 类是一个容器,它包含多个 Component 对象,既可以是叶子节点,也可以是子容器节点。

  • 客户端可以一致地操作单一叶子节点或包含多个叶子节点的容器。


4. 装饰器模式 (Decorator Pattern)

装饰器模式允许你动态地给一个对象添加额外的职责,而不影响其他对象。通过组合而非继承的方式,装饰器模式可以在运行时修改对象的行为。

实现方式

  • 定义一个组件接口,表示被装饰的对象。

  • 创建一个装饰器类,实现组件接口,并在其中添加额外功能。

Java实现

// 组件接口
interface Coffee {
    double cost();
}

// 具体组件类
class SimpleCoffee implements Coffee {
    public double cost() {
        return 5;
    }
}

// 装饰器基类
class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

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

    public double cost() {
        return decoratedCoffee.cost();
    }
}

// 具体装饰器类:加糖
class WithSugar extends CoffeeDecorator {
    public WithSugar(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 2;
    }
}

// 具体装饰器类:加奶
class WithMilk extends CoffeeDecorator {
    public WithMilk(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 3;
    }
}

public class DecoratorDemo {
    public static void main(String[] args) {
        Coffee simpleCoffee = new SimpleCoffee();
        System.out.println("Cost of simple coffee: " + simpleCoffee.cost());

        Coffee milkCoffee = new WithMilk(simpleCoffee);
        System.out.println("Cost of coffee with milk: " + milkCoffee.cost());

        Coffee sugarMilkCoffee = new WithSugar(milkCoffee);
        System.out.println("Cost of coffee with milk and sugar: " + sugarMilkCoffee.cost());
    }
}
  • Coffee 接口定义了对象的核心功能。

  • WithSugarWithMilk 是装饰器类,动态地增加新的功能。

5. 外观模式 (Facade Pattern)

外观模式为复杂的子系统提供一个统一的接口,使得客户端通过简单的接口访问复杂的子系统,简化系统的使用。

实现方式

  • 定义一个外观类,它包含多个子系统的接口。

  • 客户端通过外观类与子系统交互,隐藏了子系统的复杂性。

Java实现

// 子系统类1
class CPU {
    public void process() {
        System.out.println("CPU processing");
// 子系统类2
class Memory {
    public void load() {
        System.out.println("Memory loading");
    }
}

// 子系统类3
class HardDrive {
    public void read() {
        System.out.println("HardDrive reading data");
    }
}

// 外观类
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 start() {
        System.out.println("Starting the computer...");
        cpu.process();
        memory.load();
        hardDrive.read();
        System.out.println("Computer started successfully!");
    }
}

public class FacadeDemo {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();  // 输出: Starting the computer... CPU processing Memory loading HardDrive reading data Computer started successfully!
    }
}
  • ComputerFacade 类作为外观类,隐藏了子系统 CPUMemoryHardDrive 的复杂性。客户端只需要与外观类交互,简化了系统的使用。

6. 享元模式 (Flyweight Pattern)

享元模式通过共享对象来有效地支持大量的细粒度对象,尤其适用于创建大量对象的场景,能够节省内存并提高性能。

实现方式

  • 定义一个享元工厂,用来管理对象的共享。

  • 将共享的部分提取到外部,通过享元对象的共享来减少内存使用。

Java实现

// 享元接口
interface Flyweight {
    void operation(int extrinsicState);
}

// 具体享元类
class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;

    public ConcreteFlyweight(String state) {
        this.intrinsicState = state;
    }

    public void operation(int extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
    }
}

// 享元工厂类
class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String state) {
        Flyweight flyweight = flyweights.get(state);

        if (flyweight == null) {
            flyweight = new ConcreteFlyweight(state);
            flyweights.put(state, flyweight);
        }

        return flyweight;
    }
}

public class FlyweightDemo {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        Flyweight flyweight1 = factory.getFlyweight("State1");
        flyweight1.operation(1);

        Flyweight flyweight2 = factory.getFlyweight("State1");
        flyweight2.operation(2);

        Flyweight flyweight3 = factory.getFlyweight("State2");
        flyweight3.operation(3);

        System.out.println(flyweight1 == flyweight2);  // 输出: true, 因为它们共享相同的状态
    }
}
  • ConcreteFlyweight 类实现了享元接口,存储了不可变的内部状态(intrinsic state)。

  • FlyweightFactory 管理着享元对象的创建与共享。


7. 代理模式 (Proxy Pattern)

代理模式为其他对象提供代理,以控制对该对象的访问。它可以用于延迟初始化、访问控制、缓存、日志记录等功能。

实现方式

  • 定义一个代理接口,它与真实对象接口相同。

  • 代理类在客户端请求时,控制对真实对象的访问,可能还会做一些额外的操作。

Java实现

// 真实主题类
class RealSubject {
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 代理类
class Proxy {
    private RealSubject realSubject;

    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();  // 代理处理请求
    }
}

public class ProxyDemo {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();  // 输出: RealSubject: Handling request.
    }
}
  • Proxy 类控制对 RealSubject 的访问。客户端通过代理对象来访问实际的操作,这样可以在代理中添加额外的功能,如延迟加载、访问控制等。


Comment