本周推荐 | 设计模式在淘宝营销价格体系的实践

news2024/12/23 11:44:39

推荐语:本文详细描述责任链、中介者、适配器等多种设计模式在淘宝营销价格服务中的应用,从而实现了一套可扩展性的架构,应对灵活多变营销价格需求。

——大淘宝技术研发工程师 小枫

每年淘宝都有双11、双12等大促,我们价格服务小组的工作就是提前预计算大促期间消费者将要购买的每一件商品的价格,为消费者选出真正优惠的商品。但是大淘宝营销策略历时已久,种类多样,又紧跟市场波动,千变万化,这就要求我们设计的系统具备高可扩展性。因此今天我向大家介绍一下我们营销域下的价格服务系统是如何做到高可扩展性的。

517a6c57f0323f63079949cc2c95e895.png

营销域价格计算

我们营销域的价格服务主要是计算大促商品的消费者到手价。所谓消费者到手价就是该商品在指定的未来某个时间段消费者能购买到的价格,是由商品的活动价减去叠加在商品上面的各种优惠金额后的价格。举个例子,一件衣服参与双十一活动,价格为980元,商家还设置了商品优惠券满800减200元,同时商家还报名了跨店满减(满300减50元)活动,除此之外没有其他优惠了,那该商品到手价就是980-200-[980/300]*50 = 630元。

  种类多样

商品优惠券、满2件打8折、跨店满减、品类券、消费券这些词对于经常网购的朋友来说肯定很熟悉,这些就是我们所说的优惠工具。为了满足不同场景下消费者的需求,我们设计了多种多样的优惠工具。用户在下单的时候往往会用到多种优惠工具,比如在今年淘宝天猫双十一活动中,大部分订单都使用了两类及其以上的优惠工具。有些情况下,为了让消费者更方便计算,优惠工具是互斥使用的。比如在双十一时,一个订单使用了跨店满减,那么就不能再使用商家发行的满折优惠了。我们要做的就是计算出最省钱的优惠工具组合方式,在此基础上得到消费者在大促期间可能买到的价格。

  千变万化

消费者的需求是不断变化的,因此我们的营销策略也是随着消费者的需求不断调整的。

近些年为了让消费者更方便计算,我们开始简化营销。比如让某两类优惠工具不能同时使用,但是还有一些白名单商家或者商品类目又是可以二者同时使用的。

为了解决消费者买多件更贵问题,我们推出了预售直降券。买多件更贵问题是指:由于我们在领取商家发的优惠券时在下单时只能使用一张,在我们下单时买较少件数的价格就可以达到使用该优惠券的门槛,但是当我们买更多件时还是只能使用一张,导致了买多件还不如分开买便宜。为了解决这个问题我们推出了直降券,优惠直接作用在每件商品上面。

我们大淘宝营销工具的业务随着市场不断变化,每次大促活动玩法都各不相同,不断新增优惠和玩法,我们常常需要在短时间内把某项新的优惠玩法纳入到我们的计算链路中,这就要求我们的系统具备高可扩展性。同时如果能够充分利用原有代码,也将会节省我们的开发时间。

efb342b0df48cdf94c3e323dacf05ed3.png

为何要引入设计模式

  价格服务业务特点

由前面章节可以看到我们的优惠工具是种类多样且千变万化的,除此之外我们的开发测试资源也非常紧张。

每次新增优惠和玩法等业务或者进行优惠工具规则调整时,不仅留给开发人员的时间短,测试资源也非常紧张。如果我们每次新增加一个优惠等规则进入到我们的计算链路中时都会改动大量的核心计算链路代码,那测试的case也将要覆盖非常多的面。举个例子,平台新增加了官方立减优惠,如果我们系统架构设计的不够好,必须要改动原先核心计算价格的函数才能将该优惠计算规则加入,那么测试的范围可能不仅仅是当前新增加的官方立减优惠,还要包括之前已经实现的店铺优惠券、品类券、跨店满减等等各种通过该核心链路的优惠。无疑大大增加测试的工作量,本就资源紧张的测试人员更加无法完成。因此要求我们的系统能够灵活扩展,且对原有业务的影响要降到最低。

