设计模式:结构型模式

1. 适配器模式 (Adapter Pattern)

适配器模式是一种结构型设计模式,旨在将一个类的接口转换成客户端所期待的另一个接口,从而使原本由于接口不兼容而无法一起工作的类能够协同工作。适配器模式通常用于需要复用现有类但其接口与要求不匹配的情况。

1.1 适配器模式的概念和作用

适配器模式允许接口不兼容的类可以相互合作,其作用在于解决不同接口之间的兼容性问题,使得原本不兼容的类可以协同工作。它允许我们创建一个包装器 (Adapter),该包装器实现了客户端所期待的目标接口,并将调用转发给被包装对象。

1.2 对象适配器和类适配器的区别

在适配器模式中,有两种常见的实现方式:对象适配器和类适配器。

  • 对象适配器:适配器持有被适配对象的实例,并在适配器中调用被适配对象的方法来实现目标接口。
  • 类适配器:适配器继承了被适配对象,同时实现了目标接口,从而使得适配器可以作为被适配对象的子类被使用。

1.3 适配器模式的结构和实现

适配器模式的结构包括:目标接口 (Target)、适配器 (Adapter)、被适配对象 (Adaptee)。

java 复制代码
// 目标接口
interface Target {
    void request();
}

// 被适配对象
class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee's specificRequest called");
    }
}

// 类适配器
class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() {
        specificRequest();
    }
}

// 对象适配器
class ObjectAdapter implements Target {
    private Adaptee adaptee;

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

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

1.4 适配器模式的优缺点

  • 优点:
    • 使得客户端可以调用不兼容接口的对象。
    • 可以封装已有的类,提高代码复用性。
  • 缺点:
    • 类适配器需要多重继承,不够灵活,只能适配适配者的接口。
    • 对象适配器需要额外的对象引用,增加了系统的复杂度。

1.5 适配器模式在实际项目中的应用场景

适配器模式常用于以下场景:

  • 已有类的接口与现有系统不兼容。
  • 在不破坏封装性的前提下,需要将一个类适配到另一个接口。
  • 需要复用一个类,但其接口与其他类不兼容。

2. 桥接模式 (Bridge Pattern)

桥接模式是一种结构型设计模式,旨在将抽象部分与实现部分分离,使它们可以独立地变化。桥接模式通过将抽象部分和实现部分分开,使它们可以独立地进行扩展和变化,从而降低它们之间的耦合度。

2.1 桥接模式的概念和作用

桥接模式的核心思想是将抽象与实现分离,使它们可以独立变化,相互之间解耦。这样一来,抽象部分和实现部分可以分别进行扩展,而不会相互影响,从而提高了系统的灵活性和可扩展性。

2.2 桥接模式的结构和实现

在桥接模式中,有两个重要的角色:抽象类 (Abstraction) 和实现类 (Implementor)。抽象类定义了抽象部分的接口,而实现类则负责实现抽象部分的具体功能。

java 复制代码
// 抽象类
abstract class Abstraction {
    protected Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}

// 实现类接口
interface Implementor {
    void operationImpl();
}

// 具体实现类A
class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operationImpl called");
    }
}

// 具体实现类B
class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorB operationImpl called");
    }
}

// 桥接模式的具体实现
class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operation() {
        implementor.operationImpl();
    }
}

2.3 桥接模式的优缺点

  • 优点:
    • 分离抽象部分和实现部分,使得系统更加灵活。
    • 可以独立地扩展抽象部分和实现部分。
    • 符合开闭原则,对扩展开放,对修改关闭。
  • 缺点:
    • 增加了系统的复杂度,需要同时设计抽象类和实现类的层次结构。

2.4 桥接模式在实际项目中的应用场景

桥接模式常用于以下场景:

  • 当一个类需要多个变化维度时,使用桥接模式可以将各个维度分离,使得每个维度可以独立变化。
  • 当需要对抽象部分和实现部分进行独立扩展时,可以使用桥接模式。

3. 组合模式 (Composite Pattern)

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

3.1 组合模式的概念和作用

组合模式的核心思想是将对象组织成树形结构,使得客户端可以统一处理单个对象和组合对象。这样一来,用户可以像处理单个对象一样处理组合对象,无需关心其内部结构。

3.2 组合模式的结构和实现

在组合模式中,有两个重要的角色:组件 (Component) 和叶子节点 (Leaf)、容器节点 (Composite)。

java 复制代码
// 抽象组件类
interface Component {
    void operation();
}

// 叶子节点类
class Leaf implements Component {
    @Override
    public void operation() {
        System.out.println("Leaf operation called");
    }
}

// 容器节点类
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);
    }

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

3.3 组合模式的优缺点

  • 优点:
    • 统一对待单个对象和组合对象,简化了客户端代码。
    • 可以动态地增加或删除组合对象,更灵活。
  • 缺点:
    • 增加了系统的复杂性,需要设计额外的层次结构。
    • 不太容易限制组合对象的类型。

