《深入解析Android 虚拟机》——1.3 编译Android源码

简介: Android编译环境本身比较复杂,并且不像普通的编译环境那样只有顶层目录下才有Makefile文件,而其他的每个Component都使用统一标准的Android.mk文件。不过这并不是我们熟悉的Makefile,而是经过Android自身编译系统的很多处理。

本节书摘来自异步社区《深入解析Android 虚拟机》一书中的第1章,第1.3节,作者:钟世礼著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.3 编译Android源码

编译Android源码的方法非常简单,只需使用Android源码根目录下的Makefile,执行make命令即可轻松实现。因为Android L是一个Preview版本,官方并没有公布其完整的内核代码。所以本节中的编译内容将以正式版Android 4.3进行。当然在编译Android源码之前,首先要确定已经完成同步工作。进入Android源码目录使用make命令进行编译,使用此命令的格式如下所示:

$: cd ~/Android4.3(这里的“Android4.3”就是我们下载源码的保存目录)
$: make

编译Android源码可以得到“~/project/android/cupcake/out”目录,笔者的截图界面如图1-18所示。

screenshot

整个编译过程也是非常漫长的,需要读者耐心等待。在本节的内容中,将详细讲解编译Android源码的基本过程。

1.3.1 搭建编译环境
在编译Android源码之前,需要先进行环境搭建工作。在接下来的内容中,以Ubuntu系统为例讲解搭建编译环境以及编译Android源码的方法。具体流程如下。

(1)安装JDK,编译Android 4.3的源码需要JDK1.6,下载jdk-6u21-linux-i586.bin后进行安装,对应命令如下所示:

$ cd /usr
$ mkdir java
$ cd java
$ sudo cp jdk-6u21-linux-i586.bin所在目录 ./
$ sudo chmod 755 jdk-6u21-linux-i586.bin
$ sudo sh jdk-6u21-linux-i586.bin

(2)设置JDK环境变量,将如下环境变量添加到主文件夹目录下的.bashrc文件中,然后用source命令使其生效,加入的环境变量代码如下所示:

export JAVA_HOME=/usr/java/jdk1.6.0_23
export JRE_HOME=$JAVA_HOME/jre 
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/bin/tools.jar:$JRE_HOME/bin
export ANDROID_JAVA_HOME=$JAVA_HOME

(3)安装需要的包,读者可以根据编译过程中的提示进行选择,可能需要的包的安装命令如下所示:

$ sudo apt-get install git-core bison zlib1g-dev flex libx11-dev gperf sudo aptitude install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev

1.3.2 开始编译
当完成安装所依赖包的工作后,就可以开始编译Android源码了,具体步骤如下。

(1)首先进行编译初始化工作,在终端中执行以下命令:

source build/envsetup.sh
或:

.build/envsetup.sh
执行后将会输出以下内容。

source build/envsetup.sh 
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/generic/armv7-a-neon/vendorsetup.sh
including device/generic/armv7-a/vendorsetup.sh
including device/generic/mips/vendorsetup.sh
including device/generic/x86/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including device/samsung/toroplus/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including sdk/bash_completion/adb.bash

(2)然后选择编译目标,具体命令如下:

lunch full-eng
执行后会输出如下所示的提示信息:

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.3
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.2.2-5-generic-x86_61-with-Ubuntu-10.01-lucid
HOST_BUILD_TYPE=release
BUILD_ID=JOP40C
OUT_DIR=out
============================================

(3)接下来开始编译代码,在终端中执行以下命令:

make -j4
其中“-j4”表示用4个线程进行编译。整个编译进度根据不同机器的配置而需要不同的时间。例如笔者电脑为Intel i5-2300四核2.8 Hz,4 GB内存,经过近4小时才编译完成。当出现下面的信息时表示编译完成:

target Java: ContactsTests (out/target/common/obj/APPS/ContactsTests_intermediates/classes)
target Dex: Contacts
Done!
Install: out/target/product/generic/system/app/Browser.odex
Install: out/target/product/generic/system/app/Browser.apk
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Copying: out/target/common/obj/APPS/Contacts_intermediates/noproguard.classes.dex
target Package: Contacts (out/target/product/generic/obj/APPS/Contacts_intermediates/package.apk)
 'out/target/common/obj/APPS/Contacts_intermediates/classes.dex' as 'classes.dex'...