随着业务的拓展和团队的扩张,团队内不断有新人加入,面对着有着十万行以上代码、由多位开发人员合力而成的大项目,如何能够让新人迅速读懂代码,理解如此设计的道理是项目设计时必须要考虑的问题,即增加自己写的代码可读性和架构可解释性也是对我们当前开发人员的一大要求。

因此可以总结我们营销域下价格服务的业务特点:优惠种类多样、业务千变万化、需求开发周期短、测试资源紧张和开发人员迭代频繁等。因为这些特点所以要求我们的系统架构设计要高可扩展、代码高可复用、有统一架构设计标准。

51a4e842c8c22f719dddeffb6abdf15c.png

  设计模式

设计模式的概念出自《Design Patterns - Elements of Reusable Object-Oriented Software》中文名是《设计模式 - 可复用的面向对象软件元素》,该书是在1994 年由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合力完成。书中提出的面向对象的设计模式七大基本准则也是我们在平时编码时要广泛遵守的,它们包括:

  1. 开闭原则(Open Closed Principle,OCP)

    对外扩展开放,对内修改关闭。就是说新增需求时尽量通过扩展新类实现,而不是对原有代码修改增删。

  2. 单一职责原则(Single Responsibility Principle, SRP)

    每个类、每个方法的职责(目的)都是单一的。不要让一个类或方法做太多纵向关联或横向并列的事,否则会增加维护负担。

  3. 里氏代换原则(Liskov Substitution Principle,LSP)

    继承必须确保超类所拥有的性质在子类中仍然成立。就是只要父类出现的地方,都可以用子类替换。

  4. 依赖倒转原则(Dependency Inversion Principle,DIP)

    高层模块不应该依赖低层模块,二者都应该依赖其抽象。就是尽量使用接口来做标准和规范,降低耦合度。

  5. 接口隔离原则(Interface Segregation Principle,ISP)

    接口的功能尽可能单一。一个接口只做一类行为或事物的标准。

  6. 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)

    类间关系尽量使用聚合、组合来实现,如果不可以的话再使用继承。目的还是为了降低类间耦合度,类间关系有六种,它们的耦合度大小关系是:泛化>实现>组合>聚合>关联>依赖,我们在设计架构时,尽量让类间关系靠近右边(就是采用耦合度更小的关系)。

  7. 最少知道原则(Least Knowledge Principle,LKP)/迪米特法则(Law of Demeter,LOD)

    一个对象要对其他对象的成员尽可能少的知道。目的就是降低类间耦合度,提高代码的可复用性。

前辈们从对象的创建、对象结构关系及对象的行为总结了适应于不同场景的设计模式,设计模式中我们常常挂在嘴边的有三大类23种,包括创建型的工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式6种,结构型的适配器模式、过滤器模式、装饰器模式、桥接模式、组合模式、享元模式、代理模式和外观模式8中,行为型的责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式、访问者模式。

引入设计模式的优势可以简单概括为:

  1. 增加系统可扩展性

  2. 增加代码的复用性

  3. 增强代码可读性

  4. 借助前人经验,提供开发效率

  引入设计模式

总结一下我们价格计算服务业务的项目设计需求:

  1. 系统要具备高可扩展性,适应千变万化的营销业务场景;

  2. 系统原代码、架构要具备高通用性,为开放时间短、任务重的需求减少新增代码量;

  3. 系统要核心和扩展分离,扩展时不修改原核心链路,减少测试压力;

  4. 系统设计采用通用规范,便于他人理解。

对我们的项目设计需求总结后可以发现设计模式的优势正好能够帮我们解决上述问题,因此我们的项目架构设计时引入和借鉴了很多经典的设计模式。架构在引入设计模式基础上,我们设计了更多的优化算法,让我们的价格计算撑起了每个大促活动的价格服务。

接下来我将从我们系统中用的设计模式中列举几个,看一看我们是如果借助设计模式对我们的问题进行建模的。

