当前位置: 首页 > news >正文

设计模式-结构型模式(详解)

适配器模式

将一个类的接口转换成客户端期望的另一个接口,解决接口不兼容问题。

适配器模式由四部分组成:

  1. 客户端:即需要使用目标接口的类

  2. 目标接口

  3. 需要适配的类,也就是已经存在好的功能,但客户端通过目标接口没办法使用这个类

  4. 适配器,会实现目标接口,然后耦合需要适配的类,调用类的功能

分为类适配器和对象适配器

// 目标接口
public interface Target {void request();
}
// 适配者类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee's specificRequest");}
}
// 类适配器
public class Adapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Target target = new Adapter();target.request();  // Output: Adaptee's specificRequest}
}

对象适配器: 通过组合,让适配器类持有现有类的实例,并实现目标接口**。对象适配器使用组合关系来实现接口的适配**,较为常用。

// 目标接口
public interface Target {void request();
}
// 适配者类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee's specificRequest");}
}
// 对象适配器
public class Adapter implements Target {  //这里不再是和类适配器一样继承适配器,而是在类中装配适配器对象private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request();  // Output: Adaptee's specificRequest}
}

Java 日志中的 slf4j 其实就是使用了适配器模式来统一不同日志框架接口,使得我们不需要修改代码就可以替换不同的底层日志实现。

桥接模式

主要的作用是将抽象和实现解耦,使它们可以独立地变化。

我们熟知的JDBC 就使用了桥接模式,JDBC定义了抽象的规范,不同的数据库厂商遵循这些规范,但是它们各自又会有不同的实现。
在使用中,如果我们数据库是 mysql,则传入 com.mysql.jdbc.Driver 驱动实现类,如果要换成 oracle替换实现类为oracle.jdbc.driver.OracleDriver 即可,这就是典型的抽象与实现解耦。

代码实例

