Java 设计模式(结构型)

发布于:2024-04-30 ⋅ 阅读:(26) ⋅ 点赞:(0)

代理模式

代理模式是一种结构型设计模式,允许在访问对象时提供一种代理以控制对该对象的访问。代理模式通常在客户端和实际对象之间引入了一个代理对象,客户端通过代理对象间接访问实际对象,从而可以在访问过程中添加额外的功能,例如权限验证、缓存、延迟加载等。

  • 结构

    1. 抽象主题(Subject):定义了代理对象和真实对象之间的共同接口,客户端通过该接口访问真实对象。
    2. 真实主题(Real Subject):实现了抽象主题接口,定义了真实对象的具体功能。
    3. 代理(Proxy):实现了抽象主题接口,并保存了一个引用指向真实主题对象,客户端通过代理对象间接访问真实对象。代理对象可以在客户端访问真实对象前后执行一些额外的操作。
  • 场景

    1. 远程代理:当客户端需要访问远程对象时,可以使用远程代理来隐藏网络通信的细节。
    2. 虚拟代理:当创建一个对象的开销很大时,可以使用虚拟代理来延迟对象的实例化。
    3. 安全代理:当需要对客户端访问真实对象的权限进行控制时,可以使用安全代理来进行权限验证。
    4. 缓存代理:当需要缓存真实对象的结果以提高性能时,可以使用缓存代理来实现结果的缓存。
  • 优点

    1. 实现了客户端和真实对象的解耦:代理模式将客户端和真实对象解耦,客户端无需直接访问真实对象,从而降低了客户端和真实对象之间的依赖关系。
    2. 提高了系统的灵活性:通过引入代理对象,可以在访问真实对象前后添加额外的功能,从而提高了系统的灵活性。
    3. 增强了安全性:代理对象可以在客户端访问真实对象前进行权限验证,从而增强了系统的安全性。
  • 缺点

    1. 增加了系统复杂度:引入代理对象会增加系统的复杂度,因为需要额外的类来实现代理功能。
    2. 可能降低性能:代理模式可能会增加请求的处理时间,因为代理对象需要在访问真实对象前后执行额外的操作,例如权限验证、缓存等。
  • 示例

// 主题接口
interface Subject {
    void request();
}

// 真实主题类
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实主题类处理请求");
    }
}

// 代理类
class Proxy implements Subject {
    private RealSubject realSubject;
    
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    
    @Override
    public void request() {
        // 在访问真实主题前执行一些额外的操作
        System.out.println("代理类处理请求之前的操作");
        
        // 调用真实主题对象的方法
        realSubject.request();
        
        // 在访问真实主题后执行一些额外的操作
        System.out.println("代理类处理请求之后的操作");
    }
}

public class ProxyPatternExample {
    public static void main(String[] args) {
        // 创建真实主题对象
        RealSubject realSubject = new RealSubject();
        
        // 创建代理对象,并将真实主题对象传递给代理对象
        Proxy proxy = new Proxy(realSubject);
        
        // 通过代理对象调用真实主题的方法
        proxy.request();
    }
}
  • 输出结果
代理类处理请求之前的操作
真实主题类处理请求
代理类处理请求之后的操作

门面模式

门面模式是一种结构型设计模式,旨在为复杂子系统提供一个简单的接口,以便与外部系统进行交互。门面模式通过将复杂系统的多个接口封装在一个单一的接口中,简化了客户端与系统之间的交互。

  • 结构

    1. 门面(Facade):提供了一个简单的接口,用于与外部系统进行交互。门面将复杂系统的多个接口封装在一个单一的接口中。
    2. 子系统(Subsystem):包含了系统中的多个组件和接口,负责实现系统的具体功能。
  • 场景

    1. 为外部系统提供统一接口:当需要为复杂系统提供一个简单的接口,以便与外部系统进行交互时,可以使用门面模式。
    2. 简化复杂系统的使用:当复杂系统有多个接口和组件,并且需要简化客户端的使用时,可以使用门面模式。
    3. 隐藏系统实现细节:当需要隐藏系统的实现细节,并提供一个简单的接口给客户端时,可以使用门面模式。
  • 优点

    1. 简化接口:门面模式提供了一个简单的接口,隐藏了复杂系统的实现细节,使得客户端更容易使用系统。
    2. 降低耦合度:门面模式将客户端与系统之间的依赖关系解耦,使得系统的变化不会影响到客户端。
    3. 提高可维护性:通过将复杂系统封装在一个门面接口中,可以更容易地理解和维护系统。
  • 缺点

    1. 可能导致门面对象臃肿:如果系统过于复杂,门面对象可能会变得臃肿,导致违反单一责任原则。
    2. 不符合开闭原则:当系统的功能发生变化时,可能需要修改门面对象的实现,这可能会违反开闭原则。
  • 示例