5a9272e86f42d6d568a1beef48858b46.png

价格计算链路模型

  业务介绍

我们价格服务的基本工作就是计算每一件商品在未来某时间段的消费者到手价。比如在我们组织的每一场大促活动,商家的报名时间是提前很多天的,商家报名商品参加活动的同时,也会为自己的商品设置很多优惠,比如满100减10元,同时商家也可以报名平台发起的优惠活动,比如报名参加跨店满减或者品类券。商品报名完成后,我们需要实时计算商品的消费者到手价,提前判断该商品有没有足够优惠。

  业务模型

465bb9f8e118cc8593f811fb6ac04ebf.png

  责任链模式

责任链模式属于行为型设计模式,英文名称Chain of Responsibility,其定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

责任链模式将对请求的处理过程划分为多个独立的处理节点,节点间互相不感知具体计算过程。处理节点存在前后顺序处理关系,也可以视具体的业务特点跳过某些节点。

责任链设计模式的优点如下:

4d87882f6e160bf927edb2caf3e9874a.png

  中介者模式

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,就像我们在网络通信链路中传递的一个数据包,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

中介者设计模式的优点:

62aeabef86197912286b714c058bc0d5.png

  设计模式实践

我们在计算商品的消费者到手价时,客户端调用我们的价格计算HSF接口后,我们首先要对请求做基本的限流、验证等处理,验证通过后要查库获取该商品在价格计算中所需的全部信息,结合商品信息还要查询该商品可用的全部优惠,再结合对应的计算规则为该商品筛选其可用的优惠,并按照最低到手价原则为该商品叠加组合出最省钱的优惠工具使用方式,在最优组合基础上计算出该商品的消费者到手价,最后进行存储和返回。同时整个计算链路中还要面临短时间内新增一个环节或者跳过(下线)某个环节的问题。

为更好的解决上述问题,我们引入责任链模式,首先要做的到就是对整个价格计算链路进行责任分割,我们初步分割为请求的基本处理部分、商品信息获取部分、计算规则生成部分、优惠工具获取部分、价格计算部分和结果存储返回部分,每一个部分下面再细分处理节点,整个结构如下图所示。在计算商品消费者到手价的过程中,从接收Request Body到返回Response Body,责任链模式可以说是贯穿始终的。将所有对请求的处理和计算步骤拆分为一个个计算节点,上一节点计算完成后,将结果传到下一节点再进行计算。计算节点间仅仅传递数据,互相不感知具体计算过程。

812bef52c2bb42646ec538b89fb1adbb.png

责任划分完成后,按照责任链模式设计架构,并采用中介者模式,将context对象作为一个中介者,在责任链的不同处理节点间进行数据传递,架构类图如下所示。

6fd9e764b993da58da5e200feed9da7c.png

看到这里,读者可能会疑惑这里Chain与Processor是组合关系,但是Processor的方法形参中有Chain,又依赖了Chain,有点循环依赖的感觉。这里将chain作为形参和context一起在上下文间传递,是为了在每个Processor的process()方法的最后会调用chain.process()方法,在chain.process()方法中按照初始化的Processor顺序执行调用下一个Processor。

那为什么不将chain抽离出来,仅在chain端调用下一个Processor呢?设计为如下模式。

a5cf105ef34cd63ea58bb4736d5d13e0.png

其实这里的设计是借鉴了Servlet FilterChain过滤器链的结构,在一个 Web 应用程序中可以注册多个 Filter 程序,如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter 链,每个Filter节点可以选择将该请求传递到哪个节点、跳过哪些节点和直接返回。

664b2fd32dbc3bc4401a1eba6cea5597.png

将处理链chain作为process方法的参数在上下文间传递,每个Processor可以更具自己对请求的处理结果,灵活的从chain中选择下一个Processor继续处理请求。否则,如果再回到chain中调用下一个Processor,需要当前Processor处理完成后,传回chain中某种标识,让chain根据标识选择下一个处理节点。此处直接将chain作为参数在上下文间传递,省区了标识传递,简化了设计,而且chain在初始化后是不会变化的,并不会引起在传递过程中被修改的风险。

  引入效果