实现形状颜色解耦

  1. 实现化(Implementor):定义颜色接口

    public interface Color {void applyColor();
    }
    
  2. 具体实现化(Concrete Implementor):实现具体颜色

    public class RedColor implements Color {@Overridepublic void applyColor() { System.out.println("Applying red color");  //红色}
    }public class BlueColor implements Color {   //蓝色@Overridepublic void applyColor() {System.out.println("Applying blue color");}
    }
    
  3. 抽象化(Abstraction):定义形状接口

    public abstract class Shape {protected Color color;public Shape(Color color) {this.color = color;}public abstract void draw();
    }
    
  4. 细化抽象化(Refined Abstraction):实现具体形状

    public class Circle extends Shape {public Circle(Color color) {super(color);}@Overridepublic void draw() {System.out.print("Drawing a circle with ");color.applyColor();}
    }public class Rectangle extends Shape {public Rectangle(Color color) {super(color);}@Overridepublic void draw() {System.out.print("Drawing a rectangle with ");color.applyColor();}
    }
    
  5. 客户端代码

    public class Client {public static void main(String[] args) {// 创建红色圆形Shape redCircle = new Circle(new RedColor());redCircle.draw();  // 输出: Drawing a circle with Applying red color// 创建蓝色矩形Shape blueRectangle = new Rectangle(new BlueColor());blueRectangle.draw();  // 输出: Drawing a rectangle with Applying blue color}
    }
    

组合模式

将对象组合成树状结构以表示“整体——部分”的层次关系

以部门为示例,展示组织内的部门和人员信息

// 抽象组织
interface OrganizationComponent {  void showDetails();
}// 组织人员
class Employee implements OrganizationComponent {private String name;private String position;public Employee(String name, String position) {this.name = name;this.position = position;}@Overridepublic void showDetails() {System.out.println("Employee: " + name + ", Position: " + position);}
}// 组织部门
class Department implements OrganizationComponent {private String name;private List<OrganizationComponent> components = new ArrayList<>();public Department(String name) {this.name = name;}@Overridepublic void showDetails() {System.out.println("Department: " + name);for (OrganizationComponent component : components) {component.showDetails();}}public void add(OrganizationComponent component) { //往部门添加人员 或 部门components.add(component);}public void remove(OrganizationComponent component) {components.remove(component);}
}// 使用代码
public class Client {public static void main(String[] args) {// 创建人员OrganizationComponent employee1 = new Employee("John Doe", "Developer");OrganizationComponent employee2 = new Employee("Jane Smith", "Designer");OrganizationComponent employee3 = new Employee("Emily Davis", "Manager");// 创建部门Department engineeringDepartment = new Department("Engineering Department");Department designDepartment = new Department("Design Department");Department headDepartment = new Department("Head Department");// 添加人员到部门engineeringDepartment.add(employee1);designDepartment.add(employee2);headDepartment.add(employee3);// 添加子部门到上级部门headDepartment.add(engineeringDepartment);headDepartment.add(designDepartment);// 显示整个组织结构的详情headDepartment.showDetails();// 输出// Department: Head Department// Employee: Emily Davis, Position: Manager// Department: Engineering Department// Employee: John Doe, Position: Developer// Department: Design Department// Employee: Jane Smith, Position: Designer}
}

通过组合模式,提供统一的接口,简化对层次结构的处理,使得使用方代码更加简洁与灵活。

装饰器模式

主要作用是通过创建包装类来实现功能的增强,而不是修改原始类

通过创建一个装饰器类,该类实现了与原始对象相同的接口,并持有一个原始对象的引用。通过将原始对象传递给装饰器

代理模式中,代理类附加的是跟原始类无关的功能,而在装饰器模式中,装饰器类附加的是跟原始类相关的增强功能。

最典型的装饰器实现就是 Java 中的I/O类库,示例代码如下:

import java.io.*;
public class IOExample {public static void main(String[] args) throws IOException {File file = new File("test.txt");FileInputStream fis = new FileInputStream(file);  //读取文件流BufferedInputStream bis = new BufferedInputStream(fis);  //fis被BufferedlnputStream 装饰,提供了缓存的功能DataInputStream dis = new DataInputStream(bis); //被 DatalnputStream 装饰,提供了按数据类型读取的功能while (dis.available() > 0) {System.out.println(dis.readLine());}dis.close();}
}

文件流的代码比较复杂,这里就不展示了,我们简单看个多装饰器叠加的代码实现:

// 组件
interface Component {void operation();
}// 具体构件
class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 装饰器
abstract class Decorator implements Component {protected Component component;   public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}
// 具体装饰器 A
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA added behavior");}
}
// 具体装饰器 B
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedState();}private void addedState() {System.out.println("ConcreteDecoratorB added state");}
}// 客户端代码
public class Client {public static void main(String[] args) {Component component = new ConcreteComponent();Component decoratorA = new ConcreteDecoratorA(component);Component decoratorB = new ConcreteDecoratorB(decoratorA);decoratorB.operation();// Output:// ConcreteComponent operation// ConcreteDecoratorA added behavior// ConcreteDecoratorB added state}
}

外观模式

也叫门面模式,提供了一个简化的接口,用于访问复杂系统中的一组接口。将复杂系统的功能封装起来,让客户端可以更方便地使用系统功能而不需要了解其内部复杂结构。

举个例子就清晰了。例如 A系统有 a、b、c三个接口,B需要分别调用 a、b、c三个接口,这样比较麻烦,所以A将 a、b、c封装成一个接口给B调用,对B来说使用起来就方便了,这就是外观模式

class CPU {         //CPUpublic void start() {System.out.println("CPU 启动");}public void shutdown() {System.out.println("CPU 关闭");}
}
class Memory {            //内存public void start() {System.out.println("内存启动");}public void shutdown() {System.out.println("内存关闭");}
}class HardDrive {     //硬盘public void start() {System.out.println("硬盘启动");}public void shutdown() {System.out.println("硬盘关闭");}}
class ComputerFacade {         //外观类,封装了计算机系统的一组复杂接口,包括 CPU、内存和硬盘的启动和关闭private CPU cpu;private Memory memory;private HardDrive hardDrive;public ComputerFacade() {cpu = new CPU();memory = new Memory();hardDrive = new HardDrive();}public void start() {       //启动计算机System.out.println("计算机启动开始");cpu.start();memory.start();hardDrive.start();System.out.println("计算机启动完成");}public void shutdown() {    //关闭计算机System.out.println("计算机关闭开始");cpu.shutdown();memory.shutdown();hardDrive.shutdown();System.out.println("计算机关闭完成");}
}
ComputerFacade computerFacade = new ComputerFacade();
computerFacade.start();
// 输出:
// 计算机启动开始
// CPU 启动
// 内存启动
// 硬盘启动
// 计算机启动完成computerFacade.shutdown();
// 输出:
// 计算机关闭开始
// CPU 关闭
// 内存关闭
// 硬盘关闭
// 计算机关闭完成

享元模式

享元模式本质就是对象池,判断是否存在,若存在则取,不存在则添加。

Integer的缓存(-128~127)采用了享元模式。

具体原理可看 Java基础 29.什么是Java的Integer缓冲池?

示例:

假设我们要绘制棋盘上的棋子,棋子的种类有很多,但是每种棋子的形状和颜色是固定的。我们可以使用享元模式来共享相同种类的棋子对象,从而减少对象的创建数量。

// 棋子接口
interface ChessPiece {void setColor(String color);void display(int x, int y);
}
// 具体棋子类
class ConcreteChessPiece implements ChessPiece {private String color;public ConcreteChessPiece(String color) {this.color = color;}@Overridepublic void setColor(String color) {this.color = color;}@Overridepublic void display(int x, int y) {System.out.println("Chess Piece color: " + color + ", position: (" + x + "," + y + ")");}
}
// 享元工厂类
class ChessPieceFactory {private Map<String, ChessPiece> chessPieces;public ChessPieceFactory() {this.chessPieces = new HashMap<>();    //用集合存chessPieces}public ChessPiece getChessPiece(String color) {  //返回单例ChessPiece chessPiece = chessPieces.get(color);if (chessPiece == null) {chessPiece = new ConcreteChessPiece(color);chessPieces.put(color, chessPiece);}return chessPiece;}
}
// 客户端代码
public class Client {public static void main(String[] args) {ChessPieceFactory chessPieceFactory = new ChessPieceFactory();ChessPiece blackPiece1 = chessPieceFactory.getChessPiece("black");  ChessPiece blackPiece2 = chessPieceFactory.getChessPiece("black");ChessPiece whitePiece1 = chessPieceFactory.getChessPiece("white");ChessPiece whitePiece2 = chessPieceFactory.getChessPiece("white");blackPiece1.display(1, 2);  // 输出:Chess Piece color: black, position: (1,2)blackPiece2.display(3, 4);  // 输出:Chess Piece color: black, position: (3,4)whitePiece1.display(5, 6);  // 输出:Chess Piece color: white, position: (5,6)whitePiece2.display(7, 8);  // 输出:Chess Piece color: white, position: (7,8)}
}

代理模式

作用:在不改变原始类的情况下,为其提供一个代理,以控制对这个对象的访问

(代理模式和装饰器模式很像,其主要不同是,前者是控制原对象的访问,后者是为原对象增强已有类的功能)

核心是创建一个代理类,该类实现了与原始对象相同的接口,并持有一个原始对象的引用。在代理类的方法中,我们可以添加额外的功能,然后将请求转发给原始对象进行处理。

// 图片接口
interface Image {void display();
}
// 具体图片类
class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadImageFromDisk();}private void loadImageFromDisk() {System.out.println("Loading " + filename + " from disk.");}@Overridepublic void display() {System.out.println("Displaying " + filename);}
}
// 代理图片类
class ProxyImage implements Image {private RealImage realImage;   //引入具体图片类private String filename;		//实现了对原始图片对象的控制,而不需要修改原始图片类的代码public ProxyImage(String filename) {this.filename = filename;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(filename);}beforeDisplay();realImage.display();}private void beforeDisplay() {System.out.println("Before displaying " + filename + ", do some pre-processing.");}
}
// 客户端代码
public class Client {public static void main(String[] args) {Image image1 = new ProxyImage("image1.jpg");Image image2 = new ProxyImage("image2.jpg");image1.display();  // 输出:Before displaying image1.jpg, do some pre-processing.//        Loading image1.jpg from disk.//        Displaying image1.jpgimage2.display();  // 输出:Before displaying image2.jpg, do some pre-processing.//        Loading image2.jpg from disk.//        Displaying image2.jpg}
}
http://www.xdnf.cn/news/605881.html

相关文章:

  • el-dialog 组件 多层嵌套 被遮罩问题
  • Redis 缓存使用的BigKey问题
  • SAP在金属行业的数字化转型:无锡哲讯科技的智能解决方案
  • A10服务器使用vllm推理框架成功运行Qwen3大模型
  • 机器学习第二十四讲:scikit-learn → 机器学习界的瑞士军刀
  • Rancher 部署与使用指南
  • 使用Rancher在CentOS 环境上部署和管理多Kubernetes集群
  • 如何把一台电脑作为另外一台电脑的显示器
  • 地理特征类可视化图像
  • Java 依赖管理工具:使用 Sonatype Nexus 管理项目依赖
  • Ubantu安装 Jenkins LTS
  • AI大模型和SpringAI简介
  • 2025年最新基于Vue基础项目Todolist任务编辑器【适合新手入手】【有这一片足够了】【附源码】
  • php本地 curl 请求证书问题解决
  • Map的遍历与判断键是否存在-《Go语言实战指南》
  • ArcGIS Pro 3.4 二次开发 - 编辑
  • 基于RT-Thread的STM32F4开发第七讲——RTC(硬件、软件)
  • ATGM332D-F8N22单北斗多频定位导航模块
  • SQLMesh Typed Macros:让SQL宏更强大、更安全、更易维护
  • 【闲聊篇】java好丰富!
  • RabbitMQ配置环境变量
  • onnx模型转入rknn3399平台上工作记录
  • React从基础入门到高级实战:React 基础入门 - JSX与组件基础
  • 深入解析Java类加载机制:双亲委派模型
  • Halcon计算点到平面的距离没有那么简单
  • Spring Boot微服务架构(一):如何拆分?如何将CRM系统拆解为多个微服务构建?
  • Spring Boot集成Resilience4j实现微服务容错机制
  • 亚马逊云科技推出Anthropic新一代模型
  • 电子电气架构 --- 下一代汽车电子电气架构中的连接性
  • 传输层协议TCP