Processing target/product/generic/obj/APPS/Contacts_intermediates/package.apk
Done!
Install: out/target/product/generic/system/app/Contacts.odex
Install: out/target/product/generic/system/app/Contacts.apk
build/tools/generate-notice-files.py  out/target/product/generic/obj/NOTICE.txt  out/target/product/generic/obj/NOTICE.html "Notices for files contained in the filesystem images in this directory:" out/target/product/generic/obj/NOTICE_FILES/src
Combining NOTICE files into HTML
Combining NOTICE files into text
Installed file list: out/target/product/generic/installed-files.txt
Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img
Running:  mkyaffs2image -f out/target/product/generic/system out/target/product/generic/obj/PACKAGING/ systemimage_intermediates/system.img
Install system fs image: out/target/product/generic/system.img
DroidDoc took 5331 sec. to write docs to out/target/common/docs/doc-comment-check

1.3.3 在模拟器中运行
在模拟器中运行的步骤就比较简单了,只需在终端中执行下面的命令即可:

emulator
运行成功后的效果如图1-19所示。

screenshot

1.3.4 常见的错误分析
虽然编译方法非常简单,但是作为初学者来说非常容易出错,在下面列出了其中常见的编译错误类型。

(1)缺少必要的软件。

进入到Android目录下,使用make命令进行编译,可能会发现出现如下所示的错误提示。

host C: libneo_cgi <= external/clearsilver/cgi/cgi.c 
external/clearsilver/cgi/cgi.c:22:18: error: zlib.h: No such file or directory

上述错误是因为缺少zlib1g-dev,需要使用apt-get命令从软件仓库中安装zlib1g-dev,具体命令如下所示:

sudo apt-get install zlib1g-dev
同理需要安装下面的软件,否则也会出现上述类似的错误:

sudo apt-get install flex
sudo apt-get install bison
sudo apt-get install gperf
sudo apt-get install libsdl-dev
sudo apt-get install libesd0-dev
sudo apt-get install libncurses5-dev
sudo apt-get install libx11-dev

(2)没有安装Java环境JDK。

当安装所有上述软件后,运行make命令再次编译Android源码。如果在之前忘记安装Java环境JDK,则此时会出现很多Java文件无法编译的错误,如果打开Android的源码,可以在如下目录中下发现有很多Java源文件。

android/dalvik/libcore/dom/src/test/java/org/w3c/domts
这充分说明在编译Android之前必须先安装Java环境JDK,安装流程如下所示。

① 登录Oracle官方网站,下载jdk-6u16-linux-i586.bin文件并安装。

在Ubuntu 8.04中,“/etc/profile”文件是全局的环境变量配置文件,它适用于所有的shell。在登录Linux系统时应该先启动“/etc/profile”文件,然后再启动用户目录下的“~/.bash_profile”、“~/.bash_login”或“~/.profile”文件中的其中一个,执行的顺序和上面的排序一样。如果“~/.bash_profile”文件存在,则还会执行“~/.bashrc”文件。在此只需要把JDK的目录放到“/etc/profile”目录下即可:

JAVA_HOME=/usr/local/src/jdk1.6.0_16
PATH=$PATH:$JAVA_HOME/bin:/usr/local/src/android-sdk-linux_x86-1.1_r1/tools:~/bin

② 重新启动计算机,输入java –version命令,输出下面的信息则表示配置成功:

ava version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 13.1-b01, mixed mode, sharing)

当成功编译Android源码后,在终端会输出如下提示:

Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_unopt_intermediates/system.img
Install system fs image: out/target/product/generic/system.img
Target ram disk: out/target/product/generic/ramdisk.img
Target userdata fs image: out/target/product/generic/userdata.img
Installed file list: out/target/product/generic/installed-files.txt
root@dfsun2009-desktop:/bin/android#