采用责任链模式和中介者模式相结合完成对整改商品价格计算链路的搭建后,让我们的业务扩展变得非常方便。

  1. 适配新业务能力强,可以迅速扩展新节点,编码完成新业务;

  2. 受益于每个责任链节点对其他类的依赖关系低,开发过程中对其他代码影响较小;

  3. 测试方便,可以针对扩展或修改的节点进行单独测试,很容易构建各种case测试修改节点。

3340341fac24355f85db95f18d309ddd.jpeg

优惠种类多样问题

  业务介绍

我们大淘宝现在的优惠工具种类多样,作用原理又各不相同。

从功能上可以被划分为多个层级,比如店铺优惠层级的店铺券,比如平台优惠层级的跨店满减。每个层级下又有很多细分优惠,比如店铺优惠包括店铺券和店铺满减,店铺券又分为商品优惠券、店铺优惠券。

不同的优惠工具使用场景不同,作用方式不同,有的优惠工具是有门槛的,比如满100减10元的优惠券,有的优惠工具是没有门槛的,比如预售立减;有的门槛是价格,比如商品优惠券;有的门槛是商品购买数量,比如满2减9折;有的是需要凑单后才能使用的,比如跨店满减;有的是指定商品类型才能使用,比如品类券。

  业务模型

21b915397c9adf1bf36200f7e3d3f786.png

  适配器模式

适配器模式属于行为型设计模式,英文名称是Adapter Pattern,其定义为:作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

a4aa1ddd6a8f77c439cc3ccefc965340.png

我们的计算链路设计好后,要在后面的业务扩展时尽可能少的去改动其代码。适配器模式会极大降低客户端的使用难度,让客户端无需关系他所连接的被适配类,只需关系适配类结构即可,适配类一般是不会变化了,即使新增被试适配类,就是我们业务上新增优惠工具、玩法时,在增加该优惠工具的描述类后,再增加一个转换类便可以接入到我们的计算链路中来。

  设计模式实践

不同优惠工具其作用原理、使用方式不同,需要不同的类去描述每一种优惠工具,但是我们在计算商品的消费者到手价时,只关心所要计算的时间内能不能用这张券、商品的价格等自身条件有没有达到使用门槛、和如果能使用那么优惠多少钱。

为了方便我们对商品价格的计算,解决上述三个问题的同时要求我们的计算链路稳定性高且易扩展,就是平台新增一种优惠工具时,尽可能少的去改动我们原有核心计算链路。因此我们引入了适配器模式,这里我简单的将需要被转换的一方成为源端,最终转换成便于上层调用的一方成为宿端。我们的宿端所要实现或者描述的内容就是上述三个问题,即优惠工具使用时间、优惠工具门槛和优惠金额。源端就是诸如跨店满减、品类券、店铺券、店铺满减和官方立减等各式各样的优惠工具。因为不同优惠工具的原理不同,编码实现方式也大相径庭,因为要为每一种优惠工具提供一个转换方法。整体架构模式如下图所示。

2ed8ac8b87efdd03aed92b7e75cca5c8.png

  引入效果

通过引入适配器模式,解决了在计算商品消费者到手价时不同优惠使用方式千差万别的有大量if-else的场景。尤其新增加或者减少一种优惠时,只需新增这种优惠的描述类和转换方法即可,基本不修改核心计算链路,而且可以大量复用原有链路中价格计算的代码,扩展性好。

02b15b9aa6c8700160634871167e3c33.jpeg

多类型下游模型

  业务介绍

我们价格服务的下游使用方有多个,不同的下游使用方业务不同,目的不同,业务模型有差别,获取的结果中的关键参数自然也不同。同时之前由于业务迭代,对原有模型进行了优化,但是之前老接口已经有调用方在调用,需要做到新老同时支持。而且随着业务发展,我们的接口下游使用方会不断增加。

  业务模型