// 子系统 - 音频播放器
class AudioPlayer {
    public void play() {
        System.out.println("播放音频");
    }
    
    public void pause() {
        System.out.println("暂停音频");
    }
    
    public void stop() {
        System.out.println("停止音频");
    }
}

// 子系统 - 视频播放器
class VideoPlayer {
    public void play() {
        System.out.println("播放视频");
    }
    
    public void pause() {
        System.out.println("暂停视频");
    }
    
    public void stop() {
        System.out.println("停止视频");
    }
}

// 门面类 - 多媒体播放器门面
class MediaPlayerFacade {
    private AudioPlayer audioPlayer;
    private VideoPlayer videoPlayer;
    
    public MediaPlayerFacade() {
        audioPlayer = new AudioPlayer();
        videoPlayer = new VideoPlayer();
    }
    
    // 播放音频和视频
    public void play() {
        audioPlayer.play();
        videoPlayer.play();
    }
    
    // 暂停音频和视频
    public void pause() {
        audioPlayer.pause();
        videoPlayer.pause();
    }
    
    // 停止音频和视频
    public void stop() {
        audioPlayer.stop();
        videoPlayer.stop();
    }
}

public class FacadePatternExample {
    public static void main(String[] args) {
        // 使用门面模式简化客户端与复杂系统之间的交互
        MediaPlayerFacade mediaPlayer = new MediaPlayerFacade();
        mediaPlayer.play();
        mediaPlayer.pause();
        mediaPlayer.stop();
    }
}

外观模式

外观模式是一种结构型设计模式,旨在提供一个简单的接口,隐藏复杂的系统内部结构,使得客户端可以更容易地使用系统。外观模式将系统的多个子系统封装在一个统一的接口中,为客户端提供了一个更高层次的接口,从而简化了客户端与系统之间的交互。

  • 结构

    1. 外观(Facade):提供了一个统一的接口,用于访问子系统中的一组接口。
    2. 子系统(Subsystem):包含一组相关的类或接口,实现了系统的各种功能。
  • 场景

    1. 简化复杂系统:当系统中存在多个复杂的子系统,并且需要为客户端提供一个简单的接口来访问这些子系统时,可以使用外观模式。
    2. 隐藏实现细节:当希望隐藏系统的实现细节,使得客户端不需要了解系统的内部结构时,可以使用外观模式。
    3. 提供统一接口:当希望为客户端提供一个统一的接口,封装系统的多个子系统,并隐藏其复杂性时,可以使用外观模式。
  • 优点

    1. 简化接口:外观模式通过提供一个简单的接口,隐藏了系统的复杂性,使得客户端更容易地使用系统。
    2. 解耦:外观模式将客户端与子系统之间的依赖关系解耦,客户端只需要与外观对象交互,而不需要直接与子系统交互。
    3. 提高了灵活性:由于外观对象封装了子系统的实现细节,因此可以灵活地调整子系统的实现,而不影响客户端代码。
  • 缺点

    1. 违反单一职责原则:外观对象负责封装多个子系统的功能,可能会导致外观对象变得庞大和复杂,违反了单一职责原则。
    2. 不符合开闭原则:如果需要新增或修改系统的功能,可能需要修改外观对象,这违反了开闭原则。
  • 示例

// 子系统A
class SubsystemA {
    public void operationA() {
        System.out.println("子系统A的操作A");
    }
}

// 子系统B
class SubsystemB {
    public void operationB() {
        System.out.println("子系统B的操作B");
    }
}

// 子系统C
class SubsystemC {
    public void operationC() {
        System.out.println("子系统C的操作C");
    }
}

