GoF设计模式——结构型设计模式分析与应用

文章目录

    • UML图的结构主要表现为:继承(抽象)、关联 、组合或聚合 的三种关系。
      • 1. 继承(抽象,泛化关系)
      • 2. 关联
      • 3. 组合/聚合
      • 各种可能的配合:
        • 1. 关联后抽象
        • 2. 关联的集合
        • 3. 组合接口
        • 4. 递归聚合接口
      • Adapter
      • Bridge
      • Composite
      • Decorator
      • Facade
      • Flyweight
      • Proxy

GoF(Gang of Four)设计模式的三大类:

  • 创建型设计模式(Creational Patterns)
  • 结构型设计模式(Structural Patterns)
  • 行为设计模式(Behavioral Patterns)

Object Scope 可用于运行时

Class Scope 只能用于编译时

在这里插入图片描述


UML图的结构主要表现为:继承(抽象)、关联 、组合或聚合 的三种关系。

车是交通工具,车是我的,车里有发动机

1. 继承(抽象,泛化关系)

class Vehicle {
    String name;
    void move() {}
}

class Car extends Vehicle {
    void drive() {}
}

2. 关联

class Person {
    Car car; // 关联关系
}

class Car {
    String model;
}

3. 组合/聚合

class Car {
    Engine engine; // 组合关系
    GPS gps;       // 聚合关系
}

class Engine {}
class GPS {}

各种可能的配合:

圈住部分即为原因。

1. 关联后抽象

在这里插入图片描述

2. 关联的集合

在这里插入图片描述

3. 组合接口

在这里插入图片描述

4. 递归聚合接口

在这里插入图片描述
这里递归怎么理解?

其实是虽然我的装饰器实现了这个接口,但是我的装饰器类内部成员可能还有有这个接口类



Adapter

适配器模式能够将不兼容的接口转换成兼容的接口,从而使得原本无法直接交互的类能够合作。
可以在不修改现有代码的情况下,重用第三方的功能或代码。
可以在不同的系统间进行灵活的接口转换,尤其适用于系统集成和迁移。

Adapter(适配器)设计模式

继承+关联 (“关联后抽象”)

“ 加一层,新接口。”
在这里插入图片描述

(“R”标记:可运行时改变;实心箭头指实现,空心指泛化)

设计逻辑的层次:

  • 先从具体类(ConcreteAdapter)的实现入手,明确其与其他类的关联(如 Adaptee)。
  • 然后在其上进一步抽象出一个统一的接口(Adapter),以适应多种实现需求。
// 老版本的播放器接口
class OldMediaPlayer {
    void playAudio() {
        System.out.println("Playing audio...");
    }
}

// 新播放器接口
interface ModernPlayer {
    void play();
}

// 适配器类
class PlayerAdapter implements ModernPlayer {
    private OldMediaPlayer oldMediaPlayer;

    public PlayerAdapter(OldMediaPlayer oldMediaPlayer) {
        this.oldMediaPlayer = oldMediaPlayer;
    }

    @Override
    public void play() {
        oldMediaPlayer.playAudio(); // 使用旧方法适配新接口
    }
}

// 客户端代码
public class AdapterExample {
    public static void main(String[] args) {
        OldMediaPlayer oldPlayer = new OldMediaPlayer();
        ModernPlayer modernPlayer = new PlayerAdapter(oldPlayer);

        modernPlayer.play(); // 使用新接口播放
    }
}

Bridge

解耦抽象和实现:桥接模式将抽象部分与实现部分分离,可以独立地扩展两者。
新增抽象层或者实现层时,不会影响到对方,增强了系统的可扩展性。
避免重复代码,增加代码复用性。

Bridge(桥)设计模式

组合接口

“ 比如形状类里加个颜色类。 而该形状可以在各种地方使用”
在这里插入图片描述

// 实现接口
interface Color {
    String fill();
}

class Red implements Color {
    public String fill() {
        return "Color is Red";
    }
}

class Blue implements Color {
    public String fill() {
        return "Color is Blue";
    }
}

// 抽象类
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);
    }

    public void draw() {
        System.out.println("Drawing Circle. " + color.fill());
    }
}

// 客户端代码
public class BridgeExample {
    public static void main(String[] args) {
        Shape redCircle = new Circle(new Red());
        Shape blueCircle = new Circle(new Blue());

        redCircle.draw();
        blueCircle.draw();
    }
}

Composite

树形结构:组合模式允许你以树形结构来组合对象,简化了对象的管理和处理。
统一操作:可以统一对单个对象和组合对象的处理,客户端不需要知道是单一对象还是组合对象。
递归结构:支持递归组合,使得层次结构更易于表示和管理,特别适用于有层次结构的对象模型。