cc502a1a97eac737c1f1211f380b7b91.png

  策略模式

策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式将每个算法从原来统一的方法中拆分出来,每一个算法封装为一个类,这些类共同继承同一个父类或实现一个标准接口。

403f3f7a98da29ece8abb60d62cc48f0.png

  设计模式实践

为了减少代码中同一个方法里面大量出现if-else结构,以提高可读性和可扩展性为目的,结合业务场景特点与策略模式优势,我们在设计给下游使用方发送消息的模块时引入了策略模式。

首先抽象出一个消息Sender标准接口,接口中定义了每个消息发送类所必须实现的方法,主要是获取规则(getRules)和发送动作(send)这两个方法,同时对于一些多个类可共用的方法我们在消息Sender抽象父类中实现,向各个下游使用方进行消息发送动作的类需要实现消息Sender接口并继承消息Sender抽象父类。

所有策略的具体实现类完成后,我们业务消息SenderProcessor类中,用map集合记录所有的要发送方的规则代号和对应的消息发送实现类,具体为下图中的ruleSendMapper结构,并在该类的init()方法(创建该类实例后立刻执行该方法)中对该map进行初始化。在运行时进行消息发送时,就可以根据传递过来的规则rule选择对应的消息发送实现类进行发送。

9af489b74599130f407193159b979462.png

  引入效果

该部分代码中没有出现大量的if-else结构,同时随着业务扩展,在向新的下游使用方发送消息时,只需增加针对该下游使用方的一个类,让该类实现标准接口、继承公用父类即可,不会对原有代码进行修改,扩展非常方便。

5b689c5f6878f8eda796a1ec8c9381a6.jpeg

多套计算规则问题

  业务介绍

平台价格计算的规则是多种多样的,而且每种规则都是非常复杂的。在不同的站点如淘宝、天猫和聚划算,有不同的优惠筛选策略和计算规则。在不同的时间段如大促和日销,优惠是否计入的规则也是不一样的。

  业务模型

fd7bf491ad2c3264862d3f3da2590105.png

  解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。在调用方和被调用方进行规则策略传递前,双方只需事先约定好每种文法或者策略都由一个代号来代替,当调用方去调用被调用方接口时,只需要传递一个简单的代号即可,在被调用方会根据代号解释翻译为具体的文法或策略。

  设计模式实践

我们在HSF的请求体Request中定义了计算规则reuleId和商品所在站点,站点就包括天猫、淘宝和聚划算等等。ruleId只是一个约定的代号,通过规则翻译解释类将该代号翻译解释为该规则具体的要求,比如是否包将某类优惠计算在内、品类券具体的计入规则和店铺券发行张数的要求等。

规则翻译完成后,我们将其放入到计算链路的上下文Context中,在某些需要根据规则进行区别处理的计算节点中,将取出规则rule执行对应具体规则。

5e88c05828e49802a4e41089a1d191a6.png

  引入效果

引入后使我们的整个计算链路能够根据不同的计算规则进行灵活切换,具体的计算规则不用通过调用放传递过来,仅需传递一个编号,规则翻译解释类再将编号翻译解释为具体的处理规则,并进行处理。在规则扩展时,修改思路明确,首先在CalculateRule规则类中实现新增的规则描述,然后在所需要修改的计算节点上增加对该规则的解释实现类即可。

2df578fd50ae5e4df3e94acd681124bc.jpeg

总结

我们的项目中使用了多种设计模式,篇幅有限此处只列出了责任链、中介者、适配器、策略和解释器五种设计模式。我们在使用某些设计模式时,并非照本宣科完全按照该模式的架构来搭建我们的系统,而是灵活的结合业务场景做了一些适配、折中和让步,但是总的方向是不违反七大设计原则的。

在一个项目中如果需要用到多种设计模式时,我认为要选择其中一个设计模式作为主设计模式,其他设计模式如果与其存在设计上的冲突时,需要为其让步。具体选择哪种模式作为项目的主设计模式,这要因业务场景而异,比如我们的价格计算服务项目就以责任链模式作为主设计模式。