// 外观类
class Facade {
    private SubsystemA subsystemA;
    private SubsystemB subsystemB;
    private SubsystemC subsystemC;

    public Facade() {
        this.subsystemA = new SubsystemA();
        this.subsystemB = new SubsystemB();
        this.subsystemC = new SubsystemC();
    }

    // 提供一个统一的接口,供客户端调用
    public void operation() {
        System.out.println("外观类调用子系统A、B、C的操作:");
        subsystemA.operationA();
        subsystemB.operationB();
        subsystemC.operationC();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.operation();
    }
}
  • 输出结果
外观类调用子系统A、B、C的操作:
子系统A的操作A
子系统B的操作B
子系统C的操作C

桥接模式

桥接模式(Bridge Pattern)是一种结构型设计模式,用于将抽象部分与其实现部分分离,使它们可以独立地变化。桥接模式通过将抽象和实现分离,使得它们可以独立地变化,从而提高了系统的灵活性和可扩展性。

  • 结构

    1. 抽象部分(Abstraction):定义了抽象类或接口,并包含一个实现部分对象的引用。
    2. 扩展抽象部分(Refined Abstraction):对抽象部分进行扩展,通常包含一些额外的方法或属性。
    3. 实现部分接口(Implementor):定义了实现部分的接口,通常包含了实现抽象部分所定义的方法。
    4. 具体实现部分(Concrete Implementor):实现了实现部分接口,具体实现了实现部分的方法。
  • 场景

    1. 数据库驱动设计:在不同的数据库之间切换时,可以使用桥接模式将抽象部分和实现部分分离,以便灵活地切换。
    2. 图形界面设计:在图形界面库中,可以使用桥接模式将不同操作系统平台(如Windows、Linux、Mac)的图形界面控件和操作系统分离,提高了跨平台的灵活性。
    3. 手机操作系统设计:在手机操作系统中,可以使用桥接模式将手机应用和手机硬件分离,以便在不同手机硬件平台上灵活地切换。
    4. 消息发送系统:在消息发送系统中,可以使用桥接模式将不同的消息发送方式(如短信、邮件、微信)和消息内容分离,以便灵活地选择发送方式和内容。
  • 优点

    1. 解耦合:将抽象部分与其实现部分分离,使得它们可以独立地变化,降低了系统的耦合度。
    2. 灵活性:抽象部分和实现部分可以独立地扩展和变化,系统更加灵活。
    3. 可扩展性:可以方便地添加新的抽象部分和实现部分,符合开闭原则。
    4. 复用性:抽象部分和实现部分可以复用,提高了代码的复用性。
  • 缺点

    1. 增加系统复杂度:引入了抽象部分和实现部分之间的桥接,增加了系统的复杂度。
    2. 需正确识别抽象与实现:需要正确识别抽象部分和实现部分,否则会增加系统的混乱程度。
  • 示例

// 实现部分接口:消息发送方式
interface MessageSender {
    void sendMessage(String message);
}

// 具体实现部分:短信发送
class SmsSender implements MessageSender {
    @Override
    public void sendMessage(String message) {
        System.out.println("通过短信发送消息:" + message);
    }
}

// 具体实现部分:邮件发送
class EmailSender implements MessageSender {
    @Override
    public void sendMessage(String message) {
        System.out.println("通过邮件发送消息:" + message);
    }
}

// 抽象部分:消息
abstract class Message {
    // 持有实现部分的引用
    protected MessageSender sender;

    // 构造方法,传入实现部分的对象
    public Message(MessageSender sender) {
        this.sender = sender;
    }

    // 发送消息的抽象方法
    public abstract void send();
}

// 扩展抽象部分:普通消息
class NormalMessage extends Message {
    // 构造方法,调用父类构造方法
    public NormalMessage(MessageSender sender) {
        super(sender);
    }

    // 实现发送消息的方法
    @Override
    public void send() {
        // 调用实现部分的方法
        sender.sendMessage("普通消息");
    }
}

// 扩展抽象部分:加急消息
class UrgentMessage extends Message {
    // 构造方法,调用父类构造方法
    public UrgentMessage(MessageSender sender) {
        super(sender);
    }

