WebScarab关键源码分析(4)

数据加载DataFetcher与ModelLoader结构 UML如下: glide数据加载模块,基本结构如上图所示,DataFetcher定义了取数据的接口,具体的通过何种方式取数据,网络还是本地,均是由其子类实现,接下来我们介绍DataFetcher的几个子类。ModelLoader是一个工厂接口,用于将任意复杂的数据模型转换为具体数据类型,从而能够使用DataFetcher去获取由该模型表示的资源的数据,具体的ModelLoader实现... 阅读详情
在上一篇博文里我们分析了URLFetcher的一些行为以及相关方法,顺着这个思路走,接着我们遇到的问题是:

谁使用了URLFetcher?它是如何使用URLFetcher的?

这就又牵扯到了两个关键的类:HTTPClientFactory和FetchQueue。

首先从HTTPClientFactory说起,从名字我们也可以大概看出,这是一个工厂模式,这个工厂可以产生HTTPClient对象,当然HTTPClient是一个接口,实际上就是可以产生URLFetcher对象(该对象实现了HTTPClient接口)。

工厂本身是一个单例模式,其第一行代码说明了这一点:

private static HTTPClientFactory _instance = new HTTPClientFactory();


同时使用getinstance方法返回此唯一实例:

 

 public static HTTPClientFactory getInstance() {
        return _instance;
    }


接着比较重要的方法有产生URLFetcher对象的方法:

public HTTPClient getHTTPClient() {
        URLFetcher uf = new URLFetcher();
        uf.setHttpProxy(_httpProxy, _httpProxyPort);
        uf.setHttpsProxy(_httpsProxy, _httpsProxyPort);
        uf.setNoProxy(_noProxy);
        uf.setSSLContextManager(_sslContextManager);
        uf.setTimeouts(_connectTimeout, _readTimeout);
        uf.setAuthenticator(_authenticator);
        return uf;
    }

 可以看出,该方法很简单,首先设置一些代理以及超时相关的设定,然后就直接返回新建的URLFetcher对象了。

但是让人困惑的是以下这个方法:

 

public Response fetchResponse(Request request) throws IOException {
        HTTPClient hc = null;
        synchronized (_availableClients) {
            if (_availableClients.size()>0) {
                hc = (HTTPClient) _availableClients.remove(0);
            } else {
                _logger.info("Creating a new Fetcher");
                hc = getHTTPClient();
                _clientList.add(hc);
            }
        }
        Response response = null;
        IOException ioe = null;
        try {
            response = hc.fetchResponse(request);
        } catch (IOException e) {
            ioe = e;
        }
        synchronized (_availableClients) {
            _availableClients.add(hc);
        }
        if (ioe != null) throw ioe;
        return response;
    }


为什么让人困惑呢,因为笔者认为这个方法出现在这里很不合理。

设计模式告诉我们作为一个Factory,它唯一的职责就在于创建用户想要的对象,也就是将类的实例化的工作解耦出来。而这个方法很明显是封装了URLFetcher的fetchResponse功能,换句话说,它起到了一个管理HTTPClient的功能,而这个功能无论如何都不是属于Factory的职责,所以说这个方法出现在这里很怪。

当然或许代码原作者本身就想让Factory起到一个管理功能,但这样假设的话public的getHttpClient方法又说不清了,因为这个方法的存在使得不会有其它的类从逻辑上会尝试去调用getHttpClient方法(为什么呢?你调用getHttpClient方法肯定是为了获取一个实现HTTPClient接口的对象,你得到这个对象肯定是为了调用fetchResponse方法,而factory已经帮你把这个方法封装好了,为啥你还要去自己调用getHttpClient呢?),反正无论怎么说这里从逻辑上设计的不合理。

当然逻辑归逻辑,面向对象方法学归面向对象方法学,虽然看上去让人不舒服,但好用就行了,不是么?