营销业务对市场波动敏感,业务迭代迅速,优惠工具、规则和玩法种类多样、千变万化,正是得益于我们价格服务项目架构在设计时恰当的引入了经典的设计模式,让系统具备了高可扩展性,最终让我们有把握迅速上线新业务。

bca9aecfa51e0da8e374cab28956e745.jpeg

团队介绍

我们是大淘宝技术平台营销工具团队,是营销业务核心支撑团队,承担成交杠杆的职责,通过创新不断帮助业务挖掘新场景新用户、结合商业化能力打造技术引擎。
平台营销工具不断沉淀商业能力、运营支撑能力,例如品类券、购物津贴、会员卡等实现动态加码、混合出资,极大提升了面向竞争的灵活性;前N、买就返等形成大促标配组合拳,稳定支撑全年50+大促活动。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【车载开发系列】UDS诊断---常见的ISO标准集合

【车载开发系列】UDS诊断—常见的ISO标准集合 常见的ISO标准集合【车载开发系列】UDS诊断---常见的ISO标准集合一.前言二.基于CAN总线ISO1)ISO118982)ISO115193)ISO15765三.UDS诊断1)ISO142292)ISO14229系列规范四.CAN…

我国余热发电行业现状:政策及企业积极性双管齐下 市场发展潜力大

根据观研报告网发布的《中国余热发电行业现状深度研究与发展前景预测报告(2022-2029年)》显示,余热发电是指利用生产过程中多余的热能转换为电能的技术。余热发电技术可以回收利用如水泥、玻璃、钢铁、冶金等行业的余热资源,将余热…

深入浅出synchronized关键字

前言 无论在日常工作还是面试过程中,synchronized关键字作为并发场景下的操作,是一定要掌握的,本文从synchronized的使用方式、原理及优化三个方面,对synchronized关键字作一个系统化的说明。 使用方式 synchronized主要有三种…

Apache DolphinScheduler 发布 3.1.2 版本,Python API 实现优化

点亮 ⭐️ Star 照亮开源之路https://github.com/apache/dolphinscheduler近日,Apache DolphinScheduler 发布了 3.1.2 版本。此版本主要基于 3.1.1 版本进行了 6 处 Python API 优化,19 处 Bug 修复,并更新了 4 个文档。其中较为重要的 Bug…

HashMap1.7和1.8源码解析

