From 5697d798c41577722a4bee477453435d38a0540d Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Sat, 14 Sep 2024 19:31:09 +0800 Subject: [PATCH 01/47] feat(factory) --- js-advanced/design-pattern/02-easy-factory.ts | 47 +++++++++++ js-advanced/design-pattern/02-factory.ts | 41 ++++++++++ .../design-pattern/03.abstract-factory.ts | 80 +++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 js-advanced/design-pattern/02-easy-factory.ts create mode 100644 js-advanced/design-pattern/02-factory.ts create mode 100644 js-advanced/design-pattern/03.abstract-factory.ts diff --git a/js-advanced/design-pattern/02-easy-factory.ts b/js-advanced/design-pattern/02-easy-factory.ts new file mode 100644 index 0000000..cd01bb5 --- /dev/null +++ b/js-advanced/design-pattern/02-easy-factory.ts @@ -0,0 +1,47 @@ +// 小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木, +// 请你帮他设计一个积木工厂系统,记录积木生产的信息。 + +// 简单工厂模式 通过 if、else 判断,简化了客户端。但是如果要添加新产品,需要修改工厂类代码。 +type TName = "Circle" | "Square"; + +interface Block { + product(): void; +} + +class Circle implements Block { + product(): void { + console.log("Circle BLock"); + } +} + +class Square implements Block { + product(): void { + console.log("Square BLock"); + } +} + +class Factory { + blocks: Block[] = []; + add(type: TName, quantity: number) { + const block = type === "Circle" ? Circle : Square; + for (let i = 0; i < quantity; i++) { + this.blocks.push(new block()); + } + } + + output() { + this.blocks.forEach((block) => { + block.product(); + }); + } +} + +const blockFactory = new Factory(); + +blockFactory.add("Circle", 1); +blockFactory.add("Square", 2); +blockFactory.add("Circle", 1); + +blockFactory.output(); + +export {}; diff --git a/js-advanced/design-pattern/02-factory.ts b/js-advanced/design-pattern/02-factory.ts new file mode 100644 index 0000000..f741909 --- /dev/null +++ b/js-advanced/design-pattern/02-factory.ts @@ -0,0 +1,41 @@ +// 小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木, +// 请你帮他设计一个积木工厂系统,记录积木生产的信息。 + +interface Block { + product(): void; +} + +class Circle implements Block { + product(): void { + console.log("Circle BLock"); + } +} + +class Square implements Block { + product(): void { + console.log("Square BLock"); + } +} + +class Factory { + woods: Block[] = []; + add(type: Block, quantity: number) { + for (let i = 0; i < quantity; i++) { + this.woods.push(new type()); + } + } + + output() { + this.woods.forEach((wood) => { + console.log(`${wood.name} Block`); + }); + } +} + +const blockFactory = new Factory(); + +blockFactory.add("Circle", 1); +blockFactory.add("Square", 2); +blockFactory.add("Circle", 1); + +blockFactory.output(); diff --git a/js-advanced/design-pattern/03.abstract-factory.ts b/js-advanced/design-pattern/03.abstract-factory.ts new file mode 100644 index 0000000..2896c20 --- /dev/null +++ b/js-advanced/design-pattern/03.abstract-factory.ts @@ -0,0 +1,80 @@ +// 小明家新开了两个工厂用来生产家具, +// 一个生产现代风格的沙发和椅子, +// 一个生产古典风格的沙发和椅子,现在工厂收到了一笔订单,请你帮他设计一个系统,描述订单需要生产家具的信息。 + +type TType = "classical" | "modern"; + +interface IChair { + productChair(); +} +interface ISofa { + productSofa(); +} + +interface IFactory { + createSofa(): ISofa; + createChair(): IChair; +} + +class ModernSofa implements ISofa { + productSofa() { + console.log("modern sofa"); + } +} + +class ModernChair implements IChair { + productChair() { + console.log("modern chair"); + } +} + +class ClassicalSofa implements ISofa { + productSofa() { + console.log("classical sofa"); + } +} + +class ClassicalChair implements IChair { + productChair() { + console.log("classical chair"); + } +} + +class ModernFactory implements IFactory { + createChair(): IChair { + return new ModernChair(); + } + createSofa(): ISofa { + return new ModernSofa(); + } +} + +class ClassicalFactory implements IFactory { + createChair(): IChair { + return new ClassicalChair(); + } + createSofa(): ISofa { + return new ClassicalSofa(); + } +} + +function main(count: number) { + const classicalFactory = new ClassicalFactory(); + const modernFactory = new ModernFactory(); + + function dfs(...args: TType[]) { + if (args.length === count) { + args.forEach((type) => { + const facotry = type === "classical" ? classicalFactory : modernFactory; + facotry.createChair().productChair(); + facotry.createSofa().productSofa(); + }); + } else { + return (arg) => dfs(...args, arg); + } + } + return dfs; +} + +// @ts-ignore +main(3)("modern")("classical")("modern"); From 99de169554df506fc0c5ee5d921124b42177b279 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 14:24:29 +0800 Subject: [PATCH 02/47] =?UTF-8?q?feat(factory):=20=E5=B7=A5=E5=8E=82?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/02-factory.ts | 52 ++++++++++++++++-------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/js-advanced/design-pattern/02-factory.ts b/js-advanced/design-pattern/02-factory.ts index f741909..9fe10c3 100644 --- a/js-advanced/design-pattern/02-factory.ts +++ b/js-advanced/design-pattern/02-factory.ts @@ -1,41 +1,57 @@ // 小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木, // 请你帮他设计一个积木工厂系统,记录积木生产的信息。 -interface Block { +interface IBlock { product(): void; } -class Circle implements Block { +interface IFactory { + createBlock(): IBlock; +} + +class Circle implements IBlock { product(): void { console.log("Circle BLock"); } } -class Square implements Block { +class Square implements IBlock { product(): void { console.log("Square BLock"); } } -class Factory { - woods: Block[] = []; - add(type: Block, quantity: number) { - for (let i = 0; i < quantity; i++) { - this.woods.push(new type()); - } +class CircleFactory implements IFactory { + createBlock(): IBlock { + return new Circle(); } +} - output() { - this.woods.forEach((wood) => { - console.log(`${wood.name} Block`); - }); +class SquareFactory implements IFactory { + createBlock(): IBlock { + return new Square(); } } -const blockFactory = new Factory(); +function main(count: number) { + function dfs(...args: [string, number][]) { + if (args.length < count) { + return (arg) => dfs(...args, arg); + } + + args.forEach((blockAndCount) => { + const factory = blockAndCount[0] === "Circle" ? new CircleFactory() : new SquareFactory(); + + for(let i = 0; i < blockAndCount[1]; i++) { + factory.createBlock().product(); + } + }); + } + + return dfs; +} -blockFactory.add("Circle", 1); -blockFactory.add("Square", 2); -blockFactory.add("Circle", 1); +// @ts-ignore +main(3)(['Circle', 1])(['Square', 2])(['Circle', 1]); -blockFactory.output(); +export {}; From 3a93a9f92a27d1c9127563de256c32860cf2f9e6 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 14:24:46 +0800 Subject: [PATCH 03/47] doc(doc + tsconfig) --- js-advanced/design-pattern/README.md | 14 +++- tsconfig.json | 109 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 tsconfig.json diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 4c36ddf..617c259 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -1,5 +1,17 @@ # 设计模式案例实现 ## [参考文档](https://github.com/youngyangyang04/kama-DesignPattern) + [01.单例模式(饿汉)](./01-singleton-hunger.ts) -[01.单例模式(懒汉)](./01-singleton-lazy.ts) \ No newline at end of file +[01.单例模式(懒汉)](./01-singleton-lazy.ts) + +## 创建型模式 + +- 单例模式: 分为饿汉模式和懒汉模式,饿汉先 +- 简单工厂模式(不属于 23 钟设计模式):通过 if、else 判断,简化了客户端。但是如果要添加新产品,需要修改工厂类代码。 +- 工厂方法模式:在简单工厂模式技术上添加抽象工厂和具体工厂,每个具体工厂创建一个具体产品,添加新的产品需要添加新的工厂,而不修改原来的代码。 +- 抽象工厂模式 + - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 + +- 建造者模式 +- 原型模式 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1c4e4f8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,109 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} From c512a9f3257e14ec1852a5af2691da97e6693fb8 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 14:47:53 +0800 Subject: [PATCH 04/47] =?UTF-8?q?feat(factory):=20=E5=B7=A5=E5=8E=82?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/02-factory.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js-advanced/design-pattern/02-factory.ts b/js-advanced/design-pattern/02-factory.ts index 9fe10c3..d797aef 100644 --- a/js-advanced/design-pattern/02-factory.ts +++ b/js-advanced/design-pattern/02-factory.ts @@ -40,9 +40,12 @@ function main(count: number) { } args.forEach((blockAndCount) => { - const factory = blockAndCount[0] === "Circle" ? new CircleFactory() : new SquareFactory(); - - for(let i = 0; i < blockAndCount[1]; i++) { + const factory = + blockAndCount[0] === "Circle" + ? new CircleFactory() + : new SquareFactory(); + + for (let i = 0; i < blockAndCount[1]; i++) { factory.createBlock().product(); } }); @@ -52,6 +55,6 @@ function main(count: number) { } // @ts-ignore -main(3)(['Circle', 1])(['Square', 2])(['Circle', 1]); +main(3)(["Circle", 1])(["Square", 2])(["Circle", 1]); export {}; From c81a966abc4721be8be5eee2b64cf7b3dd197f58 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 15:08:06 +0800 Subject: [PATCH 05/47] chore(create) --- js-advanced/design-pattern/README.md | 9 +++++++-- .../design-pattern/{ => create}/01-singleton-hunger.ts | 0 .../design-pattern/{ => create}/01-singleton-lazy.ts | 0 .../design-pattern/{ => create}/02-easy-factory.ts | 0 js-advanced/design-pattern/{ => create}/02-factory.ts | 0 .../design-pattern/{ => create}/03.abstract-factory.ts | 0 js-advanced/design-pattern/create/04-builder.ts | 0 7 files changed, 7 insertions(+), 2 deletions(-) rename js-advanced/design-pattern/{ => create}/01-singleton-hunger.ts (100%) rename js-advanced/design-pattern/{ => create}/01-singleton-lazy.ts (100%) rename js-advanced/design-pattern/{ => create}/02-easy-factory.ts (100%) rename js-advanced/design-pattern/{ => create}/02-factory.ts (100%) rename js-advanced/design-pattern/{ => create}/03.abstract-factory.ts (100%) create mode 100644 js-advanced/design-pattern/create/04-builder.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 617c259..5c70588 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -2,8 +2,8 @@ ## [参考文档](https://github.com/youngyangyang04/kama-DesignPattern) -[01.单例模式(饿汉)](./01-singleton-hunger.ts) -[01.单例模式(懒汉)](./01-singleton-lazy.ts) +[01.单例模式(饿汉)](./create/01-singleton-hunger.ts) +[01.单例模式(懒汉)](./create/01-singleton-lazy.ts) ## 创建型模式 @@ -13,5 +13,10 @@ - 抽象工厂模式 - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 + > 简单工厂、工厂方法、抽象工厂的区别 + >> 简单工厂模式:一个工厂方法创建所有具体产品 + >> 工厂方法模式:一个工厂方法创建一个具体产品 + >> 抽象工厂模式:一个工厂方法可以创建一类具体产品 + - 建造者模式 - 原型模式 diff --git a/js-advanced/design-pattern/01-singleton-hunger.ts b/js-advanced/design-pattern/create/01-singleton-hunger.ts similarity index 100% rename from js-advanced/design-pattern/01-singleton-hunger.ts rename to js-advanced/design-pattern/create/01-singleton-hunger.ts diff --git a/js-advanced/design-pattern/01-singleton-lazy.ts b/js-advanced/design-pattern/create/01-singleton-lazy.ts similarity index 100% rename from js-advanced/design-pattern/01-singleton-lazy.ts rename to js-advanced/design-pattern/create/01-singleton-lazy.ts diff --git a/js-advanced/design-pattern/02-easy-factory.ts b/js-advanced/design-pattern/create/02-easy-factory.ts similarity index 100% rename from js-advanced/design-pattern/02-easy-factory.ts rename to js-advanced/design-pattern/create/02-easy-factory.ts diff --git a/js-advanced/design-pattern/02-factory.ts b/js-advanced/design-pattern/create/02-factory.ts similarity index 100% rename from js-advanced/design-pattern/02-factory.ts rename to js-advanced/design-pattern/create/02-factory.ts diff --git a/js-advanced/design-pattern/03.abstract-factory.ts b/js-advanced/design-pattern/create/03.abstract-factory.ts similarity index 100% rename from js-advanced/design-pattern/03.abstract-factory.ts rename to js-advanced/design-pattern/create/03.abstract-factory.ts diff --git a/js-advanced/design-pattern/create/04-builder.ts b/js-advanced/design-pattern/create/04-builder.ts new file mode 100644 index 0000000..e69de29 From 96f6dd4154d06af7dc4b868ac2ac39854ceeceea Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 15:56:15 +0800 Subject: [PATCH 06/47] =?UTF-8?q?feat(builder):=20=E5=BB=BA=E9=80=A0?= =?UTF-8?q?=E8=80=85=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/create/04-builder.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/js-advanced/design-pattern/create/04-builder.ts b/js-advanced/design-pattern/create/04-builder.ts index e69de29..8d35aba 100644 --- a/js-advanced/design-pattern/create/04-builder.ts +++ b/js-advanced/design-pattern/create/04-builder.ts @@ -0,0 +1,80 @@ +// 小明家新开了一家自行车工厂,用于使用自行车配件(车架 frame 和车轮 tires )进行组装定制不同的自行车,包括山地车和公路车。 + +// 山地车使用的是Aluminum Frame(铝制车架)和 Knobby Tires(可抓地轮胎),公路车使用的是 Carbon Frame (碳车架)和 Slim Tries。 + +// 现在它收到了一笔订单,要求定制一批自行车,请你使用【建造者模式】告诉小明这笔订单需要使用那些自行车配置吧。 + +class Bicycle { + private frame = ""; + private tires = ""; + + setFrame(frame) { + this.frame = frame; + } + setTires(tires) { + this.tires = tires; + } + + toString() { + return this.frame + " " + this.tires; + } +} + +interface IBuilder { + buildFrame(): void; + buildTires(): void; + getResult(): Bicycle; +} + +class MountainBikeBuilder implements IBuilder { + private bicycle = new Bicycle(); + buildFrame(): void { + this.bicycle.setFrame("Aluminum Frame"); + } + + buildTires(): void { + this.bicycle.setTires("Knobby Tires"); + } + + getResult(): Bicycle { + return this.bicycle; + } +} +class RoadBikeBuilder implements IBuilder { + private bicycle = new Bicycle(); + buildFrame(): void { + this.bicycle.setFrame("Carbon Frame"); + } + + buildTires(): void { + this.bicycle.setTires("Slim Tries"); + } + + getResult(): Bicycle { + return this.bicycle; + } +} + +function main(count: number) { + function dfs(...args) { + if (args.length < count) { + return (...arg) => dfs(...args, ...arg); + } + + // todo + + args.forEach((bike) => { + const builder = + bike === "mountain" ? new MountainBikeBuilder() : new RoadBikeBuilder(); + builder.buildFrame(); + builder.buildTires(); + console.log(builder.getResult().toString()); + }); + } + return dfs; +} + +// @ts-ignore +main(3)("mountain")("road")("mountain"); + +export {}; From ffd248527fee5d6ca8d154e078dbadc2ca2fb435 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 18 Sep 2024 17:50:50 +0800 Subject: [PATCH 07/47] =?UTF-8?q?feat(prototype):=20=E5=8E=9F=E5=9E=8B?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 16 ++++--- .../create/03.abstract-factory.ts | 2 + .../design-pattern/create/05-prototype.ts | 43 +++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 js-advanced/design-pattern/create/05-prototype.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 5c70588..4d7489e 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -13,10 +13,16 @@ - 抽象工厂模式 - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 - > 简单工厂、工厂方法、抽象工厂的区别 - >> 简单工厂模式:一个工厂方法创建所有具体产品 - >> 工厂方法模式:一个工厂方法创建一个具体产品 - >> 抽象工厂模式:一个工厂方法可以创建一类具体产品 - - 建造者模式 - 原型模式 + +## 区别 + +- 简单工厂、工厂方法、抽象工厂的区别 + - 简单工厂模式:一个工厂方法创建所有具体产品 + - 工厂方法模式:一个工厂方法创建一个具体产品 + - 抽象工厂模式:一个工厂方法可以创建一类具体产品 + +- 抽象工厂模式 与 建造者模式的区别 + - 抽象工厂模式:适合创建一系列相关的对象,封装了对象创建的逻辑,便于扩展和管理不同的产品族。 + - 建造者模式:适合构建复杂对象,支持一步一步的构建过程,能灵活地处理不同的配置选项。 diff --git a/js-advanced/design-pattern/create/03.abstract-factory.ts b/js-advanced/design-pattern/create/03.abstract-factory.ts index 2896c20..0205c63 100644 --- a/js-advanced/design-pattern/create/03.abstract-factory.ts +++ b/js-advanced/design-pattern/create/03.abstract-factory.ts @@ -78,3 +78,5 @@ function main(count: number) { // @ts-ignore main(3)("modern")("classical")("modern"); + +export {} diff --git a/js-advanced/design-pattern/create/05-prototype.ts b/js-advanced/design-pattern/create/05-prototype.ts new file mode 100644 index 0000000..9a2115e --- /dev/null +++ b/js-advanced/design-pattern/create/05-prototype.ts @@ -0,0 +1,43 @@ +// 公司正在开发一个图形设计软件,其中有一个常用的图形元素是矩形。 +// 设计师在工作时可能需要频繁地创建相似的矩形,而这些矩形的基本属性是相同的(颜色、宽度、高度), +// 为了提高设计师的工作效率,请你使用原型模式设计一个矩形对象的原型。使用该原型可以快速克隆生成新的矩形对象。 + +interface Prototype { + getDetail(): string; + clone(): Prototype; +} + +class Rectangle implements Prototype { + color: string; + width: number; + height: number; + + constructor(color: string, width: number, height: number) { + this.color = color; + this.width = width; + this.height = height; + } + + // 按实际需要实现 深拷贝或浅拷贝 + clone(): Rectangle { + return new Rectangle(this.color, this.width, this.height); + } + + getDetail(): string { + return `color: ${this.color}, width: ${this.width}, height: ${this.height}`; + } +} + +function main(color: string, width: number, height: number) { + const rectangle = new Rectangle(color, width, height); + + return function cpNumber(count: number) { + for (let i = 0; i < count; i++) { + console.log(rectangle.clone().getDetail()); + } + }; +} + +main("Red", 10, 5)(3); + +export {} \ No newline at end of file From 5d1d43fa5b8c3e9484c33f9e862d122d9eda0c4e Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 19 Sep 2024 14:26:49 +0800 Subject: [PATCH 08/47] feat(a) --- js-advanced/design-pattern/README.md | 4 ++-- js-advanced/design-pattern/structural/01.adapter.ts | 0 js-advanced/design-pattern/structural/02.proxy.ts | 0 js-advanced/design-pattern/structural/03.bridge.ts | 0 js-advanced/design-pattern/structural/04.an.ts | 0 js-advanced/design-pattern/structural/05.faced.ts | 0 js-advanced/design-pattern/structural/06.compose.ts | 0 js-advanced/design-pattern/structural/07.share.ts | 0 8 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 js-advanced/design-pattern/structural/01.adapter.ts create mode 100644 js-advanced/design-pattern/structural/02.proxy.ts create mode 100644 js-advanced/design-pattern/structural/03.bridge.ts create mode 100644 js-advanced/design-pattern/structural/04.an.ts create mode 100644 js-advanced/design-pattern/structural/05.faced.ts create mode 100644 js-advanced/design-pattern/structural/06.compose.ts create mode 100644 js-advanced/design-pattern/structural/07.share.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 4d7489e..496a7e9 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -13,8 +13,8 @@ - 抽象工厂模式 - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 -- 建造者模式 -- 原型模式 +- 建造者模式: +- 原型模式: ## 区别 diff --git a/js-advanced/design-pattern/structural/01.adapter.ts b/js-advanced/design-pattern/structural/01.adapter.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/02.proxy.ts b/js-advanced/design-pattern/structural/02.proxy.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/03.bridge.ts b/js-advanced/design-pattern/structural/03.bridge.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/04.an.ts b/js-advanced/design-pattern/structural/04.an.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/05.faced.ts b/js-advanced/design-pattern/structural/05.faced.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/06.compose.ts b/js-advanced/design-pattern/structural/06.compose.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/structural/07.share.ts b/js-advanced/design-pattern/structural/07.share.ts new file mode 100644 index 0000000..e69de29 From f78b9d9b93c51bc3e103fe8b54e259463c00b14f Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 24 Sep 2024 11:16:21 +0800 Subject: [PATCH 09/47] feat(adapter) --- .../design-pattern/structural/01.adapter.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/js-advanced/design-pattern/structural/01.adapter.ts b/js-advanced/design-pattern/structural/01.adapter.ts index e69de29..237b1db 100644 --- a/js-advanced/design-pattern/structural/01.adapter.ts +++ b/js-advanced/design-pattern/structural/01.adapter.ts @@ -0,0 +1,55 @@ +// 小明购买了一台新电脑,该电脑使用 TypeC 接口, +// 他已经有了一个USB接口的充电器和数据线,为了确保新电脑可以使用现有的USB接口充电器和数据线,他购买了一个TypeC到USB的扩展坞。 +// 请你使用适配器模式设计并实现这个扩展坞系统,确保小明的新电脑既可以通过扩展坞使用现有的USB接口充电线和数据线,也可以使用TypeC接口充电。 + +interface IUSB { + usbCharge(): void; +} + +interface ITypeC { + typeCCharge(): void; +} + +class USB implements IUSB { + usbCharge(): void {} +} + +// 适配器类,TypeC 扩展坞适配 USB +class TypeCAdapter implements IUSB, ITypeC { + private usb: IUSB; + + constructor(usb: IUSB) { + this.usb = usb; + } + + usbCharge() { + console.log("USB Adapter"); + this.usb.usbCharge(); + } + + typeCCharge(): void { + console.log("TypeC"); + this.usb.usbCharge(); + } +} + +function main(count: number) { + const expand = new TypeCAdapter(new USB()); + + function dfs(...args) { + if (args.length < count) return (...arg) => dfs(...args, ...arg); + + args.forEach((item) => { + if (item === 1) { + expand.typeCCharge(); + } else { + expand.usbCharge(); + } + }); + } + + return dfs; +} + +// @ts-ignore +main(3)(1)(2)(1); From ac1ecdc9121e5a16f0f7a3693697afe0eb6c7a6f Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 24 Sep 2024 13:43:24 +0800 Subject: [PATCH 10/47] =?UTF-8?q?feat(proxy):=20=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 4 +++ .../design-pattern/structural/02.proxy.ts | 34 +++++++++++++++++++ js-advanced/design-pattern/utils.ts | 11 ++++++ 3 files changed, 49 insertions(+) create mode 100644 js-advanced/design-pattern/utils.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 496a7e9..bb903c7 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -26,3 +26,7 @@ - 抽象工厂模式 与 建造者模式的区别 - 抽象工厂模式:适合创建一系列相关的对象,封装了对象创建的逻辑,便于扩展和管理不同的产品族。 - 建造者模式:适合构建复杂对象,支持一步一步的构建过程,能灵活地处理不同的配置选项。 + +- 适配器模式和代理模式的区别 + - 适配器模式主要是让不能访问的能访问 + - 代理模式主要是限制访问,或在访问之前或之后做一些其他的事 diff --git a/js-advanced/design-pattern/structural/02.proxy.ts b/js-advanced/design-pattern/structural/02.proxy.ts index e69de29..e318f38 100644 --- a/js-advanced/design-pattern/structural/02.proxy.ts +++ b/js-advanced/design-pattern/structural/02.proxy.ts @@ -0,0 +1,34 @@ +// 小明想要购买一套房子,他决定寻求一家房屋中介来帮助他找到一个面积超过100平方米的房子, +// 只有符合条件的房子才会被传递给小明查看。 +import { entry } from "../utils"; + +interface IHouse { + sail(area: number): void; +} + +class RealHouse implements IHouse { + sail() { + console.log("Yes"); + } +} + +class MProxy implements IHouse { + private realHouse = new RealHouse(); + + sail(area: number) { + if (area < 100) { + console.log("NO"); + return; + } + + this.realHouse.sail(); + } +} + +// @ts-ignore +entry(3, (...args) => { + const proxy = new MProxy(); + args.forEach((item) => { + proxy.sail(item); + }); +})(120)(80)(110); diff --git a/js-advanced/design-pattern/utils.ts b/js-advanced/design-pattern/utils.ts new file mode 100644 index 0000000..1fe7490 --- /dev/null +++ b/js-advanced/design-pattern/utils.ts @@ -0,0 +1,11 @@ +export function entry(count: number, fn: (...args: any) => void) { + function dfs(...args) { + if (args.length < count) { + return (...arg) => dfs(...args, ...arg); + } + + fn(...args) + } + return dfs; + } + \ No newline at end of file From c777b5442932f2ed1791192cf55aec2df7b5c6d9 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 24 Sep 2024 14:42:02 +0800 Subject: [PATCH 11/47] =?UTF-8?q?feat(decorator):=20=E8=A3=85=E9=A5=B0?= =?UTF-8?q?=E5=99=A8=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/structural/04.an.ts | 0 .../design-pattern/structural/04.decorator.ts | 61 +++++++++++++++++++ js-advanced/design-pattern/utils.ts | 15 +++-- 3 files changed, 68 insertions(+), 8 deletions(-) delete mode 100644 js-advanced/design-pattern/structural/04.an.ts create mode 100644 js-advanced/design-pattern/structural/04.decorator.ts diff --git a/js-advanced/design-pattern/structural/04.an.ts b/js-advanced/design-pattern/structural/04.an.ts deleted file mode 100644 index e69de29..0000000 diff --git a/js-advanced/design-pattern/structural/04.decorator.ts b/js-advanced/design-pattern/structural/04.decorator.ts new file mode 100644 index 0000000..5a1e198 --- /dev/null +++ b/js-advanced/design-pattern/structural/04.decorator.ts @@ -0,0 +1,61 @@ +// 小明喜欢品尝不同口味的咖啡,他发现每种咖啡都可以加入不同的调料,比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。 +// 请设计一个简单的咖啡制作系统,使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型:黑咖啡(Black Coffee)和拿铁(Latte)。 + +import { entry } from "../utils"; + +interface ICoffee { + cOperation(): void; +} + +interface IDecorator { + dOperation(): void; +} + +class BlackCoffee implements ICoffee { + cOperation(): void { + console.log("Black Coffee"); + } +} + +class LatteCoffee implements ICoffee { + cOperation(): void { + console.log("Latte"); + } +} + +abstract class Decorator implements ICoffee { + protected coffee: ICoffee; + constructor(coffee: ICoffee) { + this.coffee = coffee; + } + + cOperation(): void { + this.coffee.cOperation(); + } +} + +class MilkCoffee extends Decorator { + dOperation(): void { + super.cOperation(); + console.log("adding Milk"); + } +} + +class SugarCoffee extends Decorator { + dOperation(): void { + super.cOperation(); + console.log("adding Sugar"); + } +} + +// @ts-ignore +entry(2, (...args) => { + let coffee: ICoffee; + let decorator: IDecorator; + + args.forEach((item) => { + coffee = item[0] === 1 ? new BlackCoffee() : new LatteCoffee(); + decorator = item[1] === 1 ? new MilkCoffee(coffee) : new SugarCoffee(coffee); + decorator.dOperation(); + }); +})([1, 1])([2, 2]); diff --git a/js-advanced/design-pattern/utils.ts b/js-advanced/design-pattern/utils.ts index 1fe7490..5f6495f 100644 --- a/js-advanced/design-pattern/utils.ts +++ b/js-advanced/design-pattern/utils.ts @@ -1,11 +1,10 @@ export function entry(count: number, fn: (...args: any) => void) { - function dfs(...args) { - if (args.length < count) { - return (...arg) => dfs(...args, ...arg); - } - - fn(...args) + function dfs(...args) { + if (args.length < count) { + return (arg) => dfs(...args, arg); } - return dfs; + + fn(...args); } - \ No newline at end of file + return dfs; +} From f4f3ad700c28a6ffa1b3a73970b9778e18a9481a Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 24 Sep 2024 15:06:01 +0800 Subject: [PATCH 12/47] =?UTF-8?q?feat(facade):=20=E9=97=A8=E9=9D=A2?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 4 ++ .../design-pattern/structural/05.facade.ts | 56 +++++++++++++++++++ .../design-pattern/structural/05.faced.ts | 0 3 files changed, 60 insertions(+) create mode 100644 js-advanced/design-pattern/structural/05.facade.ts delete mode 100644 js-advanced/design-pattern/structural/05.faced.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index bb903c7..507ca36 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -30,3 +30,7 @@ - 适配器模式和代理模式的区别 - 适配器模式主要是让不能访问的能访问 - 代理模式主要是限制访问,或在访问之前或之后做一些其他的事 + +## 注意点 + +- [装饰器模式的 抽象类的使用](./structural/04.decorator.ts) diff --git a/js-advanced/design-pattern/structural/05.facade.ts b/js-advanced/design-pattern/structural/05.facade.ts new file mode 100644 index 0000000..fee9e9c --- /dev/null +++ b/js-advanced/design-pattern/structural/05.facade.ts @@ -0,0 +1,56 @@ +// 小明家的电源总开关控制了家里的三个设备:空调、台灯和电视机。 +// 每个设备都有独立的开关密码,分别用数字1、2和3表示。即输入1时,空调关闭,输入2时,台灯关闭,输入3时,电视机关闭,当输入为4时,表示要关闭所有设备。 +// 请你使用外观模式编写程序来描述电源总开关的操作。 + +import { entry } from "../utils"; + +class AirCondition { + turnOff() { + console.log("Air Conditioner is turned off."); + } +} + +class DeskLamp { + turnOff() { + console.log("Desk Lamp is turned off."); + } +} + +class Television { + turnOff() { + console.log("Television is turned off."); + } +} + +class DeviceFacade { + private airCondition = new AirCondition(); + private deskLamp = new DeskLamp(); + private television = new Television(); + + turnOff(count: number) { + switch (count) { + case 1: + this.airCondition.turnOff(); + break; + case 2: + this.deskLamp.turnOff(); + break; + case 3: + this.television.turnOff(); + break; + case 4: + console.log("All devices are off."); + break; + default: + console.log("Invalid device code"); + } + } +} + +// @ts-ignore +entry(4, (...args) => { + const deviceFacade = new DeviceFacade(); + args.forEach((item) => { + deviceFacade.turnOff(item); + }); +})(1)(2)(3)(4); diff --git a/js-advanced/design-pattern/structural/05.faced.ts b/js-advanced/design-pattern/structural/05.faced.ts deleted file mode 100644 index e69de29..0000000 From c12ad60c1398b6bd13227a3be872a7637e2825d6 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 25 Sep 2024 14:29:30 +0800 Subject: [PATCH 13/47] =?UTF-8?q?feat(bridge):=20=E6=A1=A5=E6=8E=A5?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 1 + .../design-pattern/structural/03.bridge.ts | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 507ca36..6c6b533 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -34,3 +34,4 @@ ## 注意点 - [装饰器模式的 抽象类的使用](./structural/04.decorator.ts) +- [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? diff --git a/js-advanced/design-pattern/structural/03.bridge.ts b/js-advanced/design-pattern/structural/03.bridge.ts index e69de29..3d36c8d 100644 --- a/js-advanced/design-pattern/structural/03.bridge.ts +++ b/js-advanced/design-pattern/structural/03.bridge.ts @@ -0,0 +1,89 @@ +// 小明家有一个万能遥控器,能够支持多个品牌的电视。每个电视可以执行开机、关机和切换频道的操作,请你使用桥接模式模拟这个操作。 + +import { entry } from "../utils"; + +// 0 表示创建 Sony 品牌的电视,1 表示创建 TCL 品牌的遥控和电视;2 表示开启电视、3表示关闭电视,4表示切换频道。 + +// Implementor +interface ITV { + turnOn(): void; + turnOff(): void; + changeChannel(): void; +} + +// ConcreteImplementor +class SonyTV implements ITV { + turnOn() { + console.log(`Sony TV is ON`); + } + turnOff() { + console.log(`Sony TV is OFF`); + } + changeChannel() { + console.log(`Switching Sony TV channel`); + } +} + +class TCL_TV implements ITV { + turnOn() { + console.log(`TCL TV is ON`); + } + turnOff() { + console.log(`TCL TV is OFF`); + } + changeChannel() { + console.log(`Switching TCL TV channel`); + } +} + +// Abstraction 维护一个对实现的引用 +abstract class Control { + protected tv: ITV; + constructor(tv: ITV) { + this.tv = tv; + } + + abstract operation(): void; +} + +// 修正抽象 RefinedAbstraction +class PowerOperation extends Control { + operation(): void { + this.tv.turnOn(); + } +} + +class OffOperation extends Control { + operation(): void { + this.tv.turnOff(); + } +} + +class ChannelSwitchOperation extends Control { + operation(): void { + this.tv.changeChannel(); + } +} + +// @ts-ignore +entry(6, (...args) => { + let tv: ITV; + args.forEach((item) => { + tv = item[0] === 0 ? new SonyTV() : new TCL_TV(); + + const action = item[1]; + switch (action) { + case 2: + new PowerOperation(tv).operation(); + break; + case 3: + new OffOperation(tv).operation(); + break; + case 4: + new ChannelSwitchOperation(tv).operation(); + break; + default: + console.log("invalid action"); + } + }); +})([0, 2])([1, 2])([0, 4])([0, 3])([1, 4])([1, 3]); From 0914c2a9ba459a3d790fcb3a8b50d73ebcfa0dac Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 25 Sep 2024 14:54:33 +0800 Subject: [PATCH 14/47] doc --- js-advanced/design-pattern/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 6c6b533..51e23f9 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -33,5 +33,7 @@ ## 注意点 -- [装饰器模式的 抽象类的使用](./structural/04.decorator.ts) -- [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? +- [装饰器模式](./structural/04.decorator.ts)的抽象类的使用 +- [x] [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? + - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 + - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了 From 612ca5276008417f019344990db2b6c97d655479 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 25 Sep 2024 14:57:34 +0800 Subject: [PATCH 15/47] doc --- js-advanced/design-pattern/README.md | 32 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 51e23f9..f937d83 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -7,14 +7,34 @@ ## 创建型模式 -- 单例模式: 分为饿汉模式和懒汉模式,饿汉先 +- 单例模式(Singleton): 分为饿汉模式和懒汉模式,饿汉先 - 简单工厂模式(不属于 23 钟设计模式):通过 if、else 判断,简化了客户端。但是如果要添加新产品,需要修改工厂类代码。 -- 工厂方法模式:在简单工厂模式技术上添加抽象工厂和具体工厂,每个具体工厂创建一个具体产品,添加新的产品需要添加新的工厂,而不修改原来的代码。 -- 抽象工厂模式 +- 工厂方法模式(factory Method):在简单工厂模式技术上添加抽象工厂和具体工厂,每个具体工厂创建一个具体产品,添加新的产品需要添加新的工厂,而不修改原来的代码。 +- 抽象工厂模式(Abstract Factory) - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 - -- 建造者模式: -- 原型模式: +- 建造者模式:(Builder) +- 原型模式:Prototype) + +## 结构型 + +- 适配器模式(Adapter) +- 桥接模式(Bridge) +- 组合模式(Composite) +- 装饰者模式(Decorator) +- 外观模式(Facade) +- 享元模式(Flyweight) +- 代理模式(Proxy) + +## 行为型 + +- 观察者模式(Observer) +- 策略模式(Strategy) +- 命令模式(Command) +- 状态模式(State) +- 责任链模式(Chain of Responsibility) +- 迭代器模式(Iterator) +- 访问者模式(Visitor) +- 中介者模式(Mediator) ## 区别 From e2586c7da806d326bde3abc2140f564eeba8476e Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 25 Sep 2024 15:46:56 +0800 Subject: [PATCH 16/47] doc --- js-advanced/design-pattern/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index f937d83..1e7c71b 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -18,8 +18,8 @@ ## 结构型 - 适配器模式(Adapter) -- 桥接模式(Bridge) -- 组合模式(Composite) +- 桥接模式(Bridge): 适合笛卡尔积的组合 +- 组合模式(Composite): 组合模式适用于任何需要构建具有部分-整体层次结构的场景,比如组织架构管理、文件系统的文件和文件夹组织等。 - 装饰者模式(Decorator) - 外观模式(Facade) - 享元模式(Flyweight) @@ -56,4 +56,4 @@ - [装饰器模式](./structural/04.decorator.ts)的抽象类的使用 - [x] [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 - - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了 + - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了。如:热的小杯奶茶、热的大杯奶茶、凉的小杯奶茶、凉的大杯奶茶。 From e081de37cde22ec49d24bca049ac59bdf2a2580a Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 25 Sep 2024 17:08:08 +0800 Subject: [PATCH 17/47] =?UTF-8?q?feat(compose):=20=E7=BB=84=E5=90=88?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/structural/06.compose.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/js-advanced/design-pattern/structural/06.compose.ts b/js-advanced/design-pattern/structural/06.compose.ts index e69de29..3f3424b 100644 --- a/js-advanced/design-pattern/structural/06.compose.ts +++ b/js-advanced/design-pattern/structural/06.compose.ts @@ -0,0 +1,86 @@ +// 小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。 +// 请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。 + +import { entry } from "../utils"; + +// 每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。 + +interface IComponent { + name: string; + display(dept: number): void; +} + +class Employer implements IComponent { + name: string; + + constructor(name: string) { + this.name = name; + } + + display(dept: number): void { + const indent = " ".repeat(dept * 4); + console.log(`${indent} ${this.name}`); + } +} + +class Department implements IComponent { + name: string; + private _children: IComponent[]; + + constructor(name: string) { + this.name = name; + this._children = []; + } + + add(child: IComponent) { + this._children.push(child); + } + + remove(child: IComponent) { + this._children = this._children.filter((item) => item.name !== child.name); + } + + display(dept: number): void { + const indent = " ".repeat(dept * 4); + console.log(`${indent} ${this.name}`); + + this._children.forEach((child) => { + child.display(dept + 1); + }); + } +} + +class Company { + private _department: Department; + + constructor(name: string) { + this._department = new Department(name); + } + + add(dept: Department) { + this._department.add(dept); + } + + display() { + this._department.display(1); + } +} + +// @ts-ignore +entry(8, (...args) => { + const company = new Company("MyCompany"); + let dept: Department; + args.forEach((item) => { + if (item[0] === "D") { + dept = new Department(item[1]); + company.add(dept); + } else { + dept.add(new Employer(item[1])); + } + }); + + company.display(); +})(["D", "HR"])(["E", "HRManager"])(["D", "Finance"])(["E", "AccountantA"])([ + "E", + "AccountantB", +])(["D", "IT"])(["E", "DeveloperA"])(["E", "DeveloperB"]); From 61a951a56b09a33f47110aa95e096b08e2c1a03f Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 26 Sep 2024 20:35:28 +0800 Subject: [PATCH 18/47] =?UTF-8?q?feat(flyWeight):=20=E4=BA=AB=E5=85=83?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 1 + .../design-pattern/structural/07.flyWeight.ts | 66 +++++++++++++++++++ .../design-pattern/structural/07.share.ts | 0 3 files changed, 67 insertions(+) create mode 100644 js-advanced/design-pattern/structural/07.flyWeight.ts delete mode 100644 js-advanced/design-pattern/structural/07.share.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 1e7c71b..9b6503d 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -57,3 +57,4 @@ - [x] [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了。如:热的小杯奶茶、热的大杯奶茶、凉的小杯奶茶、凉的大杯奶茶。 +- [ ] [享元模式](./structural/07.flyWeight.ts) 案例不好,理解的不行,需要一个更好的案例 diff --git a/js-advanced/design-pattern/structural/07.flyWeight.ts b/js-advanced/design-pattern/structural/07.flyWeight.ts new file mode 100644 index 0000000..8923ea2 --- /dev/null +++ b/js-advanced/design-pattern/structural/07.flyWeight.ts @@ -0,0 +1,66 @@ +// 在一个图形编辑器中,用户可以绘制不同类型的图形,包括圆形(CIRCLE)、矩形(RECTANGLE)、三角形(TRIANGLE)等。现在,请你实现一个图形绘制程序,要求能够共享相同类型的图形对象,以减少内存占用。 + +import { entry } from "../utils"; + +interface TPos { + x: number; + y: number; +} + +type TShapeName = "CIRCLE" | "RECTANGLE" | "TRIANGLE"; + +interface IShape { + draw(pos: TPos): void; +} + +class CIRCLE implements IShape { + draw({ x, y }: TPos): void { + console.log(`(${x}, ${y})`); + } +} +class RECTANGLE implements IShape { + draw({ x, y }: TPos): void { + console.log(`(${x}, ${y})`); + } +} +class TRIANGLE implements IShape { + draw({ x, y }: TPos): void { + console.log(`(${x}, ${y})`); + } +} + +class GEditor { + shapeMap = new Map(); + + getShape(name: TShapeName) { + let shape: IShape; + if (!this.shapeMap.has(name)) { + switch (name) { + case "CIRCLE": + shape = new CIRCLE(); + break; + case "RECTANGLE": + shape = new RECTANGLE(); + break; + case "TRIANGLE": + shape = new TRIANGLE(); + break; + } + console.log(`${name} drawn at `); + this.shapeMap.set(name, shape); + } else { + console.log(`${name} shared at `); + shape = this.shapeMap.get(name)!; + } + return shape; + } +} + + +// @ts-ignore +entry(6, (...args) => { + const editor = new GEditor(); + args.forEach(([name, x, y]) => { + editor.getShape(name).draw({ x, y }); + }); +})(['CIRCLE', 10, 20])(['RECTANGLE', 30, 40])(['CIRCLE', 15, 25])(['TRIANGLE', 5, 15])(['CIRCLE', 10, 20])(['RECTANGLE', 30, 40]); diff --git a/js-advanced/design-pattern/structural/07.share.ts b/js-advanced/design-pattern/structural/07.share.ts deleted file mode 100644 index e69de29..0000000 From 64f74d0caf5bd133d59a0c6a7fcedcd873cadb1e Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 26 Sep 2024 20:48:28 +0800 Subject: [PATCH 19/47] doc --- js-advanced/design-pattern/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 9b6503d..5ef61f7 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -57,4 +57,4 @@ - [x] [桥接模式](./structural/03.bridge.ts) : 有点难理解,感觉还是太散了,需要在客户端组合。目的是什么?就是方便组装?使用场景呢? - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了。如:热的小杯奶茶、热的大杯奶茶、凉的小杯奶茶、凉的大杯奶茶。 -- [ ] [享元模式](./structural/07.flyWeight.ts) 案例不好,理解的不行,需要一个更好的案例 +- [ ] [享元模式](./structural/07.flyWeight.ts) 案例不好,理解的不行,需要一个更好的案例。案例 (围棋 内部状态 颜色、外部状态 坐标)。 From d7fadd094d9eaf7fcfefd626286021772bf5c4c7 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 27 Sep 2024 21:31:53 +0800 Subject: [PATCH 20/47] feat(dir) --- js-advanced/design-pattern/README.md | 8 +++++--- js-advanced/design-pattern/behavioral/1.observer.ts | 0 js-advanced/design-pattern/behavioral/10.visitor.ts | 1 + js-advanced/design-pattern/behavioral/2.strategy.ts | 0 js-advanced/design-pattern/behavioral/3.command.ts | 0 js-advanced/design-pattern/behavioral/4.mediator.ts | 0 js-advanced/design-pattern/behavioral/5.memento.ts | 0 .../design-pattern/behavioral/6.template-method.ts | 0 js-advanced/design-pattern/behavioral/7.iterator.ts | 0 .../behavioral/8.chain-of-responsibility.ts | 0 js-advanced/design-pattern/behavioral/9.interpreter.ts | 0 11 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 js-advanced/design-pattern/behavioral/1.observer.ts create mode 100644 js-advanced/design-pattern/behavioral/10.visitor.ts create mode 100644 js-advanced/design-pattern/behavioral/2.strategy.ts create mode 100644 js-advanced/design-pattern/behavioral/3.command.ts create mode 100644 js-advanced/design-pattern/behavioral/4.mediator.ts create mode 100644 js-advanced/design-pattern/behavioral/5.memento.ts create mode 100644 js-advanced/design-pattern/behavioral/6.template-method.ts create mode 100644 js-advanced/design-pattern/behavioral/7.iterator.ts create mode 100644 js-advanced/design-pattern/behavioral/8.chain-of-responsibility.ts create mode 100644 js-advanced/design-pattern/behavioral/9.interpreter.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 5ef61f7..4a6f74c 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -30,11 +30,13 @@ - 观察者模式(Observer) - 策略模式(Strategy) - 命令模式(Command) -- 状态模式(State) -- 责任链模式(Chain of Responsibility) +- 中介者模式(Mediator) +- 备忘录模式 (Memento) +- 模板方法模式(Template Method) - 迭代器模式(Iterator) +- 责任链模式(Chain of Responsibility) +- 解释器模式(Interpreter) - 访问者模式(Visitor) -- 中介者模式(Mediator) ## 区别 diff --git a/js-advanced/design-pattern/behavioral/1.observer.ts b/js-advanced/design-pattern/behavioral/1.observer.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/10.visitor.ts b/js-advanced/design-pattern/behavioral/10.visitor.ts new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/10.visitor.ts @@ -0,0 +1 @@ + diff --git a/js-advanced/design-pattern/behavioral/2.strategy.ts b/js-advanced/design-pattern/behavioral/2.strategy.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/3.command.ts b/js-advanced/design-pattern/behavioral/3.command.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/4.mediator.ts b/js-advanced/design-pattern/behavioral/4.mediator.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/5.memento.ts b/js-advanced/design-pattern/behavioral/5.memento.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/6.template-method.ts b/js-advanced/design-pattern/behavioral/6.template-method.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/7.iterator.ts b/js-advanced/design-pattern/behavioral/7.iterator.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/8.chain-of-responsibility.ts b/js-advanced/design-pattern/behavioral/8.chain-of-responsibility.ts new file mode 100644 index 0000000..e69de29 diff --git a/js-advanced/design-pattern/behavioral/9.interpreter.ts b/js-advanced/design-pattern/behavioral/9.interpreter.ts new file mode 100644 index 0000000..e69de29 From 168c87cb45138b149610e6a871bb6b0668d5aee9 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 27 Sep 2024 22:17:58 +0800 Subject: [PATCH 21/47] =?UTF-8?q?feat(observer):=20=E8=A7=82=E5=AF=9F?= =?UTF-8?q?=E8=80=85=E6=A8=A1=E5=BC=8F=EF=BC=88=E5=8F=91=E5=B8=83=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E6=A8=A1=E5=BC=8F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/1.observer.ts | 60 +++++++++++++++++++ js-advanced/design-pattern/utils.ts | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/behavioral/1.observer.ts b/js-advanced/design-pattern/behavioral/1.observer.ts index e69de29..101fa51 100644 --- a/js-advanced/design-pattern/behavioral/1.observer.ts +++ b/js-advanced/design-pattern/behavioral/1.observer.ts @@ -0,0 +1,60 @@ +// 小明所在的学校有一个时钟(主题),每到整点时,它就会通知所有的学生(观察者)当前的时间,请你使用观察者模式实现这个时钟通知系统。 +// 注意点:时间从 0 开始,并每隔一个小时更新一次。 + +import { entry } from "../utils"; + +interface ISubject { + add(observer: Student): void; + remove(observer: Student): void; + notify(msg: string): void; +} + +interface IObserver { + update(msg: string): void; +} + +class Clock implements ISubject { + private observers: Map; + + constructor() { + this.observers = new Map(); + } + + add(observer: Student) { + this.observers.set(observer.name, observer); + } + + remove(observer: Student) { + this.observers.delete(observer.name); + } + + notify(msg: string) { + this.observers.forEach((item) => { + item.update(msg); + }); + } +} + +class Student implements IObserver { + name: string; + constructor(name: string) { + this.name = name; + } + update(msg: string) { + console.log(`${this.name} ${msg}`); + } +} + +// @ts-ignore +entry(2, (...args) => { + return (time: number) => { + const timeSubject = new Clock(); + args.forEach((item) => { + timeSubject.add(new Student(item)); + }); + + for (let i = 1; i <= time; i++) { + timeSubject.notify(i.toString()); + } + }; +})("Alice")("Bob")(3); diff --git a/js-advanced/design-pattern/utils.ts b/js-advanced/design-pattern/utils.ts index 5f6495f..be10520 100644 --- a/js-advanced/design-pattern/utils.ts +++ b/js-advanced/design-pattern/utils.ts @@ -4,7 +4,7 @@ export function entry(count: number, fn: (...args: any) => void) { return (arg) => dfs(...args, arg); } - fn(...args); + return fn(...args); } return dfs; } From a4d2b2cb0be7d7657e3e98cd8afa6ee0436cc4c8 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 30 Sep 2024 13:53:58 +0800 Subject: [PATCH 22/47] feat(doc) --- js-advanced/design-pattern/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 4a6f74c..35723e2 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -60,3 +60,7 @@ - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了。如:热的小杯奶茶、热的大杯奶茶、凉的小杯奶茶、凉的大杯奶茶。 - [ ] [享元模式](./structural/07.flyWeight.ts) 案例不好,理解的不行,需要一个更好的案例。案例 (围棋 内部状态 颜色、外部状态 坐标)。 + +## 实战点 + +- [ ] [享源模式, studio 的 block 拖动实力化问题](./structural/07.flyWeight.ts) From 99aa48d2a912246db124592801bbffd0d218ae24 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 30 Sep 2024 14:07:42 +0800 Subject: [PATCH 23/47] =?UTF-8?q?fix(observer):=20type=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/1.observer.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/1.observer.ts b/js-advanced/design-pattern/behavioral/1.observer.ts index 101fa51..58a3e22 100644 --- a/js-advanced/design-pattern/behavioral/1.observer.ts +++ b/js-advanced/design-pattern/behavioral/1.observer.ts @@ -4,8 +4,8 @@ import { entry } from "../utils"; interface ISubject { - add(observer: Student): void; - remove(observer: Student): void; + add(observer: IObserver): void; + remove(observer: IObserver): void; notify(msg: string): void; } @@ -14,18 +14,18 @@ interface IObserver { } class Clock implements ISubject { - private observers: Map; + private observers: IObserver[] constructor() { - this.observers = new Map(); + this.observers = []; } - add(observer: Student) { - this.observers.set(observer.name, observer); + add(observer: IObserver) { + this.observers.push(observer); } - remove(observer: Student) { - this.observers.delete(observer.name); + remove(observer: IObserver) { + this.observers = this.observers.filter((item) => item!== observer); } notify(msg: string) { From e736a1562fe76926a1c88d3dabeed13acb5a136b Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 10 Oct 2024 19:12:17 +0800 Subject: [PATCH 24/47] =?UTF-8?q?feat(strategy):=20=E7=AD=96=E7=95=A5?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=20done?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 4 +- .../design-pattern/behavioral/2.strategy.ts | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 35723e2..03bdf1e 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -8,7 +8,7 @@ ## 创建型模式 - 单例模式(Singleton): 分为饿汉模式和懒汉模式,饿汉先 -- 简单工厂模式(不属于 23 钟设计模式):通过 if、else 判断,简化了客户端。但是如果要添加新产品,需要修改工厂类代码。 +- 简单工厂模式(不属于 23 钟设计模式):通过 if、else 或 switch 判断,简化了客户端。但是如果要添加新产品,需要修改工厂类代码。 - 工厂方法模式(factory Method):在简单工厂模式技术上添加抽象工厂和具体工厂,每个具体工厂创建一个具体产品,添加新的产品需要添加新的工厂,而不修改原来的代码。 - 抽象工厂模式(Abstract Factory) - 在工厂方法模式基础上,每个工厂可以生产一系列相关的产品。 @@ -29,6 +29,8 @@ - 观察者模式(Observer) - 策略模式(Strategy) + - 把不需要外部清楚的细节尽可能封装起来(需要区分if 写在里面还是外面的辨别点。就是外部是否需要请求该细节) + - 往往需要结合 简单工厂模式 简化客户端操作 - 命令模式(Command) - 中介者模式(Mediator) - 备忘录模式 (Memento) diff --git a/js-advanced/design-pattern/behavioral/2.strategy.ts b/js-advanced/design-pattern/behavioral/2.strategy.ts index e69de29..6eadd7c 100644 --- a/js-advanced/design-pattern/behavioral/2.strategy.ts +++ b/js-advanced/design-pattern/behavioral/2.strategy.ts @@ -0,0 +1,62 @@ +// 小明家的超市推出了不同的购物优惠策略,你可以根据自己的需求选择不同的优惠方式。其中,有两种主要的优惠策略: +// 1. 九折优惠策略:原价的90%。 +// 2. 满减优惠策略:购物满一定金额时,可以享受相应的减免优惠。 +// 具体的满减规则如下: +// 满100元减5元 +// 满150元减15元 +// 满200元减25元 +// 满300元减40元 +// 请你设计一个购物优惠系统,用户输入商品的原价和选择的优惠策略编号,系统输出计算后的价格。 + +import { entry } from "../utils"; + +interface DiscountStrategy { + applyDiscount(price: number): void; +} + +class NinePercentDiscount implements DiscountStrategy { + applyDiscount(price) { + console.log(price * 0.9); + } +} + +class FullDiscount implements DiscountStrategy { + private priceMap = { + 100: 5, + 150: 15, + 200: 25, + 300: 40, + }; + + applyDiscount(price) { + console.log(price - this.priceMap[price]); + } +} + +class Shopping { + private discountStrategy: DiscountStrategy; + + constructor(way) { + switch (way) { + case 1: + this.discountStrategy = new NinePercentDiscount(); + break; + case 2: + this.discountStrategy = new FullDiscount(); + break; + default: + throw "1 or 2"; + } + } + + discount(price) { + this.discountStrategy.applyDiscount(price); + } +} + +// @ts-ignore +entry(4, (...args) => { + args.forEach(([price, way]) => { + new Shopping(way).discount(price); + }); +})([100, 1])([200, 2])([300, 1])([300, 2]); From befd89d03b22c1f72620f7a12baa07efb4c0ae0b Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 10 Oct 2024 19:22:44 +0800 Subject: [PATCH 25/47] =?UTF-8?q?chore(strategy):=20=E7=AD=96=E7=95=A5?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=20done?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/2.strategy.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/2.strategy.ts b/js-advanced/design-pattern/behavioral/2.strategy.ts index 6eadd7c..da10aed 100644 --- a/js-advanced/design-pattern/behavioral/2.strategy.ts +++ b/js-advanced/design-pattern/behavioral/2.strategy.ts @@ -10,17 +10,17 @@ import { entry } from "../utils"; -interface DiscountStrategy { - applyDiscount(price: number): void; +interface Strategy { + algorithm(price: number): void; } -class NinePercentDiscount implements DiscountStrategy { - applyDiscount(price) { +class NinePercentDiscount implements Strategy { + algorithm(price) { console.log(price * 0.9); } } -class FullDiscount implements DiscountStrategy { +class FullDiscount implements Strategy { private priceMap = { 100: 5, 150: 15, @@ -28,13 +28,13 @@ class FullDiscount implements DiscountStrategy { 300: 40, }; - applyDiscount(price) { + algorithm(price) { console.log(price - this.priceMap[price]); } } -class Shopping { - private discountStrategy: DiscountStrategy; +class StrategyContext { + private discountStrategy: Strategy; constructor(way) { switch (way) { @@ -50,13 +50,13 @@ class Shopping { } discount(price) { - this.discountStrategy.applyDiscount(price); + this.discountStrategy.algorithm(price); } } // @ts-ignore entry(4, (...args) => { args.forEach(([price, way]) => { - new Shopping(way).discount(price); + new StrategyContext(way).discount(price); }); })([100, 1])([200, 2])([300, 1])([300, 2]); From 32e59577957f2c726c06df4af3f608a7ae8b8613 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 11 Oct 2024 13:31:16 +0800 Subject: [PATCH 26/47] doc --- js-advanced/design-pattern/README.md | 44 +++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 03bdf1e..a96e53a 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -1,6 +1,9 @@ # 设计模式案例实现 -## [参考文档](https://github.com/youngyangyang04/kama-DesignPattern) +## 参考文档 + +- [卡码网设计模式精讲](https://github.com/youngyangyang04/kama-DesignPattern) +- [UML一一 类图关系 (泛化、实现、依赖、关联、聚合、组合)](https://blog.csdn.net/m0_37989980/article/details/104470064) [01.单例模式(饿汉)](./create/01-singleton-hunger.ts) [01.单例模式(懒汉)](./create/01-singleton-lazy.ts) @@ -66,3 +69,42 @@ ## 实战点 - [ ] [享源模式, studio 的 block 拖动实力化问题](./structural/07.flyWeight.ts) + +## 类关系 + +### 关联和依赖的区别 + +#### 关联:长实线加箭头 + +- 定义:关联表示两个类之间的长期关系,通常是拥有关系或引用关系。一个类的对象可以通过关联关系访问另一个类的对象。 +- 持续性:关联通常是持久的,也就是说,一个对象在其生命周期中会持续引用另一个对象。 +- 双向或单向:关联可以是双向的或单向的。双向关联表示两个对象可以互相访问,而单向关联则表示只有一个对象可以访问另一个对象。 +- 例子:教师和学生之间的关系。一个教师对象可能包含多个学生对象,而学生对象也可能引用该教师对象(双向关联)。 + + ``` java + class Teacher { + List students; + + } + + class Student { + Teacher teacher; + } + ``` + +#### 依赖:长虚线加箭头 + +- 定义:依赖表示一个类**临时性**地使用或需要另一个类的对象,通常是在某个方法或某个功能的执行过程中,短期地依赖该对象。依赖是一种更松散的关系。 +- 短暂性:依赖关系通常是瞬时的,一个类只是在某个方法或操作中需要另一个类的帮助,执行完该操作后,依赖就结束了。 +- 例子:司机依赖车来驾驶,但并不一定永久拥有某一辆车。依赖只存在于司机开车的时刻。 + +``` java + +class Driver { + void drive(Car car) { + // 司机在需要驾驶的时候依赖车 + car.start(); + } +} + +``` From a125f3ec34206db15b8e101adf2471c3352f7816 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 11 Oct 2024 13:32:18 +0800 Subject: [PATCH 27/47] doc --- js-advanced/design-pattern/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index a96e53a..53af064 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -76,7 +76,7 @@ #### 关联:长实线加箭头 -- 定义:关联表示两个类之间的长期关系,通常是拥有关系或引用关系。一个类的对象可以通过关联关系访问另一个类的对象。 +- 定义:关联表示两个类之间的长期关系,通常是**拥有关系**或**引用关系**。一个类的对象可以通过关联关系访问另一个类的对象。 - 持续性:关联通常是持久的,也就是说,一个对象在其生命周期中会持续引用另一个对象。 - 双向或单向:关联可以是双向的或单向的。双向关联表示两个对象可以互相访问,而单向关联则表示只有一个对象可以访问另一个对象。 - 例子:教师和学生之间的关系。一个教师对象可能包含多个学生对象,而学生对象也可能引用该教师对象(双向关联)。 From e2752eee428e724d845e2f89d26d609778361881 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 11 Oct 2024 19:40:54 +0800 Subject: [PATCH 28/47] feat(command):pro --- js-advanced/design-pattern/README.md | 111 ++++++++++++++++++ .../behavioral/3.command-pro.ts | 50 ++++++++ .../design-pattern/behavioral/3.command.ts | 50 ++++++++ 3 files changed, 211 insertions(+) create mode 100644 js-advanced/design-pattern/behavioral/3.command-pro.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 53af064..91d9af0 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -35,6 +35,8 @@ - 把不需要外部清楚的细节尽可能封装起来(需要区分if 写在里面还是外面的辨别点。就是外部是否需要请求该细节) - 往往需要结合 简单工厂模式 简化客户端操作 - 命令模式(Command) + - 需求对 “行为请求者” 与 ”行为实现者“ 进行松耦合 + - Invoker(服务员)、Receiver(烤肉师傅)、OrderCommand(烤羊肉)、xxxCommand(烤xxx肉) - 中介者模式(Mediator) - 备忘录模式 (Memento) - 模板方法模式(Template Method) @@ -108,3 +110,112 @@ class Driver { } ``` + +### 组合和聚合 + +#### 组合:长实线加实心菱形 + +``` java +// 轮子类,依赖于 Car +class Wheel { + private String position; + + public Wheel(String position) { + this.position = position; + } + + public String getPosition() { + return position; + } +} + +// 车类,组合多个轮子 +class Car { + private List wheels; + + public Car() { + // 车类内部负责创建轮子对象 + wheels = new ArrayList<>(); + wheels.add(new Wheel("Front-Left")); + wheels.add(new Wheel("Front-Right")); + wheels.add(new Wheel("Rear-Left")); + wheels.add(new Wheel("Rear-Right")); + } + + public void showWheels() { + for (Wheel wheel : wheels) { + System.out.println(wheel.getPosition()); + } + } +} + +public class Main { + public static void main(String[] args) { + // 创建车对象 + Car car = new Car(); + car.showWheels(); + + // 当车对象被销毁时,轮子对象也随之销毁 + car = null; + // 无法再访问车的轮子,因为它们被组合在一起,生命周期一同结束 + } +} +``` + +#### 聚合:长实线加空心菱形 + +``` java +// 学生类,生命周期独立于 Classroom +class Student { + private String name; + + public Student(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} + +// 班级类,聚合多个学生 +class Classroom { + private List students; + + // 构造函数接受外部创建的学生对象 + public Classroom(List students) { + this.students = students; + } + + public void showStudents() { + for (Student student : students) { + System.out.println(student.getName()); + } + } +} + +public class Main { + public static void main(String[] args) { + // 学生对象在外部创建 + Student s1 = new Student("Alice"); + Student s2 = new Student("Bob"); + + // 学生对象传入 Classroom + List studentList = new ArrayList<>(); + studentList.add(s1); + studentList.add(s2); + + // 创建班级对象 + Classroom classroom = new Classroom(studentList); + classroom.showStudents(); + + // Classroom 对象被销毁后,学生对象仍然存在 + classroom = null; + System.out.println(s1.getName()); // 输出 "Alice" + } +} +``` + +#### 组合和聚合的特点 + +- 两个方式可以互相转换,如何需要部分依赖整体的生命周期,则使用组合。如果需要独立,则使用聚合 diff --git a/js-advanced/design-pattern/behavioral/3.command-pro.ts b/js-advanced/design-pattern/behavioral/3.command-pro.ts new file mode 100644 index 0000000..b906e36 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/3.command-pro.ts @@ -0,0 +1,50 @@ +// 小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。 + +import { entry } from "../utils"; + +interface Command { + execute(): void; +} + +// 烤肉师傅 +class Receiver { + action(name: string) { + console.log(`${name} is ready!`); + } +} + +// 烤羊肉串命令 +class OrderCommand implements Command { + private receiver: Receiver; + private receiverName: string; + constructor(receiver: Receiver, receiverName: string) { + this.receiverName = receiverName; + this.receiver = receiver; + } + + execute(): void { + this.receiver.action(this.receiverName); + } +} + +// 服务员 +class Invoke { + private command: Command; + + constructor(command: Command) { + this.command = command; + } + + invokeCommand() { + this.command.execute(); + } +} + +// @ts-ignore +entry(4, (...args) => { + args.forEach((type) => { + const command = new OrderCommand(new Receiver(), type); + const invoke = new Invoke(command); + invoke.invokeCommand() + }); +})("MilkTea")("Coffee")("Cola")("MilkTea"); diff --git a/js-advanced/design-pattern/behavioral/3.command.ts b/js-advanced/design-pattern/behavioral/3.command.ts index e69de29..b906e36 100644 --- a/js-advanced/design-pattern/behavioral/3.command.ts +++ b/js-advanced/design-pattern/behavioral/3.command.ts @@ -0,0 +1,50 @@ +// 小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。 + +import { entry } from "../utils"; + +interface Command { + execute(): void; +} + +// 烤肉师傅 +class Receiver { + action(name: string) { + console.log(`${name} is ready!`); + } +} + +// 烤羊肉串命令 +class OrderCommand implements Command { + private receiver: Receiver; + private receiverName: string; + constructor(receiver: Receiver, receiverName: string) { + this.receiverName = receiverName; + this.receiver = receiver; + } + + execute(): void { + this.receiver.action(this.receiverName); + } +} + +// 服务员 +class Invoke { + private command: Command; + + constructor(command: Command) { + this.command = command; + } + + invokeCommand() { + this.command.execute(); + } +} + +// @ts-ignore +entry(4, (...args) => { + args.forEach((type) => { + const command = new OrderCommand(new Receiver(), type); + const invoke = new Invoke(command); + invoke.invokeCommand() + }); +})("MilkTea")("Coffee")("Cola")("MilkTea"); From 6911859aa64a8bad7d3d689c95d53d8b93323bc2 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Sat, 12 Oct 2024 19:35:04 +0800 Subject: [PATCH 29/47] feat(command):pro 1 --- .../behavioral/3.command-pro.ts | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/3.command-pro.ts b/js-advanced/design-pattern/behavioral/3.command-pro.ts index b906e36..36f07ad 100644 --- a/js-advanced/design-pattern/behavioral/3.command-pro.ts +++ b/js-advanced/design-pattern/behavioral/3.command-pro.ts @@ -1,29 +1,48 @@ -// 小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。 +// 烤肉案例 import { entry } from "../utils"; +// 命令的抽象类 +abstract class Command { + protected receiver: Receiver; // 烤肉师傅 -interface Command { - execute(): void; + constructor(receiver: Receiver) { + this.receiver = receiver; + } + + abstract execute(): void; } // 烤肉师傅 class Receiver { + bakeMutton() { + console.log("烤羊肉串"); + } + + bakeChickenWing() { + console.log("烤鸡翅"); + } + action(name: string) { console.log(`${name} is ready!`); } } // 烤羊肉串命令 -class OrderCommand implements Command { - private receiver: Receiver; - private receiverName: string; - constructor(receiver: Receiver, receiverName: string) { - this.receiverName = receiverName; - this.receiver = receiver; +class BakeMuttonCommand extends Command { + constructor(receiver: Receiver) { + super(receiver); } - execute(): void { - this.receiver.action(this.receiverName); + this.receiver.bakeMutton(); + } +} +// 烤鸡翅命令 +class BakeCheckingWingCommand extends Command { + constructor(receiver: Receiver) { + super(receiver); + } + execute(): void { + this.receiver.bakeChickenWing(); } } @@ -35,6 +54,10 @@ class Invoke { this.command = command; } + setOrder(command: Command) { + this.command = command; + } + invokeCommand() { this.command.execute(); } @@ -42,9 +65,27 @@ class Invoke { // @ts-ignore entry(4, (...args) => { + // 开店前的准备, 提前准备好烤肉师傅和服务员 + const boy = new Receiver(); + // const bakeMutton1 = new BakeMuttonCommand(boy); + // const bakeMutton2 = new BakeMuttonCommand(boy); + // const bakeChickenWing = new BakeCheckingWingCommand(boy) + let girl: Invoke; + let command: Command; + args.forEach((type) => { - const command = new OrderCommand(new Receiver(), type); - const invoke = new Invoke(command); - invoke.invokeCommand() + if (type === "bakeMutton") { + command = new BakeMuttonCommand(boy); + } else { + command = new BakeCheckingWingCommand(boy); + } + + if (!girl) { + girl = new Invoke(command); + girl.invokeCommand(); + } else { + girl.setOrder(command); + girl.invokeCommand(); + } }); -})("MilkTea")("Coffee")("Cola")("MilkTea"); +})("bakeMutton")("Coffee")("Cola")("bakeMutton"); From 1268334f613e4f2b4686c4f5d670dd18ae19247a Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Sat, 12 Oct 2024 19:38:04 +0800 Subject: [PATCH 30/47] doc --- js-advanced/design-pattern/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 91d9af0..b8d6929 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -67,6 +67,7 @@ - 代码中的桥接就是两个抽象接口其中一个抽象接口接入到另一个抽象接口中,二者都有对应的实现类,这样就可以编程笛卡尔积组合,进而增强实用性和扩展性。 - 如果程序设计上出现笛卡尔积的情况时就要考虑采用该设计模式了。如:热的小杯奶茶、热的大杯奶茶、凉的小杯奶茶、凉的大杯奶茶。 - [ ] [享元模式](./structural/07.flyWeight.ts) 案例不好,理解的不行,需要一个更好的案例。案例 (围棋 内部状态 颜色、外部状态 坐标)。 +- [ ] [命令模式](./behavioral/3.command.ts) 命令模式太难了吧!! ## 实战点 From d429a5a0f20da48e74d4f923a92e85fe9530a923 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 14 Oct 2024 11:51:39 +0800 Subject: [PATCH 31/47] feat(command) base --- .../design-pattern/behavioral/3.command.ts | 77 +++++++++++++++---- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/3.command.ts b/js-advanced/design-pattern/behavioral/3.command.ts index b906e36..d9cf662 100644 --- a/js-advanced/design-pattern/behavioral/3.command.ts +++ b/js-advanced/design-pattern/behavioral/3.command.ts @@ -2,28 +2,53 @@ import { entry } from "../utils"; -interface Command { - execute(): void; +abstract class Command { + protected receiver: Receiver; + + constructor(receiver: Receiver) { + this.receiver = receiver; + } + + abstract execute(): void; } -// 烤肉师傅 class Receiver { - action(name: string) { - console.log(`${name} is ready!`); + milkTea() { + console.log("MileTea is Ready!"); + } + coffee() { + console.log("Coffee is Ready!"); + } + cola() { + console.log("Cola is Ready!"); } } -// 烤羊肉串命令 -class OrderCommand implements Command { - private receiver: Receiver; - private receiverName: string; - constructor(receiver: Receiver, receiverName: string) { - this.receiverName = receiverName; - this.receiver = receiver; +class MileTeaCommand extends Command { + constructor(receiver: Receiver) { + super(receiver); + } + + execute(): void { + this.receiver.milkTea(); + } +} +class CoffeeCommand extends Command { + constructor(receiver: Receiver) { + super(receiver); + } + + execute(): void { + this.receiver.coffee(); + } +} +class ColaCommand extends Command { + constructor(receiver: Receiver) { + super(receiver); } execute(): void { - this.receiver.action(this.receiverName); + this.receiver.cola(); } } @@ -35,6 +60,10 @@ class Invoke { this.command = command; } + setOrder(command: Command) { + this.command = command; + } + invokeCommand() { this.command.execute(); } @@ -42,9 +71,25 @@ class Invoke { // @ts-ignore entry(4, (...args) => { + const machine = new Receiver(); + let waiter: Invoke; + let command: Command; + args.forEach((type) => { - const command = new OrderCommand(new Receiver(), type); - const invoke = new Invoke(command); - invoke.invokeCommand() + if (type === "MilkTea") { + command = new MileTeaCommand(machine); + } else if (type === "Coffee") { + command = new CoffeeCommand(machine); + } else if (type === "Cola") { + command = new ColaCommand(machine); + } + + if (!waiter) { + waiter = new Invoke(command); + waiter.invokeCommand(); + } else { + waiter.setOrder(command); + waiter.invokeCommand(); + } }); })("MilkTea")("Coffee")("Cola")("MilkTea"); From a12ef48934e43d7d48ba316d86636ed307421a62 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 14 Oct 2024 11:52:48 +0800 Subject: [PATCH 32/47] =?UTF-8?q?chore(command):=20=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavioral/{3.command.ts => 03.command/01.base.ts} | 2 +- .../behavioral/{3.command-pro.ts => 03.command/02.bbq.ts} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename js-advanced/design-pattern/behavioral/{3.command.ts => 03.command/01.base.ts} (98%) rename js-advanced/design-pattern/behavioral/{3.command-pro.ts => 03.command/02.bbq.ts} (97%) diff --git a/js-advanced/design-pattern/behavioral/3.command.ts b/js-advanced/design-pattern/behavioral/03.command/01.base.ts similarity index 98% rename from js-advanced/design-pattern/behavioral/3.command.ts rename to js-advanced/design-pattern/behavioral/03.command/01.base.ts index d9cf662..67e9ff3 100644 --- a/js-advanced/design-pattern/behavioral/3.command.ts +++ b/js-advanced/design-pattern/behavioral/03.command/01.base.ts @@ -1,6 +1,6 @@ // 小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。 -import { entry } from "../utils"; +import { entry } from "../../utils"; abstract class Command { protected receiver: Receiver; diff --git a/js-advanced/design-pattern/behavioral/3.command-pro.ts b/js-advanced/design-pattern/behavioral/03.command/02.bbq.ts similarity index 97% rename from js-advanced/design-pattern/behavioral/3.command-pro.ts rename to js-advanced/design-pattern/behavioral/03.command/02.bbq.ts index 36f07ad..0027379 100644 --- a/js-advanced/design-pattern/behavioral/3.command-pro.ts +++ b/js-advanced/design-pattern/behavioral/03.command/02.bbq.ts @@ -1,6 +1,6 @@ // 烤肉案例 -import { entry } from "../utils"; +import { entry } from "../../utils"; // 命令的抽象类 abstract class Command { protected receiver: Receiver; // 烤肉师傅 From f207e68d4bd61f8fe502d55c82339f94689ac9b9 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 14 Oct 2024 18:15:19 +0800 Subject: [PATCH 33/47] =?UTF-8?q?feat(17)=20mediator=20=E4=B8=AD=E4=BB=8B?= =?UTF-8?q?=E8=80=85=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/README.md | 2 +- .../design-pattern/behavioral/4.mediator.ts | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index b8d6929..490db9c 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -37,7 +37,7 @@ - 命令模式(Command) - 需求对 “行为请求者” 与 ”行为实现者“ 进行松耦合 - Invoker(服务员)、Receiver(烤肉师傅)、OrderCommand(烤羊肉)、xxxCommand(烤xxx肉) -- 中介者模式(Mediator) +- 中介者模式(Mediator) :调停者模式。 - 备忘录模式 (Memento) - 模板方法模式(Template Method) - 迭代器模式(Iterator) diff --git a/js-advanced/design-pattern/behavioral/4.mediator.ts b/js-advanced/design-pattern/behavioral/4.mediator.ts index e69de29..143f82f 100644 --- a/js-advanced/design-pattern/behavioral/4.mediator.ts +++ b/js-advanced/design-pattern/behavioral/4.mediator.ts @@ -0,0 +1,82 @@ +// 小明正在设计一个简单的多人聊天室系统,有多个用户和一个聊天室中介者,用户通过中介者进行聊天,请你帮他完成这个系统的设计。 + +import { entry } from "../utils"; + +abstract class Colleague { + private name: string; + + get cname() { + return this.name; + } + + constructor(name: string) { + this.name = name; + } + + send(msg: string) { + console.log(`${this.name} received: ${msg}`); + } +} + +abstract class Mediator { + protected colleagues: Colleague[] = []; + + constructor(...colleagues: Colleague[]) { + this.addColleague(...colleagues); + } + + addColleague(...colleagues: Colleague[]) { + this.colleagues.push(...colleagues); + } + + abstract notify(name: string, msg: string): void; +} + +class ChatRoomMediator extends Mediator { + constructor(...colleagues: Colleague[]) { + super(...colleagues); + } + + notify(name: string, msg: string) { + this.colleagues.forEach((item) => { + if (item.cname !== name) { + item.send(msg); + } + }); + } +} + +class UserColleague extends Colleague { + constructor(name: string) { + super(name); + } +} + +// @ts-ignore +entry(3, (...args) => { + const chatRoom = new ChatRoomMediator(); + args.forEach((uname) => { + chatRoom.addColleague(new UserColleague(uname)); + }); + + function dfs([name, msg]: [string, string]) { + chatRoom.notify(name, msg); + return dfs; + } + + return dfs; +})("User1")("User2")("User3")(["User1", "Hello_All!"])(["User2", "Hi_User1!"])([ + "User3", + "How_is_everyone?", +]); + +function entry(count: number, fn: (...args: any) => void) { + function dfs(...args) { + if (args.length < count) { + return (arg) => dfs(...args, arg); + } + + return fn(...args); + } + return dfs; +} From ab974ba8a59863791b8b552f11ecbf8a4a9d409f Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 14 Oct 2024 18:15:35 +0800 Subject: [PATCH 34/47] =?UTF-8?q?feat(17)=20mediator=20=E4=B8=AD=E4=BB=8B?= =?UTF-8?q?=E8=80=85=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js-advanced/design-pattern/behavioral/4.mediator.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/4.mediator.ts b/js-advanced/design-pattern/behavioral/4.mediator.ts index 143f82f..99e8ae5 100644 --- a/js-advanced/design-pattern/behavioral/4.mediator.ts +++ b/js-advanced/design-pattern/behavioral/4.mediator.ts @@ -69,14 +69,3 @@ entry(3, (...args) => { "User3", "How_is_everyone?", ]); - -function entry(count: number, fn: (...args: any) => void) { - function dfs(...args) { - if (args.length < count) { - return (arg) => dfs(...args, arg); - } - - return fn(...args); - } - return dfs; -} From 91b494e4f6d848106e00aa4a4e0eeb3080b4cc30 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 15 Oct 2024 11:56:48 +0800 Subject: [PATCH 35/47] chore(command) --- .../behavioral/{03.command => 3.command}/01.base.ts | 0 .../design-pattern/behavioral/{03.command => 3.command}/02.bbq.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename js-advanced/design-pattern/behavioral/{03.command => 3.command}/01.base.ts (100%) rename js-advanced/design-pattern/behavioral/{03.command => 3.command}/02.bbq.ts (100%) diff --git a/js-advanced/design-pattern/behavioral/03.command/01.base.ts b/js-advanced/design-pattern/behavioral/3.command/01.base.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/03.command/01.base.ts rename to js-advanced/design-pattern/behavioral/3.command/01.base.ts diff --git a/js-advanced/design-pattern/behavioral/03.command/02.bbq.ts b/js-advanced/design-pattern/behavioral/3.command/02.bbq.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/03.command/02.bbq.ts rename to js-advanced/design-pattern/behavioral/3.command/02.bbq.ts From 26b64f34c9d5c6ac9b33d4c5c358ebd34cd93452 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Wed, 16 Oct 2024 18:21:28 +0800 Subject: [PATCH 36/47] =?UTF-8?q?feat(17):=20memento=20=E5=A4=87=E5=BF=98?= =?UTF-8?q?=E5=BD=95=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/5.memento.ts | 0 .../behavioral/5.memento/01.base.ts | 88 +++++++++++++++ .../behavioral/5.memento/01.counter.ts | 96 ++++++++++++++++ .../behavioral/5.memento/02.game.ts | 106 ++++++++++++++++++ 4 files changed, 290 insertions(+) delete mode 100644 js-advanced/design-pattern/behavioral/5.memento.ts create mode 100644 js-advanced/design-pattern/behavioral/5.memento/01.base.ts create mode 100644 js-advanced/design-pattern/behavioral/5.memento/01.counter.ts create mode 100644 js-advanced/design-pattern/behavioral/5.memento/02.game.ts diff --git a/js-advanced/design-pattern/behavioral/5.memento.ts b/js-advanced/design-pattern/behavioral/5.memento.ts deleted file mode 100644 index e69de29..0000000 diff --git a/js-advanced/design-pattern/behavioral/5.memento/01.base.ts b/js-advanced/design-pattern/behavioral/5.memento/01.base.ts new file mode 100644 index 0000000..1e16945 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/5.memento/01.base.ts @@ -0,0 +1,88 @@ +// 小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。 + +import { entry } from "../../utils"; + +// 备忘录 +class Memento { + private state: string; + + getState() { + return this.state; + } + + constructor(state: string) { + this.state = state; + } +} + +// 发起人 +class Originator { + private state: string; + constructor(state: string) { + this.state = state; + } + + setState(state: string) { + this.state = state; + } + + createMemento() { + return new Memento(this.state); + } + + setMemento(memento: Memento) { + this.state = memento.getState(); + } + + // 通过备忘录恢复状态 + restoreFromMemento(memento: Memento) { + this.state = memento.getState(); + } + + show() { + console.log(this.state); + } +} + +// // 管理者 +// class Caretaker { +// private mementos: Memento[] = []; +// addMemento(memento: Memento) { +// this.mementos.push(memento); +// } + +// getMemento(idx: number) { +// // return this.mementos. +// } +// } + +// 管理者 +class Caretaker { + private memento: Memento; + + constructor(memento: Memento) { + this.memento = memento; + } + + addMemento(memento: Memento) { + this.memento = memento; + } + + getMemento() { + return this.memento; + } +} + +(function () { + let originator = new Originator("on"); + originator.show(); + + const caretaker = new Caretaker(originator.createMemento()) + originator.setState('off'); + originator.show(); + + originator.setMemento(caretaker.getMemento()); + originator.show(); +})(); + + diff --git a/js-advanced/design-pattern/behavioral/5.memento/01.counter.ts b/js-advanced/design-pattern/behavioral/5.memento/01.counter.ts new file mode 100644 index 0000000..1a51b64 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/5.memento/01.counter.ts @@ -0,0 +1,96 @@ +// 小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。 + +class CounterMemento { + private state: number; + + constructor(state: number) { + this.state = state; + } + + getState() { + return this.state; + } +} + +class Counter { + private state: number; + private redoAction = ""; + private counterCaretaker: CounterCaretaker; + constructor(state: number, counterCaretaker: CounterCaretaker) { + this.state = state; + this.counterCaretaker = counterCaretaker; + } + + increment() { + this.counterCaretaker.addMemento(new CounterMemento(this.state)); + this.state += 1; + this.redoAction = "INCREMENT"; + } + + decrement() { + this.counterCaretaker.addMemento(new CounterMemento(this.state)); + this.state -= 1; + this.redoAction = "DECREMENT"; + } + + undo() { + const state = this.counterCaretaker.getMemento()?.getState(); + if (state) { + this.state = state; + } + this.redoAction = "UNDO"; + } + + // 这里实现的是重复上一次执行的命令 + redo() { + if (this.redoAction === "INCREMENT") { + this.increment(); + } else if (this.redoAction === "DECREMENT") { + this.decrement(); + } else if (this.redoAction === "UNDO") { + this.undo(); + } else { + throw "error action"; + } + } + + createMemento() { + return new CounterMemento(this.state); + } + + setMemento(memento: CounterMemento) { + this.state = memento.getState(); + } + + restoreFromMemento(memento: CounterMemento) { + this.state = memento.getState(); + } + + show() { + console.log(this.state); + } +} + +class CounterCaretaker { + private actionStack: CounterMemento[] = []; + + addMemento(memento: CounterMemento) { + this.actionStack.push(memento); + } + + getMemento() { + return this.actionStack.pop(); + } +} + +(function () { + const caretaker = new CounterCaretaker(); + let originator = new Counter(0, caretaker); + + (function doIt(action: string) { + originator[action](); + originator.show(); + + return doIt; + })("increment")("increment")("decrement")("undo")("redo")("increment"); +})(); diff --git a/js-advanced/design-pattern/behavioral/5.memento/02.game.ts b/js-advanced/design-pattern/behavioral/5.memento/02.game.ts new file mode 100644 index 0000000..7f1abdb --- /dev/null +++ b/js-advanced/design-pattern/behavioral/5.memento/02.game.ts @@ -0,0 +1,106 @@ +// 小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。 + +// 备忘录 +class RoleMemento { + private blood: number; + private atk: number; + private defense: number; + + constructor(blood: number, atk: number, defense: number) { + this.blood = blood; + this.atk = atk; + this.defense = defense; + } + + getState() { + const { blood, atk, defense } = this; + return { blood, atk, defense }; + } +} + +// 发起人(业务对象) +class GameRole { + private blood: number; + private atk: number; + private defense: number; + + constructor(blood: number, atk: number, defense: number) { + this.blood = blood; + this.atk = atk; + this.defense = defense; + } + + setState(blood: number, atk: number, defense: number) { + this.blood = blood; + this.atk = atk; + this.defense = defense; + } + + createMemento() { + const { blood, atk, defense } = this; + return new RoleMemento(blood, atk, defense); + } + + setMemento(memento: RoleMemento) { + const { blood, atk, defense } = memento.getState(); + this.blood = blood; + this.atk = atk; + this.defense = defense; + } + + // 通过备忘录恢复状态 + restoreFromMemento(memento: RoleMemento) { + const { blood, atk, defense } = memento.getState(); + this.blood = blood; + this.atk = atk; + this.defense = defense; + } + + show() { + const { blood, atk, defense } = this; + console.log(`blood: ${blood}, atk: ${atk}, defense: ${defense}, `); + return { blood, atk, defense }; + } +} + +// 管理者 +class RoleStateCaretaker { + private mementos: RoleMemento[] = []; + + constructor(memento: RoleMemento) { + this.mementos.push(memento); + } + + addMemento(memento: RoleMemento) { + this.mementos.push(memento); + } + + getMemento(i: number) { + return this.mementos[i]; + } +} + +(function () { + let index = -1; + let originator = new GameRole(100, 100, 100); + originator.show(); + + const roleStateCaretaker = new RoleStateCaretaker(originator.createMemento()); + index++; + + originator.setState(50, 50, 50); + roleStateCaretaker.addMemento(originator.createMemento()); + index++; + originator.show(); + + originator.setState(0, 0, 0); + originator.show(); + + originator.restoreFromMemento(roleStateCaretaker.getMemento(index)); + index--; + originator.show(); + + originator.restoreFromMemento(roleStateCaretaker.getMemento(index)); + index--; + originator.show(); +})(); From d55582ee399e82223ee06fcf07dce09f37cbbba4 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 21 Oct 2024 17:37:52 +0800 Subject: [PATCH 37/47] =?UTF-8?q?feat(18):=20template=20=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavioral/6.template-method.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/js-advanced/design-pattern/behavioral/6.template-method.ts b/js-advanced/design-pattern/behavioral/6.template-method.ts index e69de29..1403f09 100644 --- a/js-advanced/design-pattern/behavioral/6.template-method.ts +++ b/js-advanced/design-pattern/behavioral/6.template-method.ts @@ -0,0 +1,84 @@ +// 小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。 + +import { entry } from "../utils"; + +// 咖啡制作过程包括以下步骤: + +// 1. 研磨咖啡豆 Grinding coffee beans + +// 2. 冲泡咖啡 Brewing coffee + +// 3. 添加调料 Adding condiments + +// 其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk + +abstract class AbstractTemplate { + coffeeName: string; + + constructor(coffee: string) { + this.coffeeName = coffee; + } + templateMethod() { + console.log(`Making ${this.coffeeName}:`); + this.grindingCoffeeBeans(); + this.brewingCoffee(); + this.addingCondiments(); + console.log(); + } + + abstract grindingCoffeeBeans(): void; + abstract brewingCoffee(): void; + abstract addingCondiments(): void; +} + +class AmericaCoffee extends AbstractTemplate { + constructor() { + super("American Coffee"); + } + + grindingCoffeeBeans(): void { + console.log("Grinding coffee beans"); + } + + brewingCoffee(): void { + console.log("Brewing coffee"); + } + + addingCondiments(): void { + console.log("Adding condiments"); + } +} +class Latte extends AbstractTemplate { + constructor() { + super("Latte"); + } + + grindingCoffeeBeans(): void { + console.log("Grinding coffee beans"); + } + + brewingCoffee(): void { + console.log("Brewing coffee"); + } + + addingCondiments(): void { + console.log("Adding milk"); + console.log("Adding condiments"); + } +} + +// @ts-ignore +entry(2, (...args) => { + args.forEach((type) => { + let coffee: AbstractTemplate; + if (type === 1) { + coffee = new AmericaCoffee(); + } else if (type === 2) { + coffee = new Latte(); + } else { + throw "type error"; + } + + coffee.templateMethod(); + }); +})(1)(2); From 4ab16e2e8456e6d7deecfb93a391f5fba7e1ee2a Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 21 Oct 2024 19:50:29 +0800 Subject: [PATCH 38/47] =?UTF-8?q?feat(19):=20iterator=20=E8=BF=AD=E4=BB=A3?= =?UTF-8?q?=E5=99=A8=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/7.iterator.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/js-advanced/design-pattern/behavioral/7.iterator.ts b/js-advanced/design-pattern/behavioral/7.iterator.ts index e69de29..e96db64 100644 --- a/js-advanced/design-pattern/behavioral/7.iterator.ts +++ b/js-advanced/design-pattern/behavioral/7.iterator.ts @@ -0,0 +1,54 @@ +// 小明是一位老师,在进行班级点名时,希望有一个学生名单系统,请你实现迭代器模式提供一个迭代器使得可以按顺序遍历学生列表 + +import { entry } from "../utils"; + +interface IIterator { + hasNext(): boolean; + next(): T; +} + +interface IIterable { + createIterator(): IIterator; +} + +class NameList implements IIterator { + private idx: number; + private nameList: string[]; + + constructor(names: string[]) { + this.nameList = names; + this.idx = 0; + } + + hasNext(): boolean { + return this.idx < this.nameList.length; + } + + next(): string { + if (this.hasNext()) { + return this.nameList[this.idx++]; + } else { + throw "No more elements"; + } + } +} + +class ConcreteIterable implements IIterable { + private ele: string[]; + + constructor(ele: string[]) { + this.ele = ele; + } + + createIterator(): IIterator { + return new NameList(this.ele); + } +} + +// @ts-ignore +entry(3, (...args) => { + const iterator = new ConcreteIterable(args).createIterator(); + while (iterator.hasNext()) { + console.log(iterator.next()); + } +})("Alice 1001")("Bob 1002")("Charlie 1003"); From ce2b93e8e6bae842d78077d64d92190ccfb1fc15 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 4 Nov 2024 18:24:09 +0800 Subject: [PATCH 39/47] chore(file) --- js-advanced/design-pattern/README.md | 1 + .../{8.chain-of-responsibility.ts => 10.interpreter.ts} | 0 .../design-pattern/behavioral/{10.visitor.ts => 11.visitor.ts} | 0 .../design-pattern/behavioral/{9.interpreter.ts => 8.state.ts} | 0 .../design-pattern/behavioral/9.chain-of-responsibility.ts | 0 5 files changed, 1 insertion(+) rename js-advanced/design-pattern/behavioral/{8.chain-of-responsibility.ts => 10.interpreter.ts} (100%) rename js-advanced/design-pattern/behavioral/{10.visitor.ts => 11.visitor.ts} (100%) rename js-advanced/design-pattern/behavioral/{9.interpreter.ts => 8.state.ts} (100%) create mode 100644 js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts diff --git a/js-advanced/design-pattern/README.md b/js-advanced/design-pattern/README.md index 490db9c..d89c6ad 100644 --- a/js-advanced/design-pattern/README.md +++ b/js-advanced/design-pattern/README.md @@ -41,6 +41,7 @@ - 备忘录模式 (Memento) - 模板方法模式(Template Method) - 迭代器模式(Iterator) +- 状态模式 (State) - 责任链模式(Chain of Responsibility) - 解释器模式(Interpreter) - 访问者模式(Visitor) diff --git a/js-advanced/design-pattern/behavioral/8.chain-of-responsibility.ts b/js-advanced/design-pattern/behavioral/10.interpreter.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/8.chain-of-responsibility.ts rename to js-advanced/design-pattern/behavioral/10.interpreter.ts diff --git a/js-advanced/design-pattern/behavioral/10.visitor.ts b/js-advanced/design-pattern/behavioral/11.visitor.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/10.visitor.ts rename to js-advanced/design-pattern/behavioral/11.visitor.ts diff --git a/js-advanced/design-pattern/behavioral/9.interpreter.ts b/js-advanced/design-pattern/behavioral/8.state.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/9.interpreter.ts rename to js-advanced/design-pattern/behavioral/8.state.ts diff --git a/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts b/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts new file mode 100644 index 0000000..e69de29 From 43c0a85389f90e742c6d4096778e5bbb01ebbb3e Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Mon, 4 Nov 2024 19:20:32 +0800 Subject: [PATCH 40/47] =?UTF-8?q?feat(20):=20state=20=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-pattern/behavioral/8.state copy.ts | 99 +++++++++++++++++++ .../design-pattern/behavioral/8.state.ts | 68 +++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 js-advanced/design-pattern/behavioral/8.state copy.ts diff --git a/js-advanced/design-pattern/behavioral/8.state copy.ts b/js-advanced/design-pattern/behavioral/8.state copy.ts new file mode 100644 index 0000000..df9a78d --- /dev/null +++ b/js-advanced/design-pattern/behavioral/8.state copy.ts @@ -0,0 +1,99 @@ +// 小明家有一个灯泡,刚开始为关闭状态(OffState)。 +// 台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("blink")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。 + +import { entry } from "../utils"; + +interface IState { + turnOn(): OnState | null; + turnOff(): OffState | null; + turnBlink(): BlinkState | null; +} + +class OnState implements IState { + // 可以关、闪烁 + + turnOn() { + console.log("当前已经是打开状态"); + return null; + } + + turnOff(): OffState { + console.log("Light is ON"); + return new OffState(); + } + turnBlink(): BlinkState { + console.log("Light is Blinking"); + return new BlinkState(); + } +} + +class OffState implements IState { + // 可以开 + + turnOn() { + console.log("Light is ON"); + return new OnState(); + } + + turnOff() { + console.log("当前已经是关闭状态"); + return null; + } + + turnBlink() { + console.log("Light is Blinking"); + return new BlinkState(); + } +} + +class BlinkState implements IState { + // 可以关 + turnOn() { + console.log("当前已经是打开状态"); + return null; + } + + turnOff() { + console.log("Light is OFF"); + return new OffState(); + } + turnBlink() { + console.log("当前已经是闪烁状态"); + return null; + } +} + +class StateContext { + private currentState: IState; + + constructor(state) { + this.currentState = state; + } + + setState(state: IState) { + this.currentState = state; + } + + getHandle() { + return this.currentState; + } +} + +// @ts-ignore +entry(5, (...args) => { + const fnMap = { + ON: "turnOn", + OFF: "turnOff", + BLINK: "turnBlink", + }; + + let state = new StateContext(new OffState()); + args.forEach((item) => { + const handle = state.getHandle(); + const method = fnMap[item]; + const next = handle[method](); + if (next) { + state.setState(next); + } + }); +})("ON")("OFF")("BLINK")("OFF")("ON"); diff --git a/js-advanced/design-pattern/behavioral/8.state.ts b/js-advanced/design-pattern/behavioral/8.state.ts index e69de29..49b1609 100644 --- a/js-advanced/design-pattern/behavioral/8.state.ts +++ b/js-advanced/design-pattern/behavioral/8.state.ts @@ -0,0 +1,68 @@ +// 小明家有一个灯泡,刚开始为关闭状态(OffState)。 +// 台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("blink")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。 + +// import { entry } from "../utils"; + +interface IState { + handle(); +} + +class OnState implements IState { + handle() { + console.log("Light is ON"); + } +} + +class OffState implements IState { + handle() { + console.log("Light is OFF"); + } +} + +class BlinkState implements IState { + handle() { + console.log("Light is Blinking"); + } +} + +class StateContext { + private currentState: IState; + + constructor(state) { + this.currentState = state; + } + + setState(state: IState) { + this.currentState = state; + } + + getHandle() { + return this.currentState.handle(); + } +} + +// @ts-ignore +entry(5, (...args) => { + const classMap = { + ON: OnState, + OFF: OffState, + BLINK: BlinkState, + }; + + let state = new StateContext(new OffState()); + args.forEach((item) => { + state.setState(new classMap[item]()); + state.getHandle(); + }); +})("ON")("OFF")("BLINK")("OFF")("ON"); + +function entry(count: number, fn: (...args: any) => void) { + function dfs(...args) { + if (args.length < count) { + return (arg) => dfs(...args, arg); + } + + return fn(...args); + } + return dfs; +} From 9cbc6455469da7d4af9850b1ca165b04b575d5ce Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 5 Nov 2024 11:22:56 +0800 Subject: [PATCH 41/47] =?UTF-8?q?pro(20):=20state=20=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{8.state.ts => 8.state/8.base.ts} | 0 .../behavioral/{ => 8.state}/8.state copy.ts | 2 +- .../behavioral/8.state/8.work-state.ts | 118 ++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) rename js-advanced/design-pattern/behavioral/{8.state.ts => 8.state/8.base.ts} (100%) rename js-advanced/design-pattern/behavioral/{ => 8.state}/8.state copy.ts (98%) create mode 100644 js-advanced/design-pattern/behavioral/8.state/8.work-state.ts diff --git a/js-advanced/design-pattern/behavioral/8.state.ts b/js-advanced/design-pattern/behavioral/8.state/8.base.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/8.state.ts rename to js-advanced/design-pattern/behavioral/8.state/8.base.ts diff --git a/js-advanced/design-pattern/behavioral/8.state copy.ts b/js-advanced/design-pattern/behavioral/8.state/8.state copy.ts similarity index 98% rename from js-advanced/design-pattern/behavioral/8.state copy.ts rename to js-advanced/design-pattern/behavioral/8.state/8.state copy.ts index df9a78d..dfe861c 100644 --- a/js-advanced/design-pattern/behavioral/8.state copy.ts +++ b/js-advanced/design-pattern/behavioral/8.state/8.state copy.ts @@ -1,7 +1,7 @@ // 小明家有一个灯泡,刚开始为关闭状态(OffState)。 // 台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("blink")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。 -import { entry } from "../utils"; +import { entry } from "../../utils"; interface IState { turnOn(): OnState | null; diff --git a/js-advanced/design-pattern/behavioral/8.state/8.work-state.ts b/js-advanced/design-pattern/behavioral/8.state/8.work-state.ts new file mode 100644 index 0000000..18b08f5 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/8.state/8.work-state.ts @@ -0,0 +1,118 @@ +// 一个人不同时间,会有不同的工作状态 + +// < 12 上午工作,精神百倍 +// < 13 饿了,午饭; 犯困,午休 +// < 17 下午状态不错,继续努力 +// < 21 加班,疲累之极 +// + +interface IState { + // (method) IState.handle(workContent: WorkContent): void (+1 overload) + writeProgram(workContent: WorkContent): void; +} + +class MonWork implements IState { + writeProgram(workContent: WorkContent): void { + if (workContent.hour > 12) { + workContent.setState(new MiddleWork()); + workContent.request(); + } else { + console.log(`当前时间:${workContent.hour}。 上午工作,精神百倍`); + } + } +} + +class MiddleWork implements IState { + writeProgram(workContent: WorkContent): void { + if (workContent.hour > 13) { + workContent.setState(new AfterWork()); + workContent.request(); + } else { + console.log(`当前时间:${workContent.hour}。 饿了,午饭; 犯困,午休`); + } + } +} + +class AfterWork implements IState { + writeProgram(workContent: WorkContent): void { + if (workContent.hour > 17) { + if(workContent.workFinished) { + workContent.setState(new RestState()); + }else { + workContent.setState(new NightWork()); + } + workContent.request(); + } else { + console.log(`当前时间:${workContent.hour}。 下午状态不错,继续努力`); + } + } +} + +class NightWork implements IState { + writeProgram(workContent: WorkContent): void { + console.log(`当前时间:${workContent.hour}。 加班,疲累之极`); + } +} + +class RestState implements IState { + writeProgram(workContent: WorkContent): void { + console.log(`当前时间:${workContent.hour}。 下班回家`); + } +} + +class WorkContent { + private _hour: number = 0; + + public get hour(): number { + return this._hour; + } + public set hour(value: number) { + this._hour = value; + } + + private _workFinished = false; + public get workFinished() { + return this._workFinished; + } + + public set workFinished(value) { + this._workFinished = value; + } + + private state: IState; + + constructor(state: IState) { + this.state = state; + } + + setState(state: IState) { + this.state = state; + } + + request() { + this.state.writeProgram(this); + } +} + +const work = new WorkContent(new MonWork()); + +work.hour = 9; +work.request(); +work.hour = 10; +work.request(); +work.hour = 12; +work.request(); +work.hour = 13; +work.request(); +work.hour = 14; +work.request(); +work.hour = 17; +work.request(); +work.workFinished = true +// work.workFinished = false; +work.hour = 19; +work.request(); +work.hour = 22; +work.request(); + +export {}; From d9237560af76232d528d14c953d3b20c5f240c8b Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Tue, 5 Nov 2024 14:26:22 +0800 Subject: [PATCH 42/47] =?UTF-8?q?pro(20):=20state=20=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=20-=2002?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../8.state/{8.base.ts => 1.base.ts} | 0 .../{8.state copy.ts => 2.state copy.ts} | 0 .../{8.work-state.ts => 3.work-state.ts} | 0 .../behavioral/8.state/4.bank.ts | 44 +++++++++++++++++++ 4 files changed, 44 insertions(+) rename js-advanced/design-pattern/behavioral/8.state/{8.base.ts => 1.base.ts} (100%) rename js-advanced/design-pattern/behavioral/8.state/{8.state copy.ts => 2.state copy.ts} (100%) rename js-advanced/design-pattern/behavioral/8.state/{8.work-state.ts => 3.work-state.ts} (100%) create mode 100644 js-advanced/design-pattern/behavioral/8.state/4.bank.ts diff --git a/js-advanced/design-pattern/behavioral/8.state/8.base.ts b/js-advanced/design-pattern/behavioral/8.state/1.base.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/8.state/8.base.ts rename to js-advanced/design-pattern/behavioral/8.state/1.base.ts diff --git a/js-advanced/design-pattern/behavioral/8.state/8.state copy.ts b/js-advanced/design-pattern/behavioral/8.state/2.state copy.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/8.state/8.state copy.ts rename to js-advanced/design-pattern/behavioral/8.state/2.state copy.ts diff --git a/js-advanced/design-pattern/behavioral/8.state/8.work-state.ts b/js-advanced/design-pattern/behavioral/8.state/3.work-state.ts similarity index 100% rename from js-advanced/design-pattern/behavioral/8.state/8.work-state.ts rename to js-advanced/design-pattern/behavioral/8.state/3.work-state.ts diff --git a/js-advanced/design-pattern/behavioral/8.state/4.bank.ts b/js-advanced/design-pattern/behavioral/8.state/4.bank.ts new file mode 100644 index 0000000..1e6ac11 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/8.state/4.bank.ts @@ -0,0 +1,44 @@ +// 如果账户中余额大于或等于0,则账户的状态为正常状态(Normal State)​,此时用户既可以向该账户存款也可以从该账户取款 +// 如果账户中余额小于0,并且大于-2000,则账户的状态为透支状态(Overdraft State)​,此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息 +// 如果账户中余额等于-2000,那么账户的状态为受限状态(Restricted State)​,此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息。 +// 根据余额的不同,以上3种状态可发生相互转换 + +interface IState { + take(); + put(); +} + +class NormalState implements IState { + take() {} + + put() {} +} +class OverdraftState implements IState { + take() {} + + put() {} +} +class RestrictedState implements IState { + take() {} + + put() {} +} + +class Bank { + amount: number = 0; + private state: IState; + + constructor(state: IState) { + this.state = state; + } + + take() { + this.state.take(); + } + + put() { + this.state.put(); + } +} + +export {}; From 4656f6880ebe285215585e4d016db53b5619c2e8 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 7 Nov 2024 17:55:59 +0800 Subject: [PATCH 43/47] not ok --- .../behavioral/8.state/4.bank.ts | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/8.state/4.bank.ts b/js-advanced/design-pattern/behavioral/8.state/4.bank.ts index 1e6ac11..c926a39 100644 --- a/js-advanced/design-pattern/behavioral/8.state/4.bank.ts +++ b/js-advanced/design-pattern/behavioral/8.state/4.bank.ts @@ -4,24 +4,38 @@ // 根据余额的不同,以上3种状态可发生相互转换 interface IState { - take(); - put(); + // 取款 + withdraw(bank: Bank, amount: number); + // 存款 + deposit(bank: Bank, amount: number); } class NormalState implements IState { - take() {} + withdraw(bank: Bank, amount: number) { + bank.amount -= amount; + } - put() {} + deposit(bank: Bank, amount: number) { + bank.amount += amount; + } } class OverdraftState implements IState { - take() {} + withdraw(bank: Bank, amount: number) { + bank.amount -= amount; + } - put() {} + deposit(bank: Bank, amount: number) { + bank.amount += amount; + } } class RestrictedState implements IState { - take() {} + withdraw(bank: Bank, amount: number) { + bank.amount -= amount; + } - put() {} + deposit(bank: Bank, amount: number) { + bank.amount += amount; + } } class Bank { @@ -32,12 +46,12 @@ class Bank { this.state = state; } - take() { - this.state.take(); + take(amount: number) { + this.state.withdraw(this, amount); } - put() { - this.state.put(); + put(amount: number) { + this.state.deposit(this, amount); } } From 91a43354181c0b083c38e8f7c2f8410f98bb9595 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 22 Nov 2024 10:41:36 +0800 Subject: [PATCH 44/47] reset base --- .../design-pattern/behavioral/8.state/1.base.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/js-advanced/design-pattern/behavioral/8.state/1.base.ts b/js-advanced/design-pattern/behavioral/8.state/1.base.ts index 49b1609..8b5ad52 100644 --- a/js-advanced/design-pattern/behavioral/8.state/1.base.ts +++ b/js-advanced/design-pattern/behavioral/8.state/1.base.ts @@ -1,7 +1,7 @@ // 小明家有一个灯泡,刚开始为关闭状态(OffState)。 // 台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("blink")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。 -// import { entry } from "../utils"; +import { entry } from "../../utils"; interface IState { handle(); @@ -54,15 +54,4 @@ entry(5, (...args) => { state.setState(new classMap[item]()); state.getHandle(); }); -})("ON")("OFF")("BLINK")("OFF")("ON"); - -function entry(count: number, fn: (...args: any) => void) { - function dfs(...args) { - if (args.length < count) { - return (arg) => dfs(...args, arg); - } - - return fn(...args); - } - return dfs; -} +})("ON")("OFF")("BLINK")("OFF")("ON"); \ No newline at end of file From a56fdcdf7e4f97dec34f175ddd79719efe9df4cf Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 22 Nov 2024 11:02:31 +0800 Subject: [PATCH 45/47] =?UTF-8?q?feat(=E8=B4=A3=E4=BB=BB=E9=93=BE=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavioral/9.chain-of-responsibility.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts b/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts index e69de29..f6a4e8e 100644 --- a/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts +++ b/js-advanced/design-pattern/behavioral/9.chain-of-responsibility.ts @@ -0,0 +1,79 @@ +// 小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者,请你实现责任链模式,可以根据请求天数找到对应的处理者。 + +import { entry } from "../utils"; + +// 审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。 + +interface IHandler { + handleRequest(request: LeaveRequest): void; +} + +class Supervisor implements IHandler { + private nextHandler: IHandler; + constructor(handler: IHandler) { + this.nextHandler = handler; + } + + handleRequest(request: LeaveRequest): void { + if (request.getDays() > 3) { + // manage.setNext(new Manager()); + this.nextHandler.handleRequest(request); + } else { + console.log(`${request.getName()} Approved by Supervisor`); + } + } +} + +class Manager implements IHandler { + private nextHandler: IHandler; + constructor(handler: IHandler) { + this.nextHandler = handler; + } + + handleRequest(request: LeaveRequest): void { + if (request.getDays() > 7) { + this.nextHandler.handleRequest(request); + } else { + console.log(`${request.getName()} Approved by Manager`); + } + } +} + +class Director implements IHandler { + handleRequest(request: LeaveRequest): void { + if (request.getDays() > 10) { + console.log(`${request.getName()} Denied by Director`); + } else { + console.log(`${request.getName()} Approved by Director`); + } + } +} + +class LeaveRequest { + private name: string; + private days: number; + + constructor([name, days]) { + this.name = name; + this.days = days; + } + + getName() { + return this.name; + } + + getDays() { + return this.days; + } +} + +// @ts-ignore +entry(4, (...args) => { + const director = new Director(); + const manager = new Manager(director); + const supervisor = new Supervisor(manager); + args.forEach((info) => { + const request = new LeaveRequest(info); + supervisor.handleRequest(request); + }); +})(["Alice", 2])(["Bob", 5])(["Tom", 10])(["Jerry", 12]); From 85866da4c5926f736e40a48e3944ad1e57399c58 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Fri, 27 Dec 2024 18:09:39 +0800 Subject: [PATCH 46/47] ignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f87da15..f41c5bf 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,8 @@ dist __pycache__ kssbox.egg-info node_modules -*.class \ No newline at end of file +*.class +debug +release +.rustc_info.json +CACHEDIR.TAG From ab1259a2479acad3905745dbf289005959e4f112 Mon Sep 17 00:00:00 2001 From: caojunjie <1301239018@qq.com> Date: Thu, 5 Jun 2025 14:54:44 +0800 Subject: [PATCH 47/47] easy interpreter --- .../behavioral/10.interpreter.ts | 0 .../behavioral/10.interpreter/music.ts | 109 ++++++++++++++++++ 2 files changed, 109 insertions(+) delete mode 100644 js-advanced/design-pattern/behavioral/10.interpreter.ts create mode 100644 js-advanced/design-pattern/behavioral/10.interpreter/music.ts diff --git a/js-advanced/design-pattern/behavioral/10.interpreter.ts b/js-advanced/design-pattern/behavioral/10.interpreter.ts deleted file mode 100644 index e69de29..0000000 diff --git a/js-advanced/design-pattern/behavioral/10.interpreter/music.ts b/js-advanced/design-pattern/behavioral/10.interpreter/music.ts new file mode 100644 index 0000000..62bc1d5 --- /dev/null +++ b/js-advanced/design-pattern/behavioral/10.interpreter/music.ts @@ -0,0 +1,109 @@ +// 我的规则是O表示音阶‘O1’表示低音阶,‘O2’表示中音阶,‘O3’表示高音阶; +// ‘P’表示休止符,‘CDEFGAB’表示‘Do-Re-Mi-Fa-So-La-Ti’:音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25表示四分之一拍,以此类推. +// 注意:所有的字母和数字都要用半角空格分开。例如上海滩的歌曲第一句,‘浪奔’,可以写成‘O 2 E 0.5 G 0.5 A 3’表示中音开始,演奏的是mi so la。​” + +interface IExpress { + interpreter(content: string): string; +} + +const LevelMap = { + O1: "低音", + O2: "中音", + O3: "高音", +}; + +const BeatMap = { + "3": "三拍", + "2": "二拍", + "1": "一拍", + "0.5": "半拍", + "0.25": "四分之一拍", +}; + +const NoteMap = { + C: "Do", + D: "Re", + E: "Mi", + F: "Fa", + G: "So", + A: "La", + B: "Ti", +}; + +type LevelMapKey = keyof typeof LevelMap; +type BeatMapKey = keyof typeof BeatMap; +type NoteMapKey = keyof typeof NoteMap; + +class MusicLevel implements IExpress { + interpreter(content: LevelMapKey) { + return LevelMap[content]; + } +} + +class MusicBeat implements IExpress { + interpreter(content: BeatMapKey): string { + return BeatMap[content]; + } +} + +class MusicNote implements IExpress { + interpreter(content: NoteMapKey): string { + return NoteMap[content]; + } +} + +class Context { + musicLevel = new MusicLevel(); + musicBeat = new MusicBeat(); + musicNote = new MusicNote(); + rst: string[][] = []; + + interpreter(content: string) { + this.rst = []; + let path: string[] = []; + let preStr = ""; + // const cA = content.split(" ") + // cA.forEach((element) => { + content.split(" ").forEach((element) => { + if (isNaN(Number(element))) { + if (element === "O") { + preStr = element; + path = []; + this.rst.push(path); + } else { + path.push(this.musicNote.interpreter(element as NoteMapKey)); + } + } else { + if (preStr) { + const curStr = (preStr + element) as LevelMapKey; + path.push(this.musicLevel.interpreter(curStr)); + preStr = ""; + } else { + // path.push(this.musicBeat.interpreter(element as BeatMapKey)); + } + } + }); + + return this; + } + + executor() { + this.rst.forEach((path) => { + let line = ""; + path.forEach((ele) => { + line += ele + " "; + }); + console.log(line); + }); + } +} + +class Player { + context = new Context(); + play(content: string) { + this.context.interpreter(content).executor(); + } +} + +const player = new Player(); +player.play("O 2 E 0.5 G 0.5 A 3 O 2 E 0.5 G 0.5 A 3");