1.3.5 实践演练——演示两种编译Android程序的方法
Android编译环境本身比较复杂,并且不像普通的编译环境那样只有顶层目录下才有Makefile文件,而其他的每个Component都使用统一标准的Android.mk文件。不过这并不是我们熟悉的Makefile,而是经过Android自身编译系统的很多处理。所以说要真正理清楚其中的联系还比较复杂,不过这种方式的好处在于,编写一个新的Android.mk给Android增加一个新的Component会变得比较简单。为了使读者更加深入地理解在Linux环境下编译Android程序的方法,在接下来的内容中,将分别演示两种编译Android程序的方法。

1.编译Native C(本地C程序)的helloworld模块
编译Java程序可以直接采用Eclipse的集成环境来完成,实现方法非常简单,在这里就不再重复了。接下来将主要针对C/C++进行说明,通过一个例子来讲解在Android 中增加一个C程序的Hello World的方法。

(1)在“$(YOUR_ANDROID)/development”目录下创建一个名为“hello”的目录,并用“$(YOUR_ANDROID)”指向Android源代码所在的目录:

- # mkdir $(YOUR_ANDROID)/development/hello
(2)在目录“$(YOUR_ANDROID)/development/hello/”下编写一个名为“hello.c”的C语言文件,文件hello.c的实现代码如下所示:

#include <stdio.h>
int main()
{
    printf("Hello World!\n");//输出Hello World
return 0;
}

(3)在目录“$(YOUR_ANDROID)/development/hello/”下编写Android.mk文件。这是Android Makefile的标准命名,不能更改。文件Android.mk的格式和内容可以参考其他已有的Android.mk文件的写法,针对helloworld程序的Android.mk文件内容如下所示:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
    hello.c
LOCAL_MODULE := helloworld
include $(BUILD_EXECUTABLE)

上述各个内容的具体说明如下所示。

LOCAL_SRC_FILES:用来指定源文件用。
LOCAL_MODULE:指定要编译的模块的名字,在下一步骤编译时将会用到。
include $(BUILD_EXECUTABLE):表示要编译成一个可执行文件,如果想编译成动态库则可用BUILD_SHARED_LIBRARY,这些具体用法可以在“$(YOUR_ANDROID)/build/core/config.mk”查到。
(4)回到Android源代码顶层目录进行编译。

# cd $(YOUR_ANDROID) && make helloworld
在此需要注意,make helloworld中的目标名helloworld就是上面Android.mk文件中由LOCAL_MODULE指定的模块名。最终的编译结果如下所示:

target thumb C: helloworld <= development/hello/hello.c
target Executable: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/ LINKED/helloworld)
target Non-prelinked: helloworld (out/target/product/generic/symbols/system/bin/helloworld)
target Strip: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/ helloworld)
Install: out/target/product/generic/system/bin/helloworld

(5)如果和上述编译结果相同,则编译后的可执行文件存放在如下目录:

out/target/product/generic/system/bin/helloworld
这样通过“adb push”将它传送到模拟器上,再通过“adb shell”登录到模拟器终端后就可以执行了。

2.手工编译C模块
在前面讲解了通过标准的Android.mk文件来编译C模块的具体流程,其实可以直接运用gcc命令行来编译C程序,这样可以更好地了解Android编译环境的细节。具体流程如下。

(1)在Android编译环境中,提供了“showcommands”选项来显示编译命令行,可以通过打开这个选项来查看一些编译时的细节。

(2)在具体操作之前需要使用如下命令把前面中的helloworld模块清除:

# make clean-helloworld
上面的“make clean-$(LOCAL_MODULE)”命令是Android编译环境提供的make clean的方式。

(3)使用showcommands选项重新编译helloworld,具体命令如下所示:

# make helloworld showcommands
build/core/product_config.mk:229: WARNING: adding test OTA key
target thumb C: helloworld <= development/hello/hello.c
prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-gcc  -I system/core/include   -I hardware/libhardware/include   -I hardware/ril/include   -I dalvik/libnativehelper/include   -I frameworks/base/include   -I external/skia/include   -I out/target/product/generic/obj/include   -I bionic/libc/arch-arm/include   -I bionic/libc/include   -I bionic/libstdc++/include   -I bionic/libc/kernel/common   -I bionic/libc/kernel/arch-arm   -I bionic/libm/include   -I bionic/libm/include/arch/arm   -I bionic/libthread_db/include   -I development/hello   -I out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates  -c  -fno-exceptions -Wno-multichar -march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -DSK_RELEASE -DNDEBUG -O2 -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64      -MD -o out/target/product/generic/ obj/EXECUTABLES/helloworld_intermediates/hello.o development/hello/hello.c