3.4 组合模式在实际项目中的应用场景

组合模式常用于以下场景:

  • 表示树形结构的数据,如文件系统、组织架构等。
  • 图形界面中的布局管理器,将控件组织成嵌套的层次结构。
  • 菜单管理系统,将菜单项和子菜单组织成树形结构。

4. 装饰器模式 (Decorator Pattern)

装饰器模式是一种结构型设计模式,允许向现有对象动态地添加新功能,同时又不改变其结构。这种模式对于扩展类的功能非常有用,同时又保持了类的简单性和可读性。

4.1 装饰器模式的概念和作用

装饰器模式允许在不改变现有对象结构的情况下,动态地添加新功能。它通过创建一个装饰器类,该类包含一个指向原始对象的引用,并实现与原始对象相同的接口。通过将装饰器类的对象包裹在原始对象周围,可以逐步添加新的行为。

4.2 装饰器模式的结构和实现

在装饰器模式中,有以下几个关键角色:组件 (Component)、具体组件 (ConcreteComponent)、装饰器 (Decorator)、具体装饰器 (ConcreteDecorator)。

java 复制代码
// 抽象组件类
interface Component {
    void operation();
}

// 具体组件类
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation called");
    }
}

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

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

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

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

    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("Added behavior by ConcreteDecorator");
    }
}

4.3 装饰器模式的优缺点

  • 优点:
    • 可以动态地添加或删除对象的功能,灵活性高。
    • 遵循开闭原则,不需要修改现有代码就可以添加新功能。
  • 缺点:
    • 可能会产生大量的具体装饰器类,增加了系统的复杂性。
    • 客户端需要了解装饰器和被装饰对象的区别,容易混淆。

4.4 装饰器模式在实际项目中的应用场景

装饰器模式常用于以下场景:

  • Java I/O 类库中的 InputStream 和 OutputStream 就是使用了装饰器模式,通过组合不同的装饰器类来实现不同的功能。
  • GUI 应用程序中的窗口和控件,通过装饰器模式可以动态地添加边框、滚动条等装饰。
  • Web 开发中的过滤器、拦截器等功能,也可以使用装饰器模式来实现。

5. 外观模式 (Facade Pattern)

外观模式是一种结构型设计模式,提供了一个统一的接口,用于访问子系统中的一群接口。它隐藏了子系统的复杂性,使得客户端更加容易使用。

5.1 外观模式的概念和作用

外观模式的核心思想是提供一个简单的接口,隐藏了系统的复杂性,并将系统的子模块组织成一个更大的系统。这样,客户端只需要与外观对象进行交互,而不需要了解内部子系统的细节。

5.2 外观模式的结构和实现

在外观模式中,有以下几个关键角色:外观 (Facade)、子系统 (Subsystem)。

java 复制代码
// 子系统类
class Subsystem1 {
    public void operation1() {
        System.out.println("Subsystem1 operation");
    }
}

class Subsystem2 {
    public void operation2() {
        System.out.println("Subsystem2 operation");
    }
}

class Subsystem3 {
    public void operation3() {
        System.out.println("Subsystem3 operation");
    }
}

// 外观类
class Facade {
    private Subsystem1 subsystem1;
    private Subsystem2 subsystem2;
    private Subsystem3 subsystem3;

    public Facade() {
        subsystem1 = new Subsystem1();
        subsystem2 = new Subsystem2();
        subsystem3 = new Subsystem3();
    }

    public void operation() {
        subsystem1.operation1();
        subsystem2.operation2();
        subsystem3.operation3();
    }
}

5.3 外观模式的优缺点

  • 优点:
    • 简化了客户端与子系统之间的交互,降低了耦合度。
    • 客户端不需要了解子系统的内部结构,减少了对子系统的直接依赖。
    • 提高了代码的灵活性和可维护性。
  • 缺点:
    • 如果外观对象过于臃肿,可能会变得难以维护和理解。

5.4 外观模式在实际项目中的应用场景

外观模式常用于以下场景:

  • 复杂系统的接口简化:当一个系统包含多个子系统,并且子系统之间存在复杂的依赖关系时,可以使用外观模式来简化客户端与系统之间的交互。
  • 封装不稳定的接口:当一个系统中的某些接口频繁变化,但是客户端不希望因此受到影响时,可以使用外观模式来封装这些不稳定的接口。

6. 享元模式 (Flyweight Pattern)

享元模式是一种结构型设计模式,旨在通过共享对象来最小化内存使用和提高性能。它适用于大量相似对象的场景,通过共享内部状态来减少内存占用。

6.1 享元模式的概念和作用

享元模式的核心思想是共享对象以减少内存占用和提高性能。在享元模式中,对象分为内部状态和外部状态。内部状态是可以共享的,而外部状态是不可共享的。通过共享内部状态,可以减少系统中重复对象的数量,从而节省内存。