吐槽完了之后继续分析这段代码的逻辑,可以看出代码首先锁住_availableClients,这是个什么什么东西呢?按F3追上去发现是一个arraylist,从名字也可以看出,这个ArrayList存储了可用的Clients,然后尝试从这个对象里获取第一个位置(下标为0)的HttpClient对象,若容器为空,说明当前没有可用对象便实例化一个新的对象。然后用调用这个对象的fetchResponse方法去请求这个Request,最后再锁死_availableClients,把用完的Client加进去。

这段代码一开始看上去没啥难的,但为了方便理解以后的代码,需要注意这两点:

1、HttpClient是反复使用的,虽然采用资源池的方法最大限度的使用了已有资源,但是却不能很好的利用Http1.1中的connect:keep-alive属性。(为什么?因为两个指向相同地址的请求可能使用不同的httpClient,并且httpClient每次fetchResponse都要重新连接。)

2、在response返回(函数结束)之前,httpClient已经先于response返回资源池。

至此HttpClientFactory类的分析就结束了。考虑到篇幅问题,就在下篇里面分析FetcherQueue吧。

Parallel URL Fetcher-开源 Puf是命令行Web(HTTP)客户端。 它类似于GNU wget(并且具有类似的选项),但是具有并行执行许多下载的能力。 当然,它支持递归提取。 立即下载

相关推荐

第12章 STM32+BH1750光照传感器+OLED模块显示环境光照强度

相比光敏传感器,它可以直接输出环境光照强度的数值(范围是0~65535lx),非常适合懒人党,各位的传感器买到手后,赶紧跟着文章试试吧!

qq_44645742的博客 1万+

关于chrome的UrlFetch类

urlfetch的创建; urlfetch的生命周期 urlfetch的释放 注意:urlfetch一定要在创建的同时,用完了后要释放掉,如果不释放掉就存在一个问题,这个连接一致保持着,一个tcp连接的断开就是在urlfetch的析构的时候,调用了request->cancel()

5300

ICNN实现入侵检测的思路与源码(CIC-IDS-2017)

基于ICNN实现入侵检测,可用于现实网络

t1274171989的博客 8415

Web安全测试-WebScarab工具介绍

 1.1  Webscarab 【功能】 WebScarab是一个用来分析使用HTTP和HTTPS协议的应用程序框架。其原理很简单,WebScarab可以记录它检测到的会话内容(请求和应答),并允许使用者可以通过多种形式来查看记录。WebScarab的设计目的是让使用者可以掌握某种基于HTTP(S)程序的运作过程;可以用它来调试程序中较难处理的bug,也可以帮助安全专家发现潜在的程序漏洞。...

iteye_5347的博客 1150

MicroPython跨平台移植实战:从源码解析到STM32+FreeRTOS部署

本文详细解析了MicroPython的跨平台移植实战,重点介绍了如何将其从源码开始,成功部署到STM32微控制器并运行于FreeRTOS实时操作系统。内容涵盖源码结构解析、编译环境搭建、内存管理协调、FreeRTOS任务集成、数学库(math)启用与优化,以及自定义模块开发等核心步骤,为开发者提供了一套完整的、可操作的嵌入式Python移植方案。

vodka的博客 1014

告别轮询!用STM32CubeMX给STM32F030配置ADC多通道+DMA,实测代码分享

本文详细介绍了如何使用STM32CubeMX为STM32F030配置ADC多通道采集与DMA传输,显著提升采集效率。通过实测对比轮询与DMA模式的性能差异,提供完整的代码实现和优化技巧,帮助开发者快速掌握这一高效采集方案。

weixin_42570296的博客 410

URL请求流程图

url请求流程图:   输入url请求地址   通过DNS服务查询目标IP   浏览器发送请求   浏览器与服务器完成三次握手,建立链接     socket作为网络通信的基本操作单元,负责完成数据传输   浏览器发送http请求   服务器处理http请求,并返回http响应   浏览器解析渲染html页面,转换成人类易懂内容   浏览器与服务器完成四次挥手,断开链接 ...