Composite(组合)设计模式

递归聚合接口

“可以都放进一个容器,装满书的书包”

书包里可能还有一个书包,所以书包的“聚合”里,还有component抽象类——递归。
在这里插入图片描述

// 组件接口
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);
    }
}

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

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

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

// 客户端代码
public class CompositeExample {
    public static void main(String[] args) {
        Composite root = new Composite();

        Leaf leaf1 = new Leaf("Leaf 1");
        Leaf leaf2 = new Leaf("Leaf 2");

        Composite subTree = new Composite();
        subTree.add(new Leaf("SubTree Leaf 1"));

        root.add(leaf1);
        root.add(leaf2);
        root.add(subTree);

        root.operation(); // 遍历树形结构
    }
}

Decorator

动态扩展功能:装饰器模式可以在运行时动态地给对象添加新的功能,而不改变原有类的代码。
增加灵活性:通过装饰器,可以为对象添加多种功能,客户端可以根据需求进行组合,增加了系统的灵活性。
符合开放/关闭原则:装饰器通过扩展功能,而不是修改类本身,符合开放/关闭原则。

Decorator(装饰器)设计模式

递归聚合接口

“对不同物品可以进行不同装饰”

“两组抽象和实现。
装饰器里有【具体部件】和新的方法”
在这里插入图片描述

// 抽象组件(饮料)
interface Beverage {
    String getDescription();
    double cost();
}

// 具体组件
class Coffee implements Beverage {
    public String getDescription() {
        return "Coffee";
    }

    public double cost() {
        return 5.0;
    }
}

// 装饰器
abstract class AddOnDecorator implements Beverage {
    protected Beverage beverage;

    public AddOnDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}

class Milk extends AddOnDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    public String getDescription() {
        return beverage.getDescription() + ", Milk";
    }

    public double cost() {
        return beverage.cost() + 1.0;
    }
}

class Sugar extends AddOnDecorator {
    public Sugar(Beverage beverage) {
        super(beverage);
    }

    public String getDescription() {
        return beverage.getDescription() + ", Sugar";
    }

    public double cost() {
        return beverage.cost() + 0.5;
    }
}

// 客户端代码
public class DecoratorExample {
    public static void main(String[] args) {
        Beverage beverage = new Coffee();
        beverage = new Milk(beverage);
        beverage = new Sugar(beverage);

        System.out.println(beverage.getDescription() + " costs " + beverage.cost());
    }
}

Facade

简化接口:外观模式为复杂子系统提供了一个统一的、高层的接口,简化了客户端的调用方式。
降低耦合:客户端不需要了解各个子系统的实现细节,只需要与外观类交互,从而降低了系统的耦合度。
便于扩展:如果需要修改子系统的实现,可以在外观类中进行修改,而不影响客户端代码。

Façade(门面)设计模式

关联的集合

“将各个组件集成在一起”
在这里插入图片描述

class CPU {
    public void start() {
        System.out.println("CPU started.");
    }
}

class Memory {
    public void load() {
        System.out.println("Memory loaded.");
    }
}

class HardDrive {
    public void readData() {
        System.out.println("HardDrive read 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() {
        cpu.start();
        memory.load();
        hardDrive.readData();
    }
}

// 客户端代码
public class FacadeExample {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start(); // 一键启动
    }
}

Flyweight

内存优化:享元模式通过共享相同的对象实例,减少了内存的消耗,尤其适用于大量相似对象的场景。
提高性能:由于共享对象的使用,可以减少对象的创建和销毁,提高了系统的性能。

Flyweight(享元)设计模式

关联的集合

“共享的懒汉模式”
在这里插入图片描述

// 抽象享元
interface Shape {
    void draw();
}

// 具体享元
class Circle implements Shape {
    private String color;

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

    public void draw() {
        System.out.println("Drawing " + color + " Circle");
    }
}

// 享元工厂
class ShapeFactory {
    private static Map<String, Shape> shapeMap = new HashMap<>();

    public static Shape getCircle(String color) {
        if (!shapeMap.containsKey(color)) {
            shapeMap.put(color, new Circle(color));
            System.out.println("Created new " + color + " Circle");
        }
        return shapeMap.get(color);
    }
}

// 客户端代码
public class FlyweightExample {
    public static void main(String[] args) {
        Shape redCircle = ShapeFactory.getCircle("Red");
        Shape blueCircle = ShapeFactory.getCircle("Blue");
        Shape anotherRedCircle = ShapeFactory.getCircle("Red");

        redCircle.draw();
        blueCircle.draw();
        anotherRedCircle.draw(); // 复用红色圆
    }
}