1.HashMap (1)数据结构 在JDK1.7中,HashMap中的数据结构是数组单链表的组合;在JDK1.8中的HashMap存储结构是由数组、链表、红黑树这三种数据结构形成。 (2)JDK1.7中HashMap源码分析 (2.1&am…

Portal门户常见宕机或性能低问题分析与七大解决之道

不论使用什么产品构建门户,只要是基于Java技术的,就很容易宕机或出现性能低的问题。因为Portal产品比较复杂,且集成的数据特别多,架构特别复杂,涉及到的数据通信特别多。宕机或性能低也通常是用户较为头疼的问题。经常…

excel文本函数应用:单元格中的数字和字母,如何判断?

文本字符是Excel中除了数字以外的另一种非常常用的数据类型,Excel也提供了大量的文本函数。利用这些函数我们可以用来判断字符串开头是否为数字、字符串是否同时包含了数字和英文、字符串是否包含了指定字符,可以用来转换英文字母的大小,可以…

Java基础之Stream的使用078

1. Stream 的使用 Stream 是什么? Stream 是数据渠道,用于操作数据源(数组、集合等)所生成的元素序列。 Java8两大最为重要的改变就是 Lambda表达式 与 Stream API,这两种改变的引入带来的是新的抽象方式 &#xff08…

目标检测之Fast RCNN概述

基本原理 Fast Rcnn主要步骤为 利用SR算法生成候选区域利用VGG16网络进行特征提取利用第一步生成的候选区域在特征图中得到对应的特征矩阵利用ROI pooling将特征矩阵缩放到相同大小并平展得到预测结果 相对于RCNN的优化 主要有三个改进 不再将每一个候选区域依次放入CNN网络…

【基于通道-空间注意的高分辨率锐化】

Channel–spatial attention-based pan-sharpening of very high-resolution satellite images (基于通道-空间注意的很高分辨率卫星影像全色锐化) 全色锐化处理旨在生成新的合成输出图像,其保留全色的空间细节和多光谱图像输入的光谱细节。…

【服务器端程序的演进过程】

目录 1 服务器端程序的演进过程 阶段一:静态服务器 阶段二:普通动态服务器 阶段三: 以用户共享内容为主的互联网生态 阶段四: 微服务时代(有高并发需求或特征的网站) 2 Java服务器项目分类 3 微服务概述 3.1 什么是微服务 3.2 为什么需要微服务 3.3 怎么搭建微服务项…

C#获取计算机详细的软件和硬件信息

利用System.Management提供的类可以用于读取本地计算机设备的各种数据,包括操作系统、软件、硬件的各种详细信息,内容很丰富。 System.Management的命名空间下,ManagementObjectSearcher类用于查询特定类型的设备,ManagementObjec…

转行做“程序员”很难?这里有几个建议...

“是什么?为什么?怎么样?”的灵魂三连问在我们生活中比比皆是,目的是为了清晰思考和看到事物的本质。对于编程学习也是一样,需要带着疑问从本质上去学习编。 本人是某985高校的本硕连读,非计算机科班出身&…

利器 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

1080469 14.7 KB 上两篇文章介绍了自动遍历的测试需求、工具选择和 AppCrawler 的环境安装、启动及配置文件字段基本含义,这里将以实际案例更加细致的说明配置文件的用法和一些特殊场景的处理。 下面我们继续之前的例子,在雪球搜索框输入搜索内容后的页面…

CloudFlare系列--功能介绍与常用配置

原文网址:CloudFlare系列--功能与特性的介绍_IT利刃出鞘的博客-CSDN博客 简介 本文介绍CloudFlare的功能与常用的配置。 功能介绍 CloudFlare是世界最强的网络服务商。它可以提供如下服务: 防御DDoS攻击 世界最强防御DDos攻击的厂商。域名注册 世界最…

JavaWeb语法四:多线程案例

目录 1.单例模式 1.1:饿汉模式 1.2:懒汉模式 2.阻塞式队列 2.1:生产者消费者模型 2.2:阻塞队列的模拟实现 3.线程池 3.1:标准库中的线程池 3.2:模拟实现线程池 前言:前一篇我们讲了线程不安全的原因…

SAP UI5 里 FlexBox 的使用方法

ScrollContainer 的使用方式: ScrollContainer 是一个控件,可以在有限的屏幕区域内显示任意内容,并提供滚动以使所有内容都可访问。注意,为了避免影响用户使用体验,不要嵌套沿相同方向滚动的滚动区域。例如&#xff…

【LaTex】基础语法框架快速入门教程——Tex live+TexStudio简要安装及使用教程

0. 引言 LaTeX对于论文排版有着巨大的便利,并且对于参考文献的引用也十分方便,不会出现使用word引用参考文献一旦更改文献引用顺序,就必须全部改编号的情况。这里记录一下如何从0开始学习使用LaTeX书写论文。 1. 软件安装&环境配置 1.…

Qt中实例化一个函数变量时加不加括号的区别,以及括号中的this的使用

一、设计一个测试小程序 废话不多说,直接上代码。 main.h函数就不多说了,没改动。直接上mainwindow.h,也没改动。看mainwindow.cpp的内容。 #include "mainwindow.h" #include "ui_mainwindow.h" #include "test.…

机器学习算法基础——KNN算法

KNN (K-Nearest Neighbor)–K近邻分类算法 • 为了判断未知实例的类别,以所有已知类别的实例作为参照选择参数K • 计算未知实例与所有已知实例的距离 • 选择最近K个已知实例 • 根据少数服从多数的投票法则(majority-voting),让未知实例归类为K个最邻…