m0_38098362的博客 2341

【本地部署实战】LM Studio深度使用指南:从环境搭建到模型调优

LM Studio通过极简的操作流程和强大的生态兼容性,让本地部署大模型成为可能。随着M4芯片的发布和CUDA 12.0的优化,未来本地化AI开发将迎来新的爆发点。建议开发者关注官方Discord社区(https://discord.gg/lmstudio)获取最新模型支持信息。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 8751

chromium中HTTP网络资源的加载过程

chromium中HTTP网络资源的加载主要分两部分,一部分是缓存的网络资源,一部分是线上的网络资源。我们访问http网页的时候,首先访问httpcache,看缓存中的数据是否有效,如果有效,那么我们加载这个数据,如果无效,那么我们访问网络去重新加载资源,当然chromium中HTTP网络资源的加载并没有说起来这么简单,实际上架构设计还是比较复杂的。首先我们先看看HttpCache::Transac

飞鸟的专栏 6196

10. 重磅!Spring AI 1.0 正式发布,Java 开发者的 AI神器!

重磅!Spring AI 1.0 正式发布,Java 开发者的 AI神器! 全网最详细的Spring AI 文章,每章都会提供代码入口,让你更容易得入门和理解Spring AI 相关概念,直接节约你百分之六十的学习成本时间。

gorgor在码农 1066

SpringBoot中使用FastJson解析Json数据

场景 1.SpringBoot默认配置的是Jackson。 2.项目搭建专栏: https://blog.youkuaiyun.com/BADAO_LIUMANG_QIZHI/column/info/35688 实现 引入fastJson的依赖 <!-- fastjson的依赖 --> <dependency> <groupId>com.alibab...

BADAO_LIUMANG_QIZHI的博客 4140

Webscarab关键源码分析(1)

最近写一个android上的东西,要用到http代理的一些东西,包括封装解析各种http request和response以及多连接并发管理各种麻烦的东西。虽然自己也能写,但感觉是在重复的发明轮子,不如拿一些现成的东西来用,而且更快更成熟。所以选择了Webscareb,打算把里面的http协议栈相关的东西裁减出来供自己使用,这就避免不了源码的阅读。 但在网上搜了搜发现没有什么和这方面有关的资料,

锐之锋芒 1403

手把手教你用 Cursor 写一个完整的 Web 应用(含前后端 + 部署)

本文介绍如何利用Cursor AI工具从零开发一个完整的全栈待办事项Web应用。文章针对开发者常见痛点——无法独立完成项目闭环,提供了一套AI驱动的全栈开发范式。通过Vue3+Node.js+MySQL技术栈,全程由Cursor自动生成项目架构、前后端代码、数据库设计,并解决联调、部署等关键问题。重点展示了如何用AI完成:项目规划与架构设计、后端接口开发、前端页面实现、跨域联调、打包优化及云端部署全流程。该方法将传统需要3-5天的开发工作压缩至1小时内完成,产出规范可上线的项目,特别适合想突破"碎

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 637

WebScarab关键源码分析(5)

接上篇分析FetcherQueue,这个大概是最麻烦的方法了,通过这个方法实现线程池进而实现异步操作,并将resquest和httpclient对象结合起来,同时还维护请求队列,并负责调用上层传下来的ConversationHandler方法。 首先从构造函数说起: public FetcherQueue(String name, ConversationHandler handler

锐之锋芒 1119

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

WebScarab关键源码分析(3)

今天读的比较多,就多写点吧。 一个Http代理要实现的功能不外乎就四句话,保存客户端发过来的http请求,将请求发给服务器端,搜集返回结果,并发给客户端,如果用webscarab的数据结构来描述这个过程的话也就:   客户socket的输入流----->> request对象 ------->>>response对象------->>>客户socket输出流 如果把这三个箭头当做3个过程,

锐之锋芒 1211

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Webscarab关键源码分析(2)

接上篇说Request对象和Response对象 Request代表一个请求,首先给出一个http请求头: GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 Host: net.tutsplus.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US;

锐之锋芒 1071

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

WebScarab关键源码分析(3)(续)

接上篇。 接下来是两个if,如果接收到的是401或者407返回码(其含义分别为需验证和代理服务器需验证),则重新调整验证信息,并在下一个while里继续请求内容。 再一个是判断如果request使用的是head方法,则setNobody(),因为head方法是不可能有内容部分的,调用setnobody后未读取的输入流_in将不会再尝试读取。 接着判断connect域的内容,如果是不是keep

锐之锋芒 832

Nutch 1.3 学习笔记 5 Fetcher流程

Nutch 1.3 学习笔记 5 Fetcher ------------------------------- 1. Fetcher模块的简单介绍 Fetcher这个模块在Nutch中有单独一个包在实现,在org.apache.nutch.fetcher,其中有Fetch

lemo的专栏 4817

Chromium网页URL加载过程分析

Chromium在Browser进程中为网页创建了一个Frame Tree之后,会将网页的URL发送给Render进程进行加载。Render进程接收到网页URL加载请求之后,会做一些必要的初始化工作,然后请求Browser进程下载网页的内容。Browser进程一边下载网页内容,一边又通过共享内存将网页内容传递给Render进程解析,也就是创建DOM Tree。本文接下来就分析网页URL的加载过程。

老罗的Android之旅 3万+

怎样设计一个好架构:八个评价维度、四层思考深度,以及 23 种设计模式各自解决什么问题

架构要解决的是变化、理解、故障和协作的成本。本文从耦合、可迁移、可适配、复杂度等八个维度讲怎么评价架构,讲维度之间怎么取舍、架构思考可以分几层,再用可编译的 C 代码过一遍 23 种设计模式。

weixin_52400878的博客 334

访问者模式详解

汇总目录请点击访问:《设计模式目录汇总》 喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞!

2601_96797912的博客 21

Agent Skill 五大设计模式:从工程实践到落地指南

Skill 不是一段临时 Prompt,而是一个可复用、可测试、可迭代的任务流程模板。通常通过SKILL.mdWhen:什么情况下触发How:按什么步骤执行What:最终输出什么:哪些行为必须遵守、哪些行为禁止fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;用户意图Skill 路由工具调用 / MCP / API结构化输出检查与交付。

m0_62458145的博客 211

设计模式之状态模式

状态模式是一种行为型设计模式,通过将对象的不同状态行为封装到独立的状态类中,使上下文对象在状态变化时自动切换行为。以外卖订单为例,不同状态(如待支付、配送中)对同一操作(如取消)有不同响应。状态模式避免了复杂的if/else判断,提升代码可维护性与扩展性。其核心由上下文(Order)、状态接口(OrderState)和具体状态类组成,通过委托机制实现状态间的平滑切换。

FallingGod的博客 166

设计模式速查

本文梳理12个核心设计模式,涵盖创建型、结构型与行为型,提供简洁Java实现与面试要点。重点解析单例(静态内部类)、工厂(方法/抽象)、建造者(链式构建)等高频模式,强调代码可维护性与扩展性,附速记口诀与对比表格,助力开发与面试双提升。

ttlovet的博客 174

设计模式(unity游戏研发版)

当你使用图形用户界面类时通常会遇到一个问题。比如,你创建了自定义按钮类并允许客户端在按钮中注入自定义代码,这样当用户按下按钮时就会触发这些代码。观察者模式允许任何实现了订阅者接口的对象订阅发布者对象的事件通知。你可在按钮中添加订阅机制,允许客户端通过自定义订阅类注入自定义代码。在Unity中,这就像UnityEvent在Inspector中绑定多个回调。

m0_63330263的博客 103
上一篇: WebScarab关键源码分析(3)(续)
下一篇: WebScarab关键源码分析(5)
ROger__Wong
博客等级 码龄14年 250粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值