Proxy

控制访问:代理模式可以控制对真实对象的访问,例如延迟加载、权限控制、缓存等。
增强功能:代理类可以为目标对象增加额外的功能,比如日志记录、安全控制等,而不需要修改目标对象的代码。
降低耦合:代理类和目标类相互独立,客户端通过代理类访问目标对象,减少了对目标类的直接依赖。

Proxy(代理)设计模式

关联后抽象

“懒汉模式”
在这里插入图片描述

// 抽象接口
interface Image {
    void display();
}

// 真实类
class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading " + fileName);
    }

    public void display() {
        System.out.println("Displaying " + fileName);
    }
}

// 代理类
class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;

    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName); // 延迟加载
        }
        realImage.display();
    }
}

// 客户端代码
public class ProxyExample {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");
        image.display(); // 加载并显示
        image.display(); // 再次显示,无需加载
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/923182.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

日常开发记录-正确的prop传参,reduce搭配promise的使用

日常开发记录-正确的prop传参&#xff0c;reduce搭配promise的使用 1.正确的prop传参2.reduce搭配promise的使用 1.正确的prop传参 一般会的父组件传参子组件 //父组件 <A :demodata.sync"testData" :listData.sync"testData2"></A> data ()…

Windows系统电脑安装TightVNC服务端结合内网穿透实现异地远程桌面

文章目录 前言1. 安装TightVNC服务端2. 局域网VNC远程测试3. Win安装Cpolar工具4. 配置VNC远程地址5. VNC远程桌面连接6. 固定VNC远程地址7. 固定VNC地址测试 前言 在追求高效、便捷的数字化办公与生活的今天&#xff0c;远程桌面服务成为了连接不同地点、不同设备之间的重要桥…

IDEA2019搭建Springboot项目基于java1.8 解决Spring Initializr无法创建jdk1.8项目 注释乱码

后端界面搭建 将 https://start.spring.io/ 替换https://start.aliyun.com/ 报错 打开设置 修改如下在这里插入代码片 按此方法无果 翻阅治疗后得知 IDEA2019无法按照网上教程修改此问题因此更新最新idea2024或利用插件Alibaba Clouod Toolkit 换用IDEA2024创建项目 下一步…

Paper -- 洪水深度估计 -- 利用图像处理和深度神经网络绘制街道照片中的洪水深度图

基本信息 论文题目&#xff1a;Flood depth mapping in street photos with image processing and deep neural networks 中文题目: 利用图像处理和深度神经网络绘制街道照片中的洪水深度图 作者及单位&#xff1a; Bahareh Alizadeh Kharazi&#xff0c;美国得克萨斯州立大…

准备阶段 AssetChecker性能分析工具的使用

UPR资源检测工具AssetChecker的使用 AssetChecker主要功能 支持所有版本的Unity项目 不依赖UnityEditor,无需安装绿色运行 检测速度极快&#xff0c;可在UPR中查看结果和修改建议 支持命令模式&#xff0c;可以CI/CD工具集成&#xff0c;实现自动化检测 检测库持续更新 支持A…

【Python】分割秘籍!掌握split()方法,让你的字符串处理轻松无敌!

在Python开发中&#xff0c;字符串处理是最常见也是最基础的任务之一。而在众多字符串操作方法中&#xff0c;split()函数无疑是最为重要和常用的一个。无论你是Python新手&#xff0c;还是经验丰富的开发者&#xff0c;深入理解并熟练运用split()方法&#xff0c;都将大大提升…

数字图像处理(4):FPGA中的定点数、浮点数

&#xff08;1&#xff09;定点数&#xff1a;小数点固定在数据的某一位置的数&#xff0c;可以分为定点整数和定点小数和普通定点数。定点数广泛应用于数字图像处理&#xff08;图像滤波、图像缩放&#xff09;和数字信号处理&#xff08;如FFT、定点卷积&#xff09;中。 定…

重新定义社媒引流:AI社媒引流王如何为品牌赋能?

在社交媒体高度竞争的时代&#xff0c;引流已经不再是单纯追求流量的数字游戏&#xff0c;而是要找到“对的用户”&#xff0c;并与他们建立真实的连接。AI社媒引流王通过技术创新和智能策略&#xff0c;重新定义了社媒引流的方式&#xff0c;帮助品牌在精准触达和高效互动中脱…

tcp/ip异常断开调试笔记——lwip

问题一&#xff1a;异常掉线 异常断开模拟 1、单片机端做服务端&#xff08;只监听一个客户端&#xff09;&#xff0c;电脑做客户端连接 2、尝试连接确定通信正常&#xff0c;断开网线。电脑客户端点击断开 3、经过一段时间&#xff08;超过tcp/ip 3次握手时间&#xff09…

【大数据学习 | Spark-Core】Spark的改变分区的算子

当分区由多变少时&#xff0c;不需要shuffle&#xff0c;也就是父RDD与子RDD之间是窄依赖。 当分区由少变多时&#xff0c;是需要shuffle的。 但极端情况下&#xff08;1000个分区变成1个分区)&#xff0c;这时如果将shuffle设置为false&#xff0c;父子RDD是窄依赖关系&…

低速接口项目之串口Uart开发(二)——FIFO实现串口数据的收发回环测试

本节目录 一、设计思路 二、loop环回模块 三、仿真模块 四、仿真验证 五、上板验证 六、往期文章链接本节内容 一、设计思路 串口数据的收发回环测试&#xff0c;最简单的硬件测试是把Tx和Rx连接在一起&#xff0c;然后上位机进行发送和接收测试&#xff0c;但是需要考虑到串…

C#基础上机练习题

21.计算500-800区间内素数的个数cn&#xff0c;并按所求素数的值从大到小的顺序排列&#xff0c;再计算其间隔加、减之和&#xff0c;即第1个素数-第2个素数第3个素数-第4个素数第5个素数……的值sum。请编写函数实现程序的要求&#xff0c;把结果cn和sum输出。 22.在三位整数…

2024年11月25日Github流行趋势

项目名称&#xff1a;flux 项目维护者&#xff1a;timudk jenuk apolinario zeke thibautRe项目介绍&#xff1a;FLUX.1模型的官方推理仓库。项目star数&#xff1a;17,381项目fork数&#xff1a;1,229 项目名称&#xff1a;screenshot-to-code 项目维护者&#xff1a;abi cle…

运维Tips:Docker或K8s集群拉取Harbor私有容器镜像仓库配置指南

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] Docker与Kubernetes集群拉取Harbor私有容器镜像仓库配置 描述:在现在微服务、云原生的环境下,通常我们会在企业中部署Docker和Kubernetes集群,并且会在企业内部搭建Harbor私有镜像仓库以保证开发源码安全,以及加快…