6.2 享元模式的结构和实现

在享元模式中,有以下几个关键角色:享元工厂 (FlyweightFactory)、具体享元 (ConcreteFlyweight)、非共享具体享元 (UnsharedConcreteFlyweight)、享元接口 (Flyweight)。

java 复制代码
// 享元接口
interface Flyweight {
    void operation();
}

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

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

    @Override
    public void operation() {
        System.out.println("ConcreteFlyweight: Intrinsic State = " + intrinsicState);
    }
}

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

    public Flyweight getFlyweight(String key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new ConcreteFlyweight(key));
        }
        return flyweights.get(key);
    }
}

6.3 享元模式的优缺点

  • 优点:
    • 减少内存占用:通过共享内部状态,可以减少系统中重复对象的数量,节省内存空间。
    • 提高性能:由于减少了对象数量,可以提高系统的性能。
  • 缺点:
    • 增加了系统复杂性:引入了共享对象的管理机制,增加了系统的复杂度。
    • 限制外部状态:外部状态不可共享,可能导致一些不便之处。

6.4 享元模式在实际项目中的应用场景

享元模式常用于以下场景:

  • 文字编辑器中的字符共享:在文字编辑器中,如果存在大量相同字符,可以使用享元模式共享这些字符对象,减少内存占用。
  • 棋盘游戏中的棋子管理:在棋盘游戏中,如果存在大量相同的棋子对象,可以使用享元模式共享这些棋子对象,提高性能。

7. 代理模式 (Proxy Pattern)

代理模式是一种结构型设计模式,用于控制对其他对象的访问。

7.1 代理模式的概念和作用

代理模式充当了客户端和目标对象之间的中介,控制对目标对象的访问。它通常用于以下情况:

  • 远程代理:控制对远程对象的访问,例如在网络上访问对象。
  • 虚拟代理:延迟加载目标对象,直到真正需要时才创建。
  • 保护代理:控制对目标对象的访问权限,验证客户端的请求是否合法。
  • 缓存代理:为昂贵的操作结果提供缓存,避免重复计算。

7.2 静态代理和动态代理的区别

  • 静态代理:在编译时已经确定代理类和目标类的关系,代理类需要显式地实现与目标类相同的接口或继承相同的父类。缺点是每个代理类只能代理一个目标类,不够灵活。
  • 动态代理 :在运行时动态生成代理类,无需提前定义代理类。Java中的动态代理是通过 java.lang.reflect.Proxy 类实现的,可以代理任意接口。相比静态代理更灵活,但性能上略有损失。

7.3 代理模式的结构和实现

代理模式通常包含以下角色:

  • 抽象主题 (Subject):定义了代理类和真实主题类的公共接口,客户端通过此接口访问真实主题。
  • 真实主题 (Real Subject):实现了抽象主题接口,是代理模式中的实际业务逻辑。
  • 代理类 (Proxy):保存了一个真实主题对象的引用,可以控制对真实主题的访问,在必要时创建或删除真实主题对象。

示例代码:

java 复制代码
// 抽象主题
interface Subject {
    void request();
}

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

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

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    public void request() {
        System.out.println("Proxy: Pre-processing request.");
        realSubject.request();
        System.out.println("Proxy: Post-processing request.");
    }
}

7.4 代理模式的优缺点

优点

  • 可以实现对目标对象的控制,保护目标对象和客户端的透明性。
  • 可以实现远程代理、虚拟代理、保护代理等多种功能。

缺点

  • 由于增加了代理类,可能导致代码结构复杂化。
  • 静态代理需要提前定义代理类,不够灵活;动态代理性能稍逊于静态代理。

7.5 代理模式在实际项目中的应用场景

  • 对外服务接口的访问控制与权限验证。
  • 远程接口的访问与数据传输。
  • 延迟加载大对象或耗时操作。
相关推荐
路上阡陌3 分钟前
Java学习笔记(二十四)
java·笔记·学习
爱敲代码的边芙5 分钟前
Linux:信号的保存[2]
linux·运维·服务器
葛小白18 分钟前
第五天 Labview数据记录(5.1 INI配置文件读写)
服务器·labview
何中应13 分钟前
Spring Boot中选择性加载Bean的几种方式
java·spring boot·后端
苏苏大大15 分钟前
zookeeper
java·分布式·zookeeper·云原生
工程师焱记18 分钟前
Linux 常用命令——系统设置篇(保姆级说明)
linux·运维·服务器
涅槃寂雨35 分钟前
C语言小任务——寻找水仙花数
c语言·数据结构·算法
某风吾起40 分钟前
linux系统中的 scp的使用方法
linux·服务器·网络
『往事』&白驹过隙;42 分钟前
操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之缓冲区的管理
linux·c语言·数据结构·物联网·操作系统
wclass-zhengge42 分钟前
03垃圾回收篇(D3_垃圾收集器的选择及相关参数)
java·jvm