    // 实现发送消息的方法
    @Override
    public void send() {
        // 调用实现部分的方法
        sender.sendMessage("加急消息");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 创建短信发送对象
        MessageSender smsSender = new SmsSender();
        // 创建邮件发送对象
        MessageSender emailSender = new EmailSender();

        // 创建普通消息对象,传入短信发送对象
        Message normalMessage1 = new NormalMessage(smsSender);
        // 发送普通消息
        normalMessage1.send();

        // 创建加急消息对象,传入邮件发送对象
        Message urgentMessage1 = new UrgentMessage(emailSender);
        // 发送加急消息
        urgentMessage1.send();

        // 创建普通消息对象,传入邮件发送对象
        Message normalMessage2 = new NormalMessage(emailSender);
        // 发送普通消息
        normalMessage2.send();

        // 创建加急消息对象,传入短信发送对象
        Message urgentMessage2 = new UrgentMessage(smsSender);
        // 发送加急消息
        urgentMessage2.send();
    }
}
  • 输出结果
通过短信发送消息:普通消息
通过邮件发送消息:加急消息
通过邮件发送消息:普通消息
通过短信发送消息:加急消息

适配器模式

适配器模式是一种结构设计模式,用于使接口不兼容的类可以一起工作。它允许将现有类的接口转换为所需的接口,从而使得不兼容的类可以进行协同工作。

  • 结构

    1. 目标接口(Target):定义客户端使用的接口。
    2. 适配器(Adapter):实现目标接口,并持有被适配的对象,将被适配对象的接口转换为目标接口。
    3. 被适配者(Adaptee):定义了需要被适配的接口。
  • 场景

    1. 第三方库的接口不兼容:当需要使用某个第三方库,但其接口与系统中已有的接口不兼容时,可以使用适配器模式将其接口转换为系统需要的接口。
    2. 新旧系统的整合:当需要将新系统与旧系统进行整合时,由于接口不兼容,可以使用适配器模式进行转换。
    3. 在不破坏现有接口的情况下添加功能:当需要在不破坏现有接口的情况下添加功能时,可以使用适配器模式。
  • 优点

    1. 兼容性:可以让原本不兼容的接口能够一起工作,使得客户端无需修改现有代码。
    2. 复用性:可以复用现有的类,而无需修改其代码。
    3. 解耦性:客户端与被适配者之间解耦,适配器作为中间层,降低了客户端与被适配者之间的依赖关系。
  • 缺点

    1. 过多的适配器:如果系统中适配器的数量过多,可能会增加系统的复杂性。
    2. 增加了代码的阅读难度:适配器模式可能会增加代码的阅读难度,因为需要理解适配器与被适配者之间的关系。
  • 示例

// 目标接口
interface Target {
    void request();
}

// 具体目标类
class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("具体目标类的方法被调用");
    }
}

// 适配器类
class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

// 被适配者类
class Adaptee {
    public void specificRequest() {
        System.out.println("被适配者类的方法被调用");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 使用具体目标类
        Target target = new ConcreteTarget();
        target.request(); // 输出:具体目标类的方法被调用

        // 使用适配器类
        Adaptee adaptee = new Adaptee();
        Target adapter = new Adapter(adaptee);
        adapter.request(); // 输出:被适配者类的方法被调用
    }
}
  • 输出结果
具体目标类的方法被调用
被适配者类的方法被调用