target Executable: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/ LINKED/helloworld)

prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-g++ -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o out/target/product/generic/ obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld -Lout/target/product/generic/obj/lib -Wl, -rpath-link=out/target/product/generic/obj/lib -lc -lstdc++ -lm  out/target/product/generic/obj/lib/ crtbegin_dynamic.o         out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o       -Wl,--no-undefined prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/../lib/gcc/arm-eabi/4.3.1/interwork/libgcc.a out/target/product/generic/obj/lib/crtend_android.o

target Non-prelinked: helloworld (out/target/product/generic/symbols/system/bin/helloworld)

out/host/linux-x86/bin/acp -fpt out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/ LINKED/helloworld out/target/product/generic/symbols/system/bin/helloworld

target Strip: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld)

out/host/linux-x86/bin/soslim --strip --shady --quiet out/target/product/generic/symbols/system/bin/ helloworld --outfile out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld

Install: out/target/product/generic/system/bin/helloworld

out/host/linux-x86/bin/acp -fpt out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/ helloworld out/target/product/generic/system/bin/helloworld

从上述命令行可以看到,Android编译环境所用的交叉编译工具链如下所示:

prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-gcc
其中参数“-I”和“-L”分别指定了所用的C库头文件和动态库文件路径分别是“bionic/libc/include ”和“out/target/product/generic/obj/lib”,其他还包括很多编译选项以及-D所定义的预编译宏。

(4)此时就可以利用上面的编译命令来手工编译helloworld程序,首先手工删除上次编译得到的helloworld程序:

# rm out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o
# rm out/target/product/generic/system/bin/helloworld

然后再用gcc编译以生成目标文件:

# prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-gcc -I bionic/libc/arch-arm/include -I bionic/libc/include -I bionic/libc/kernel/common   -I bionic/libc/kernel/arch-arm -c  -fno-exceptions -Wno-multichar -march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -include system/core/include/arch/linux-arm/AndroidConfig.h -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -DSK_RELEASE -DNDEBUG -O2 -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64      -MD -o out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/hello.o development/hello/hello.c

如果此时与Android.mk编译参数进行比较,会发现上面主要减少了不必要的参数“-I”。

(5)接下来开始生成可执行文件:

# prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,build/core/ armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o out/target/ product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld -Lout/target/product/generic/obj/lib -Wl,-rpath-link=out/target/product/generic/obj/lib -lc -lm  out/target/product/generic/obj/EXECUTABLES/ helloworld_intermediates/hello.o out/target/product/generic/obj/lib/crtbegin_dynamic.o -Wl,--no- undefined ./prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/../lib/gcc/arm-eabi/4.3.1/interwork/libgcc.a out/target/product/generic/obj/lib/crtend_android.o

在此需要特别注意的是参数“-Wl,-dynamic-linker,/system/bin/linker”,它指定了Android专用的动态链接器是“/system/bin/linker”,而不是平常使用的ld.so。

(6)最后可以使用命令file和readelf来查看生成的可执行程序:

# file out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld
out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld: ELF 31-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
#  readelf -d out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld |grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]

这就是ARM格式的动态链接可执行文件,在运行时需要libc.so和libm.so。当提示“not stripped”时表示它还没被STRIP(剥离)。嵌入式系统中为节省空间通常将编译完成的可执行文件或动态库进行剥离,即去掉其中多余的符号表信息。在前面“make helloworld showcommands”命令的最后也可以看到,Android编译环境中使用了“out/host/linux-x86/bin/soslim”工具进行STRIP。

相关文章
|
7月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
203 2
|
3月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
340 29
|
3月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
97 4
|
3月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
3月前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
3月前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
3月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
4月前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
405 0
|
6月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
6月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

推荐镜像

更多
下一篇
oss创建bucket