# docker
# linux docker
# https://github.com/docker/docker-install
make shellcheck
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
# docker 加速
# https://developer.aliyun.com/article/1131834
# docker manager
potainer & lazydocker
# 编程范式
OOP:
Object Oriented Programming 对象式编程
知识点树形图-入门
面向对象编程 (OOP) - 入门知识点
│
├── 类与对象
│ ├── 定义类 (class)
│ ├── 创建对象 (new Class())
│ ├── 构造函数 (constructor)
│ ├── 实例属性与方法
│ ├── 静态属性与方法 (static)
│ └── this 关键字的指向
│
├── 属性类型
│ ├── 实例属性(每个对象独立)
│ ├── 静态属性(类级别共享)
│ └── 私有属性约定(_prop 命名)
│
├── 封装 (Encapsulation)
│ ├── 数据隐藏(通过 _ 表示私有)
│ ├── Getter / Setter 方法
│ ├── 控制属性访问权限
│ └── 示例:密码保护、余额封装
│
└── 基础方法
├── 实例方法定义与调用
└── 静态方法的使用场景
知识点树形图-高阶
面向对象编程 (OOP) - 高阶知识点
│
├── 继承 (Inheritance)
│ ├── 子类 extends 父类
│ ├── super 关键字
│ │ ├── 调用父类构造函数 (super())
│ │ └── 调用父类方法 (super.methodName())
│ └── 方法重写(Override)
│
├── 多态 (Polymorphism)
│ ├── 同一接口不同实现
│ ├── 子类重写父类方法
│ ├── 运行时决定调用哪个方法
│ └── 示例:Animal、Dog、Cat 的 speak 方法
│
├── 抽象 (Abstraction)
│ ├── 隐藏复杂实现细节
│ ├── 只暴露必要接口
│ └── 用户无需了解内部逻辑
│
├── 对象关系
│ ├── 关联(Association)
│ ├── 聚合(Aggregation)
│ └── 组合(Composition)
│
├── 设计原则(SOLID)
│ ├── 单一职责原则 (SRP)
│ ├── 开闭原则 (OCP)
│ ├── 里氏替换原则 (LSP)
│ ├── 接口隔离原则 (ISP)
│ └── 依赖倒置原则 (DIP)
│
├── 设计模式(常见)
│ ├── 工厂模式
│ ├── 单例模式
│ ├── 策略模式
│ └── 观察者模式(部分 OOP 实现)
│
└── 高级特性(ES6+ / TypeScript)
├── 混入(Mixins)
├── 装饰器(Decorators)
├── 代理(Proxy)
├── 反射(Reflection)
├── 接口(Interfaces)— TypeScript
└── 抽象类(Abstract Classes)— TypeScript
class User {
// 静态属性
static userCount = 0
constructor(name, email, password) {
// 实例属性
this.name = name
this.email = email
this._password = '' // 使用 _ 表示私有属性
// 初始化
this.setPassword(password)
User.userCount++
}
// 静态方法
static getUserCount() {
console.log(`Total users: ${User.userCount}`)
}
// 实例方法:登录验证
login(email, password) {
if (email === this.email && password === this._password) {
console.log(`Welcome back, ${this.name}!`)
} else {
console.error('Login failed: invalid credentials.')
}
}
// Getter
get password() {
return '********'
}
// Setter
set password(value) {
this.setPassword(value)
}
// 实例方法
setPassword(newPassword) {
if (newPassword.length >= 6) {
this._password = newPassword
} else {
throw new Error('Password must be at least 6 characters')
}
}
}
// 创建用户,constructor 中自动调用 setPassword
const user1 = new User('Alice', '[email protected]', 'secret123')
// 使用 getter 查看密码(隐藏真实值)
console.log(user1.password) // 输出: ********
// 使用 setter 设置新密码
user1.password = 'newpass789' // 触发 setter,内部调用 setPassword
// 登录测试
user1.login('[email protected]', 'newpass789') // 输出: Welcome back, Alice!
// 查看静态属性
User.getUserCount() // 输出: Total users: 1
FP:
Functional Programming 函数式编程
FRP:
Functional Reactive Programming 函数式响应式编程
# AOP 与 Decorator
AOP:
Aspect Oriented Programming 面向切面编程
AOP 是 OOP 的一种补充概念,核心思想是把业务逻辑与业务逻辑以外的代码分离,比如日志记录、权限验证、事务管理等。
简单来说,就是 AOP 可以在不修改原有代码的情况下,在代码执行前后添加一些额外的功能。
# IoC 与 DI
IoC:
Inversion of Control 反转控制
IoC 是一种设计思想和设计模式,其核心思想是将对象的创建和依赖关系交给外部容器,从而实现依赖关系的对象间的解耦。
DI:
Dependency Injection 依赖注入
DI 是 IoC 的一种实现方式,它将依赖关系注入到对象中,从而实现依赖关系的对象间的解耦。
常见的依赖注入方式有:
- 构造函数注入:通过构造函数参数的形式将依赖关系注入到对象中。
class Controller {
constructor() {
this.service = new Service()
}
start() {
this.service.start()
}
}
// DI 容器
class Service {
constructor() {
this.prisma = new PrismaClient()
}
start() {
this.prisma.start()
}
}
class PrismaClient {
start() {
console.log('PrismaClient start')
}
}
// 使用
const col = new Controller()
col.start()
代码示例
// database.js
class Database {
save(data) {
throw new Error("Abstract method 'save' must be implemented.")
}
}
class MongoDBDatabase extends Database {
save(data) {
console.log(`[MongoDB] Persisted: ${data}`)
}
}
class RedisDatabase extends Database {
save(data) {
console.log(`[Redis] Persisted: ${data}`)
}
}
// user.service.js
class UserService {
constructor(database) {
this.database = database
}
registerUser(user) {
this.database.save(user)
}
}
// main.js
const mongoService = new UserService(new MongoDBDatabase())
mongoService.registerUser('Alice')
- 装饰器注入:ts + nestjs 风格
代码示例
// database.ts
interface Database {
save(data: any): void
}
class MongoDBDatabase implements Database {
save(data: any): void {
console.log(`[MongoDB] Persisted: ${JSON.stringify(data)}`)
}
}
class RedisDatabase implements Database {
save(data: any): void {
console.log(`[Redis] Cached: ${JSON.stringify(data)}`)
}
}
// user.service.ts
import { Injectable } from '@nestjs/common'
@Injectable()
class UserService {
constructor(private readonly database: Database) {}
registerUser(username: string): void {
console.log(`Registering user: ${username}`)
this.database.save({ username })
}
}
// main.ts
const mongoService = new UserService(new MongoDBDatabase())
mongoService.registerUser('Alice')
# reflect-metadata
- reflect-metadata (opens new window) 是一个元数据反射库,它允许开发者在运行时访问和修改类、方法、属性等元数据信息。
# 初始化项目
npm init -y
npm install reflect-metadata
npm install typescript ts-node --save-dev
# 创建tsconfig.json
tsc --init
# 追加:
# "experimentalDecorators": true,
# "emitDecoratorMetadata": true,
# 运行demo文件
npx ts-node simple.ts
import 'reflect-metadata'
function Inject(target: any, key: string) {
target[key] = new (Reflect.getMetadata('design:type', target, key))()
}
class A {
sayHello() {
console.log('hello')
}
}
class B {
@Inject // 等同于执行了 @Reflect.metadata('design:type', A)
a!: A
say() {
this.a.sayHello() // 不在需要 new A()
}
}
new B().say() // hello
# DI 容器
nestjs 中的 DI 容器,用于管理依赖注入。
- 注册所有有@Injectable 装饰器的类
- 通过 Constructor 了解类与类之间的依赖关系
- Nestjs 会自动创建@Injectable 装饰的类实例
- Nestjs 会自动创建依赖关系的类实例
- 按需进行调用
# @Module
@Module 是 nestjs 的核心,用于管理模块之间的依赖关系。
管理:
- imports: 引入其他 module 模块
- controllers: 获取 DI 中具体的 class 类的实例
重点:
- providers: 里面的 service 类会被放到 DI 中初始化
- exports: 里面的 service 类可以在其他地方使用
# DTO / DAO
DTO:
Data Transfer Object 数据传输对象
DAO:
Data Access Object 数据访问对象
流程:
请求 -> DTO(对请求数据进行校验)-> 逻辑 -> DAO(对数据进行操作) -> 响应
- create-cat.dto.ts
// 约定数据字段和类型
// 方便数据类型校验
export class CreateCatDto {
name: string
age: number
breed: string
}
- cat.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
import { HydratedDocument } from 'mongoose'
export type CatDocument = HydratedDocument<Cat>
@Schema()
export class Cat {
@Prop()
name: string
@Prop()
age: number
@Prop()
breed: string
}
export const CatSchema = SchemaFactory.createForClass(Cat)
认知规划 →