享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享尽可能多的对象来最小化内存使用或计算开销。该模式适用于大量相似对象的场景,以减少内存占用和提高性能。

  • 结构

    1. Flyweight(享元接口):
      • 定义了享元对象的接口,通过这个接口可以接受并作用于外部状态。
      • 通常包括一个或多个方法,用于接受外部状态并执行相应的操作。
    2. ConcreteFlyweight(具体享元类):
      • 实现了享元接口,并且包含了内部状态。
      • 具体享元对象通常是可共享的,并且在系统中可能会被多次使用。
    3. UnsharedConcreteFlyweight(非共享的具体享元类,可选):
      • 有时候并不是所有的享元对象都可以被共享,因此可以定义非共享的具体享元类。
      • 这些对象的状态不会被共享,每个对象都是独立的。
    4. FlyweightFactory(享元工厂):
      • 负责创建和管理享元对象。
      • 在请求享元对象之前,通常会首先检查工厂中是否已经存在对应的享元对象,如果存在则直接返回,否则创建一个新的享元对象并将其放入工厂中。
    5. Client(客户端):
    • 使用享元对象的客户端。
    • 客户端通常负责创建或获取享元工厂,并通过工厂获取具体的享元对象。
  • 场景

    1. 文本编辑器:在文本编辑器中,字符和字体可以被视为享元对象。大量相同字符或字体可以共享相同的状态,从而减少内存占用。
    2. 游戏开发:在游戏开发中,例如棋盘游戏中的棋子,可以使用享元模式来共享相同的状态,以减少对象数量并提高性能。
    3. 连接池:数据库连接池、线程池等资源池都可以使用享元模式来管理和复用资源对象,以减少资源的创建和销毁开销。
    4. 图形系统:在图形系统中,像素点、颜色等可以被视为享元对象,大量相同的像素点或颜色可以共享相同的状态,以减少内存占用。
  • 优点

    1. 减少内存占用:通过共享相同的状态来减少内存使用,特别是当存在大量相似对象时。
    2. 提高性能:减少了对象的数量,从而减少了内存访问和计算开销,提高了系统的性能。
    3. 灵活性:享元模式允许在运行时添加或移除共享对象,从而使系统更加灵活。
  • 缺点

    1. 复杂性增加:实现享元模式可能需要引入额外的复杂性,特别是在管理共享状态和外部状态之间的关系时。
    2. 可能影响线程安全性:如果共享的对象在多个线程之间共享并且会修改状态,那么可能需要考虑线程安全性问题。
  • 示例

import java.util.HashMap;
import java.util.Map;

// 享元接口
interface CharFlyweight {
    void display(String font);
}

// 具体享元类:字符对象
class Char implements CharFlyweight {
    private char character;

    public Char(char character) {
        this.character = character;
    }

    @Override
    public void display(String font) {
        System.out.println("Character: " + character + ", Font: " + font);
    }
}

// 享元工厂类
class CharFactory {
    private Map<Character, CharFlyweight> charMap = new HashMap<>();

    public CharFlyweight getChar(char character) {
        if (!charMap.containsKey(character)) {
            charMap.put(character, new Char(character));
        }
        return charMap.get(character);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        CharFactory charFactory = new CharFactory();

        CharFlyweight charA = charFactory.getChar('A');
        charA.display("Arial");

        CharFlyweight charB = charFactory.getChar('B');
        charB.display("Times New Roman");

        // 再次获取相同的字符对象
        CharFlyweight charA2 = charFactory.getChar('A');
        charA2.display("Calibri");
    }
}
  • 输出结果
Character: A, Font: Arial
Character: B, Font: Times New Roman
Character: A, Font: Calibri

装饰器模式

装饰器模式是一种结构设计模式,它允许你动态地将责任附加到对象上。装饰器模式提供了一种灵活的方式来扩展对象的功能,而无需通过子类化来实现。

  • 结构

    1. 组件(Component):定义了被装饰对象的接口,可以是抽象类或接口。
    2. 具体组件(ConcreteComponent):实现了组件接口,是被装饰的对象。
    3. 装饰器(Decorator):继承了组件接口,并持有一个指向组件对象的引用。通常是抽象类,它的子类可以扩展组件的功能。
    4. 具体装饰器(ConcreteDecorator):实现了装饰器接口,具体地添加额外的功能。
  • 场景

    1. 动态地添加功能:当需要动态地添加或移除对象的功能时,装饰器模式是一个很好的选择。例如,Java的IO流就使用了装饰器模式。
    2. 继承关系不合适:当类的继承关系不合适或不可行时,可以使用装饰器模式。例如,如果需要扩展一个类的功能,但又不希望创建其子类的情况下。
    3. 避免类爆炸:当使用继承会导致类的数量急剧增加时,装饰器模式可以避免类爆炸问题。
  • 优点

    1. 灵活性:可以动态地向对象添加新的功能,而无需修改其原始代码。
    2. 遵循开闭原则:允许新增功能而不影响现有代码,符合开闭原则。
    3. 避免类爆炸:相比使用继承来扩展功能,装饰器模式避免了类的数量急剧增加。
  • 缺点

    1. 增加复杂性:引入了许多小对象和装饰器之间的相互关系,可能会增加代码复杂性。
    2. 滥用可能性:过度使用装饰器模式可能导致代码变得难以理解和维护。
  • 示例

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