Qt:信号槽

一. 信号槽概念 信号槽 是 Qt 框架中一种用于对象间通信的机制 。它通过让一个对象发出信号&#xff0c;另一个对象连接到这个信号的槽上来实现通信。信号槽机制是 Qt 的核心特性之一&#xff0c;提供了一种灵活且类型安全的方式来处理事件和数据传递。 1. 信号的本质 QT中&a…

《硬件架构的艺术》笔记(七):处理字节顺序

介绍 本章主要介绍字节顺序的的基本规则。&#xff08;感觉偏软件了&#xff0c;不知道为啥那么会放进《硬件架构的艺术》这本书&#xff09;。 定义 字节顺序定义数据在计算机系统中的存储格式&#xff0c;描述存储器中的MSB和LSB的位置。对于数据始终以32位形式保存在存储器…

【Linux】内核的编译和加载

Linux内核是操作系统的核心&#xff0c;负责管理系统的硬件资源&#xff0c;并为用户空间的应用程序提供必要的服务。内核的编译和加载是操作系统开发和维护的重要环节。本文将详细介绍Linux内核的编译过程以及如何加载内核到系统中。 1. 引言 Linux内核的编译是一个复杂的过…

【Linux】DHCP服务实验

DHCP实验 实验前提 1、两个linux操作系统,一个为服务器端,一个为客户端 2、两个操作系统设置为仅主机模式 3、在客户端-虚拟网络编辑器-仅主机模式VMnet1-关闭DHCP 实验步骤 新建虚拟机

2022年计算机网络408考研真题解析

第一题&#xff1a; 解析&#xff1a;网络体系结构-数据链路层 在ISO网络参考模型中&#xff0c;运输层&#xff0c;网络层和数据链路层都实现了流量的控制功能&#xff0c;其中运输层实现的是端到端的流量控制&#xff0c;网络层实现的是整个网络的流量控制&#xff0c;数据链…

详解 【AVL树】

AVL树实现 1. AVL的概念AVL树的实现2.1 AVL树的结点结构2.2 AVL树的插入2.2.1 AVL树的插入的一个大概操作&#xff1a;2.2.2 AVL树的平衡因子更新2.2.3 平衡因子的停止条件2.2.4 再不考虑旋转的角度上实现AVL树的插入 2.3 旋转2.3.1 旋转的原则2.3.2 右单旋2.2.3 右单旋代码实现…