// 具体组件类(Concrete Component Class)
class ConcreteComponent implements Component {
    public void operation() {
        System.out.println("Performing operation in the concrete component.");
    }
}

// 抽象装饰器类(Decorator Abstract Class)
abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

// 具体装饰器类(Concrete Decorator Class)
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        additionalOperationA();
    }

    private void additionalOperationA() {
        System.out.println("Performing additional operation A.");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        additionalOperationB();
    }

    private void additionalOperationB() {
        System.out.println("Performing additional operation B.");
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        // 创建具体组件对象
        Component component = new ConcreteComponent();

        // 对具体组件对象进行装饰
        Component decoratedComponent = new ConcreteDecoratorA(new ConcreteDecoratorB(component));

        // 执行操作
        decoratedComponent.operation();
    }
}
  • 输出结果
Performing operation in the concrete component.
Performing additional operation B.
Performing additional operation A.

组合模式

组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。通过组合模式,客户端可以统一对待单个对象和组合对象,从而简化了客户端的代码。

  • 结构

    1. 组件(Component):定义了组合中所有对象的通用接口,可以是抽象类或接口,它声明了一些用于管理子节点的方法,如增加子节点、删除子节点、获取子节点等。
    2. 叶子节点(Leaf):表示组合中的叶子节点对象,它没有子节点。
    3. 复合节点(Composite):表示组合中的复合节点对象,它可以包含其他子节点,通常会实现组件接口中的方法来管理子节点。
  • 场景

    1. 表示“部分-整体”层次结构:当需要表示一个对象的部分-整体层次结构时,可以使用组合模式。
    2. 处理树形结构数据:当需要处理树形结构的数据时,可以使用组合模式来统一处理叶子节点和复合节点。
    3. 构建菜单、文件系统等:组合模式常用于构建菜单、文件系统等具有树形结构的应用程序。
  • 优点

    1. 简化客户端代码:客户端可以统一对待单个对象和组合对象,从而简化了客户端的代码。
    2. 灵活性:组合模式可以灵活地构建树形结构,允许动态地增加或删除节点。
    3. 可扩展性:组合模式使得客户端可以方便地增加新的组件类型,而无需修改现有代码。
  • 缺点

    1. 限制类型:组合模式限制了组合中所有对象的类型必须相同,这可能会限制组合模式的使用场景。
    2. 增加了复杂性:组合模式引入了多个新的类,可能会增加系统的复杂性。
  • 示例

import java.util.ArrayList;
import java.util.List;

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

// 叶子节点
class Leaf implements Component {
    private String name;
    
    public Leaf(String name) {
        this.name = name;
    }
    
    @Override
    public void operation() {
        System.out.println("Leaf " + name + " operation");
    }
}

// 复合节点
class Composite implements Component {
    private String name;
    private List<Component> children = new ArrayList<>();
    
    public Composite(String name) {
        this.name = name;
    }
    
    public void add(Component component) {
        children.add(component);
    }
    
    public void remove(Component component) {
        children.remove(component);
    }
    
    @Override
    public void operation() {
        System.out.println("Composite " + name + " operation");
        for (Component component : children) {
            component.operation();
        }
    }
}

public class CompositePatternExample {
    public static void main(String[] args) {
        Component leaf1 = new Leaf("Leaf1");
        Component leaf2 = new Leaf("Leaf2");
        Component leaf3 = new Leaf("Leaf3");
        
        Composite composite1 = new Composite("Composite1");
        composite1.add(leaf1);
        composite1.add(leaf2);
        
        Composite composite2 = new Composite("Composite2");
        composite2.add(leaf3);
        
        Composite root = new Composite("Root");
        root.add(composite1);
        root.add(composite2);
        
        root.operation();
    }
}
  • 输出结果
Composite Root operation
Composite Composite1 operation
Leaf Leaf1 operation
Leaf Leaf2 operation
Composite Composite2 operation
Leaf Leaf3 operation

网站公告

今日签到

点亮在社区的每一天
去签到