update files
This commit is contained in:
3
.obsidian/app.json
vendored
3
.obsidian/app.json
vendored
@@ -2,5 +2,6 @@
|
||||
"strictLineBreaks": true,
|
||||
"showLineNumber": true,
|
||||
"readableLineLength": false,
|
||||
"alwaysUpdateLinks": true
|
||||
"alwaysUpdateLinks": true,
|
||||
"promptDelete": false
|
||||
}
|
||||
4
.obsidian/community-plugins.json
vendored
4
.obsidian/community-plugins.json
vendored
@@ -2,7 +2,9 @@
|
||||
"easy-typing-obsidian",
|
||||
"cm-editor-syntax-highlight-obsidian",
|
||||
"markdown-prettifier",
|
||||
"remotely-save",
|
||||
"obsidian42-brat",
|
||||
"attachment-flow-plugin",
|
||||
"remotely-save"
|
||||
"janitor",
|
||||
"obsidian-file-cleaner"
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"id": "cm-editor-syntax-highlight-obsidian",
|
||||
"name": "Editor Syntax Highlight",
|
||||
"author": "death_au",
|
||||
"authorUrl": "https://github.com/deathau",
|
||||
"description": "Show syntax highlighing in code blocks the editor",
|
||||
"isDesktopOnly": false,
|
||||
"version": "0.1.3",
|
||||
"minAppVersion": "0.10.0"
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
.cm-s-obsidian pre.HyperMD-codeblock span.cm-formatting-code-block {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.cm-s-obsidian pre.HyperMD-codeblock .cm-keyword {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.theme-dark .cm-s-obsidian {
|
||||
/*
|
||||
|
||||
Name: yoncé
|
||||
Author: Thomas MacLean (http://github.com/thomasmaclean)
|
||||
|
||||
Original yoncé color scheme by Mina Markham (https://github.com/minamarkham)
|
||||
|
||||
*/
|
||||
/**/
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-keyword,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-keyword,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-keyword {
|
||||
color: #00A7AA;
|
||||
font-weight: normal;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-atom,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-atom,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-atom {
|
||||
color: #F39B35;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-number,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-number,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-number {
|
||||
color: #A06FCA;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-type,
|
||||
.theme-dark .cm-s-obsidian span.cm-math.cm-type,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-type {
|
||||
color: #A06FCA;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-def,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-def,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-def {
|
||||
color: #98E342;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-property,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-property,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-property {
|
||||
color: #D4D4D4;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable,
|
||||
.theme-dark .cm-s-obsidian span.cm-math.cm-variable,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable {
|
||||
color: #D4D4D4;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable-2,
|
||||
.theme-dark .cm-s-obsidian span.cm-math.cm-variable-2,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable-2 {
|
||||
color: #da7dae;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable-3,
|
||||
.theme-dark .cm-s-obsidian span.cm-math.cm-variable-3,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable-3 {
|
||||
color: #A06FCA;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-type.cm-def,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-type.cm-def,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-type.cm-def {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-property.cm-def,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-property.cm-def,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-property.cm-def {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-callee,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-callee,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-callee {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-operator,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-operator,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-operator {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-qualifier,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-qualifier,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-qualifier {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-tag,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-tag,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-tag {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-tag.cm-bracket,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-tag.cm-bracket,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-tag.cm-bracket {
|
||||
color: #D4D4D4;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-attribute,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-attribute,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-attribute {
|
||||
color: #A06FCA;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-comment,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment {
|
||||
color: #696d70;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment.cm-tag,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-comment.cm-tag,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment.cm-tag {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment.cm-attribute,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-comment.cm-attribute,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment.cm-attribute {
|
||||
color: #D4D4D4;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-string,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-string,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-string {
|
||||
color: #E6DB74;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-string-2,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-string-2,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-string-2 {
|
||||
color: #F39B35;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-meta,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-meta,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-meta {
|
||||
color: #D4D4D4;
|
||||
background: inherit;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-builtin,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-builtin,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-builtin {
|
||||
color: #FC4384;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-header,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-header,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-header {
|
||||
color: #da7dae;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-hr,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-hr,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-hr {
|
||||
color: #98E342;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-link,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-link,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-link {
|
||||
color: #696d70;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-error,
|
||||
.theme-dark .cm-s-obsidian .cm-math.cm-error,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-error {
|
||||
border-bottom: 1px solid #C42412;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.CodeMirror-activeline-background,
|
||||
.theme-dark .cm-s-obsidian .cm-math.CodeMirror-activeline-background,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .CodeMirror-activeline-background {
|
||||
background: #272727;
|
||||
}
|
||||
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.CodeMirror-matchingbracket,
|
||||
.theme-dark .cm-s-obsidian .cm-math.CodeMirror-matchingbracket,
|
||||
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .CodeMirror-matchingbracket {
|
||||
outline: 1px solid grey;
|
||||
color: #D4D4D4 !important;
|
||||
}
|
||||
56
.obsidian/plugins/easy-typing-obsidian/data.json
vendored
56
.obsidian/plugins/easy-typing-obsidian/data.json
vendored
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"Tabout": true,
|
||||
"SelectionEnhance": true,
|
||||
"IntrinsicSymbolPairs": true,
|
||||
"BaseObEditEnhance": true,
|
||||
"FW2HWEnhance": true,
|
||||
"AutoFormat": true,
|
||||
"ExcludeFiles": "",
|
||||
"ChineseEnglishSpace": true,
|
||||
"ChineseNumberSpace": true,
|
||||
"EnglishNumberSpace": true,
|
||||
"ChineseNoSpace": true,
|
||||
"PunctuationSpace": true,
|
||||
"AutoCapital": false,
|
||||
"AutoCapitalMode": "typing",
|
||||
"PunctuationSpaceMode": "typing",
|
||||
"InlineCodeSpaceMode": 1,
|
||||
"InlineFormulaSpaceMode": 1,
|
||||
"InlineLinkSpaceMode": 1,
|
||||
"InlineLinkSmartSpace": true,
|
||||
"UserDefinedRegSwitch": true,
|
||||
"UserDefinedRegExp": "{{.*?}}|++\n<.*?>|--\n\\[\\!.*?\\][-+]{0,1}|-+\n(file:///|https?://|ftp://|obsidian://|zotero://|www.)[^\\s()《》。,,!?;;:“”‘’\\)\\(\\[\\]\\{\\}']+|++\n\n[a-zA-Z0-9_\\-.]+@[a-zA-Z0-9_\\-.]+|++\n(?<!#)#[\\u4e00-\\u9fa5\\w\\/]+|++",
|
||||
"debug": false,
|
||||
"userSelRepRuleTrigger": [
|
||||
"-",
|
||||
"#"
|
||||
],
|
||||
"userSelRepRuleValue": [
|
||||
{
|
||||
"left": "~~",
|
||||
"right": "~~"
|
||||
},
|
||||
{
|
||||
"left": "#",
|
||||
"right": " "
|
||||
}
|
||||
],
|
||||
"userDeleteRulesStrList": [
|
||||
[
|
||||
"demo|",
|
||||
"|"
|
||||
]
|
||||
],
|
||||
"userConvertRulesStrList": [
|
||||
[
|
||||
":)|",
|
||||
"😀|"
|
||||
]
|
||||
],
|
||||
"userSelRuleSettingsOpen": true,
|
||||
"userDelRuleSettingsOpen": true,
|
||||
"userCvtRuleSettingsOpen": true,
|
||||
"EnterTwice": false,
|
||||
"TryFixChineseIM": false,
|
||||
"PuncRectify": false
|
||||
}
|
||||
2806
.obsidian/plugins/easy-typing-obsidian/main.js
vendored
2806
.obsidian/plugins/easy-typing-obsidian/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "easy-typing-obsidian",
|
||||
"name": "Easy Typing",
|
||||
"version": "5.3.3",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Autoformat your note as typing.(Auto captalize, autospace)",
|
||||
"author": "yaozhuwa",
|
||||
"authorUrl": "https://github.com/Yaozhuwa",
|
||||
"isDesktopOnly": false,
|
||||
"fundingUrl": "https://www.buymeacoffee.com/yaozhuwa"
|
||||
}
|
||||
28711
.obsidian/plugins/markdown-prettifier/main.js
vendored
28711
.obsidian/plugins/markdown-prettifier/main.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"id": "markdown-prettifier",
|
||||
"name": "Markdown prettifier",
|
||||
"description": "Tries to fix and reformat ugly Markdown and adds things like 'modified date' etc.",
|
||||
"isDesktopOnly": false,
|
||||
"author": "Cristian",
|
||||
"authorUrl": "https://github.com/cristianvasquez",
|
||||
"js": "main.js",
|
||||
"version": "0.1.3"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
/*Add css here*/
|
||||
229
.obsidian/plugins/obsidian-file-cleaner/main.js
vendored
Normal file
229
.obsidian/plugins/obsidian-file-cleaner/main.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
.obsidian/plugins/obsidian-file-cleaner/manifest.json
vendored
Normal file
10
.obsidian/plugins/obsidian-file-cleaner/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "obsidian-file-cleaner",
|
||||
"name": "File Cleaner",
|
||||
"version": "0.1.5",
|
||||
"minAppVersion": "0.12.0",
|
||||
"description": "Help you to clean empty files and unused attachments in the vault.",
|
||||
"author": "Johnson0907",
|
||||
"authorUrl": "https://github.com/Johnson0907",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
15
.obsidian/plugins/obsidian42-brat/manifest.json
vendored
15
.obsidian/plugins/obsidian42-brat/manifest.json
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"id": "obsidian42-brat",
|
||||
"name": "BRAT",
|
||||
"version": "1.0.1",
|
||||
"minAppVersion": "1.4.16",
|
||||
"description": "Easily install a beta version of a plugin for testing.",
|
||||
"author": "TfTHacker",
|
||||
"authorUrl": "https://github.com/TfTHacker/obsidian42-brat",
|
||||
"helpUrl": "https://tfthacker.com/BRAT",
|
||||
"isDesktopOnly": false,
|
||||
"fundingUrl": {
|
||||
"Buy Me a Coffee": "https://bit.ly/o42-kofi",
|
||||
"Visit my site": "https://tfthacker.com"
|
||||
}
|
||||
}
|
||||
138
.obsidian/plugins/remotely-save/main.js
vendored
138
.obsidian/plugins/remotely-save/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "remotely-save",
|
||||
"name": "Remotely Save",
|
||||
"version": "0.4.21",
|
||||
"version": "0.4.22",
|
||||
"minAppVersion": "0.13.21",
|
||||
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
||||
"author": "fyears",
|
||||
|
||||
5
.obsidian/plugins/remotely-save/styles.css
vendored
5
.obsidian/plugins/remotely-save/styles.css
vendored
@@ -82,6 +82,7 @@
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.setting-need-wrapping-mobile .setting-item-control {
|
||||
flex-wrap: wrap;
|
||||
.setting-need-wrapping .setting-item-control {
|
||||
/* flex-wrap: wrap; */
|
||||
display: grid;
|
||||
}
|
||||
|
||||
73
.obsidian/plugins/remove-empty-folders/main.js
vendored
Normal file
73
.obsidian/plugins/remove-empty-folders/main.js
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// main.ts
|
||||
var main_exports = {};
|
||||
__export(main_exports, {
|
||||
default: () => RemoveEmptyFoldersPlugin
|
||||
});
|
||||
module.exports = __toCommonJS(main_exports);
|
||||
var import_obsidian = require("obsidian");
|
||||
var RemoveEmptyFoldersPlugin = class extends import_obsidian.Plugin {
|
||||
async onload() {
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("files-menu", (menu, files) => {
|
||||
menu.addItem((item) => {
|
||||
item.setTitle("Remove empty folders").onClick(async () => {
|
||||
files.forEach((file) => {
|
||||
if (file instanceof import_obsidian.TFolder) {
|
||||
removeEmptyFolders(this.app, file);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file) => {
|
||||
if (file instanceof import_obsidian.TFolder) {
|
||||
menu.addItem((item) => {
|
||||
item.setTitle("Remove empty folders").onClick(async () => {
|
||||
const notice = new import_obsidian.Notice(`Removing empty folders !!`);
|
||||
console.log("Removing empty folders !!");
|
||||
removeEmptyFolders(this.app, file);
|
||||
notice.hide();
|
||||
new import_obsidian.Notice(`Empty folders removed !!`);
|
||||
console.log("Empty folders removed !!");
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
var removeEmptyFolders = (app, folder) => {
|
||||
folder.children.forEach((child) => {
|
||||
if (child instanceof import_obsidian.TFolder) {
|
||||
removeEmptyFolders(app, child);
|
||||
}
|
||||
});
|
||||
if (folder.children.length === 0) {
|
||||
app.vault.adapter.trashLocal(folder.path);
|
||||
}
|
||||
};
|
||||
10
.obsidian/plugins/remove-empty-folders/manifest.json
vendored
Normal file
10
.obsidian/plugins/remove-empty-folders/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "remove-empty-folders",
|
||||
"name": "Remove Empty Folders",
|
||||
"version": "0.0.3",
|
||||
"minAppVersion": "0.0.0",
|
||||
"description": "Easily remove empty folders.",
|
||||
"author": "fnya",
|
||||
"authorUrl": "https://github.com/fnya",
|
||||
"isDesktopOnly": true
|
||||
}
|
||||
8
.obsidian/plugins/remove-empty-folders/styles.css
vendored
Normal file
8
.obsidian/plugins/remove-empty-folders/styles.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
|
||||
This CSS file will be included with your plugin, and
|
||||
available in the app when your plugin is enabled.
|
||||
|
||||
If your plugin does not need CSS, delete this file.
|
||||
|
||||
*/
|
||||
121
.obsidian/workspace-mobile.json
vendored
121
.obsidian/workspace-mobile.json
vendored
@@ -4,15 +4,20 @@
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "49ccb5f7f471596e",
|
||||
"id": "cf337069fe626fc2",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "09210d87f9fea733",
|
||||
"id": "0423604555a10e45",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "empty",
|
||||
"state": {}
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "客户清退.md",
|
||||
"mode": "source",
|
||||
"backlinks": true,
|
||||
"source": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -67,6 +72,18 @@
|
||||
"type": "bookmarks",
|
||||
"state": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "b3d78342d62c35ea",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "all-properties",
|
||||
"state": {
|
||||
"sortOrder": "frequency",
|
||||
"showSearch": false,
|
||||
"searchQuery": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"currentTab": 0
|
||||
@@ -81,6 +98,7 @@
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"file": "客户清退.md",
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
@@ -97,6 +115,7 @@
|
||||
"state": {
|
||||
"type": "outgoing-link",
|
||||
"state": {
|
||||
"file": "客户清退.md",
|
||||
"linksCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
}
|
||||
@@ -107,7 +126,9 @@
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {}
|
||||
"state": {
|
||||
"file": "客户清退.md"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -123,65 +144,63 @@
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"markdown-importer:Open format converter": false,
|
||||
"audio-recorder:Start/stop recording": false,
|
||||
"publish:Publish changes...": false,
|
||||
"switcher:Open quick switcher": false,
|
||||
"graph:Open graph view": false,
|
||||
"canvas:Create new canvas": false,
|
||||
"daily-notes:Open today's daily note": false,
|
||||
"templates:Insert template": false,
|
||||
"command-palette:Open command palette": false
|
||||
"command-palette:Open command palette": false,
|
||||
"obsidian-file-cleaner:Clean files": false,
|
||||
"remotely-save:Remotely Save": false
|
||||
}
|
||||
},
|
||||
"active": "09210d87f9fea733",
|
||||
"active": "0423604555a10e45",
|
||||
"lastOpenFiles": [
|
||||
"客户清退.md",
|
||||
"亲选.md",
|
||||
"锁.md",
|
||||
"流.md",
|
||||
"注解.md",
|
||||
"锁优化.md",
|
||||
"并发.md",
|
||||
"语法糖.md",
|
||||
"线程池.md",
|
||||
"方法区.md",
|
||||
"弱引用.md",
|
||||
"可读性.md",
|
||||
"Set.md",
|
||||
"内部类.md",
|
||||
"使用流.md",
|
||||
"TCP.md",
|
||||
"OSI.md",
|
||||
"JVM.md",
|
||||
"Map.md",
|
||||
"CMS.md",
|
||||
"CAS.md",
|
||||
"阻塞队列.md",
|
||||
"默认方法.md",
|
||||
"虚拟机栈.md",
|
||||
"线程调度.md",
|
||||
"线程安全.md",
|
||||
"LICENSE",
|
||||
"203-Java/深入理解Java虚拟机.pdf",
|
||||
"财富自由之路.canvas",
|
||||
"Java-Interview.7z",
|
||||
"logseq-java/logseq/custom.css",
|
||||
"logseq-java/logseq/graphs-txid.edn",
|
||||
"logseq-java/logseq",
|
||||
"Pasted image 20240512214620.png",
|
||||
"Java-Interview/常见框架/SpringMVC工作流程图.png",
|
||||
"Pasted image 20230620173539.png",
|
||||
"Pasted image 20230705093951.png",
|
||||
"Pasted image 20230705104736.png",
|
||||
"203-Java/203.1-Java面试/203.11-Java基础",
|
||||
"Pasted image 20230613183256.png",
|
||||
"财富自由之路/images/page-242.png",
|
||||
"财富自由之路/images/page-079.png",
|
||||
"Java面试/用流收集数据.md",
|
||||
"Java 内存模型.md",
|
||||
"财富自由之路.canvas",
|
||||
"JavaC编译器.md",
|
||||
"HotSpot虚拟机插件及工具.md",
|
||||
"里氏替换原则.md",
|
||||
"Brook Pointer.md",
|
||||
"分代收集理论.md",
|
||||
"the-craft-of-selfteach/Part.2.D.3-lambda.md",
|
||||
"the-craft-of-selfteach/Part.2.C.why-start-from-writing-functions.md",
|
||||
"the-craft-of-selfteach/Part.2.A.clumsy-and-patience.md",
|
||||
"Pasted image 20230705093951.png",
|
||||
"the-craft-of-selfteach/Part.2.D.1-args.md",
|
||||
"the-craft-of-selfteach/Part.1.A.better.teachyourself.md",
|
||||
"财富自由之路/images/page-195.png",
|
||||
"Parallel Old.md",
|
||||
"财富自由之路/pages/33. 为什么就算有钱也不一定有资本?.md",
|
||||
"财富自由之路/pages/27. 你天天刷牙吗?又,我为什么要问这个奇怪的问题?.md",
|
||||
"the-craft-of-selfteach/Part.1.E.5.strings.md",
|
||||
"财富自由之路/pages/9. 你升级过自己的操作系统吗?.md",
|
||||
"财富自由之路/images/page-307.png",
|
||||
"财富自由之路/images/page-222.png",
|
||||
"方法调用.md",
|
||||
"运行时栈帧结构.md",
|
||||
"动态类型语言支持.md",
|
||||
"基于栈的字节码解释执行引擎.md",
|
||||
"logseq/whiteboards/子弹笔记.edn",
|
||||
"logseq/journals/2023_05_15.md",
|
||||
"Pasted image 20230516164945.png",
|
||||
"logseq/whiteboards",
|
||||
"Pasted image 20230403123034.png",
|
||||
"logseq/LICENSE",
|
||||
"logseq/README.md",
|
||||
"logseq/pages/函数.md",
|
||||
"logseq/pages/原则.md",
|
||||
"logseq/logseq/config.edn",
|
||||
"logseq/assets/2023-03-21-17-57-47.jpeg",
|
||||
"logseq/assets/34张史上最全IT架构师技术知识图谱_1679583794511_0.zip",
|
||||
"logseq/assets/2023-03-21-17-41-37.jpeg",
|
||||
"logseq/logseq/bak/pages/相约七年后9",
|
||||
"logseq/logseq/bak/pages/相约七年后8",
|
||||
"logseq/logseq/bak/pages/相约七年后7",
|
||||
"logseq/logseq/bak/pages/相约七年后5",
|
||||
"logseq/logseq/bak/pages/相约七年后4"
|
||||
"logseq/LICENSE"
|
||||
]
|
||||
}
|
||||
39
.obsidian/workspace.json
vendored
39
.obsidian/workspace.json
vendored
@@ -13,7 +13,20 @@
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "代码规范/代码规范.md",
|
||||
"file": "客户清退.md",
|
||||
"mode": "source",
|
||||
"backlinks": true,
|
||||
"source": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "6b741110a2abe7d7",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "首销价格补偿.md",
|
||||
"mode": "source",
|
||||
"backlinks": true,
|
||||
"source": false
|
||||
@@ -101,7 +114,7 @@
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"file": "并发.md",
|
||||
"file": "首销价格补偿.md",
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
@@ -126,7 +139,7 @@
|
||||
"state": {
|
||||
"type": "outgoing-link",
|
||||
"state": {
|
||||
"file": "并发.md",
|
||||
"file": "首销价格补偿.md",
|
||||
"linksCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
}
|
||||
@@ -149,7 +162,7 @@
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {
|
||||
"file": "并发.md"
|
||||
"file": "首销价格补偿.md"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -174,21 +187,24 @@
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"obsidian42-brat:BRAT": false,
|
||||
"remotely-save:Remotely Save": false,
|
||||
"obsidian-file-cleaner:Clean files": false,
|
||||
"switcher:Open quick switcher": false,
|
||||
"graph:Open graph view": false,
|
||||
"canvas:Create new canvas": false,
|
||||
"templates:Insert template": false,
|
||||
"command-palette:Open command palette": false
|
||||
"command-palette:Open command palette": false,
|
||||
"remotely-save:Remotely Save": false
|
||||
}
|
||||
},
|
||||
"active": "af571c790caf59c7",
|
||||
"active": "6b741110a2abe7d7",
|
||||
"lastOpenFiles": [
|
||||
"客户清退.md",
|
||||
"首销价格补偿.md",
|
||||
"代码规范/代码规范.md",
|
||||
"亲选.md",
|
||||
"logseq-java.7z",
|
||||
"Java-Interview.7z",
|
||||
"Java-Interview.zip",
|
||||
"代码规范/代码规范.md",
|
||||
"并发.md",
|
||||
"弱引用.md",
|
||||
"引用类型.md",
|
||||
@@ -212,8 +228,6 @@
|
||||
"方法规范.md",
|
||||
"命名规范.md",
|
||||
"方法.md",
|
||||
"变量规范.md",
|
||||
"常量规范.md",
|
||||
"Pasted image 20230403123034.png",
|
||||
"代码规范",
|
||||
"203-Java/Pasted image 20230613181834.png",
|
||||
@@ -226,7 +240,6 @@
|
||||
"203-Java/203.1-Java面试/205.17-Spring",
|
||||
"203-Java/203.1-Java面试/205.16-RabbitMQ",
|
||||
"203-Java/203.1-Java面试/205.15-Redis",
|
||||
"203-Java/203.1-Java面试/205.14-MySQL",
|
||||
"203-Java/203.1-Java面试/205.13-JVM"
|
||||
"203-Java/203.1-Java面试/205.14-MySQL"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@@ -1,42 +0,0 @@
|
||||
## 线程创建方式
|
||||
|
||||
- 继承 [[Thread]] 类
|
||||
- 实现 Runnable
|
||||
- 通过 ExecutorService 和 Callable\<Class>
|
||||
|
||||
[[线程池]]工作原理
|
||||
|
||||
[[锁]]
|
||||
|
||||
线程[[上下文切换]]
|
||||
|
||||
[[阻塞队列]]
|
||||
|
||||
并发关键字
|
||||
|
||||
[[CountDownLatch]]
|
||||
|
||||
一个同步工具类, 允许一个或多个线程一直等待其他线程的操作执行完成后再执行相关操作
|
||||
|
||||
[[CyclicBarrier]]
|
||||
|
||||
让一组线程等待至某个状态后再全部同时执行
|
||||
|
||||
[[Semaphore]]
|
||||
|
||||
信号量, 用于控制同时访问某些资源的线程个数
|
||||
|
||||
多线程共享数据
|
||||
|
||||
1. 将数据抽象为一个类, 并将对这个数据的操作封装在类的方法中
|
||||
2. 将 Runnable 对象作为一个类的内部类, 将共享数据作为这个类的成员变量
|
||||
|
||||
[[ConcurrentHashMap]] 并发
|
||||
|
||||
减小锁的粒度, 使用多个 Segment
|
||||
|
||||
[[线程调度]]
|
||||
|
||||
[[CAS]]
|
||||
|
||||
[[AQS]]
|
||||
@@ -1,22 +0,0 @@
|
||||
[[并发编程线程基础]]
|
||||
|
||||
[[并发编程的其他基础知识]]
|
||||
|
||||
[[Java 并发包中 ThreadLocalRandom 类原理剖析]]
|
||||
|
||||
[[Java 并发包中原子操作类原理剖析]]
|
||||
|
||||
[[Java 并发包中并发 List 源码剖析]]
|
||||
|
||||
[[Java 并发包中锁原理剖析]]
|
||||
|
||||
[[Java 并发包中并发队列原理剖析]]
|
||||
|
||||
[[Java 并发包中线程池 ThreadPoolExecutor 原理探究]]
|
||||
|
||||
[[Java 并发包中 ScheduledThreadPoolExecutor 原理探究]]
|
||||
|
||||
[[Java 并发包中线程同步器原理剖析]]
|
||||
|
||||
[[Java 并发编程实战]]
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
## 并行流
|
||||
|
||||
1. 将顺序流转换为并行流,
|
||||
使用parallel方法
|
||||
|
||||
```java
|
||||
public static long parallelSum(long n) {
|
||||
return Stream.interate(1L, i -> i +1)
|
||||
.limit(n)
|
||||
.parallel()
|
||||
.reduce(0L, Long::sum);
|
||||
}
|
||||
```
|
||||
|
||||
通过sequential方法可以把并行流变成顺序流,
|
||||
并行流内部使用了默认的ForkJoinPool,默认线程数量为处理器数量
|
||||
|
||||
```java
|
||||
// 测试运行性能
|
||||
System.out.println("Parallel sum done in: "+ measureSumPerf(ParallelStreams::parallelSum, 10_000_000)+" msecs" );
|
||||
```
|
||||
|
||||
使用正确的书据结构可以保证其最佳性能,避免装箱开销,
|
||||
并行化本身并不是没有代价的,需要对流做递归划分,把每个子流的归纳操作分配到不同的线程
|
||||
|
||||
### 正确使用并行流
|
||||
|
||||
避免算法改变了某些共享状态,避免共享累加器这种共享可变状态
|
||||
|
||||
### 高效使用并行流
|
||||
|
||||
- 如果有疑问,测量
|
||||
- 留意装箱
|
||||
- 有些操作本身在并行流上的性能就比顺序流差
|
||||
- 考虑操作流水线的总计算成本
|
||||
- 对于较小的数据量,选择并行流几乎从来不是一个好的决定
|
||||
- 要考虑流背后的数据结构是否易于分解
|
||||
- 流自身的特点,以及流水线中的中间操作改变流的方式,都可能会改变分解过程的性能
|
||||
- 考虑终端操作中合并步骤的代价是大是小
|
||||
|
||||
## 分支/合并框架
|
||||
|
||||
目的为以递归的方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果,是ExecutorService接口的一个实现,把子任务分配给线程池(ForkJoinPool)中工作线程
|
||||
|
||||
1. 使用**RecursiveTask**
|
||||
|
||||
提交任务必须创建一个RecursiveTask\<R>的一个子类,
|
||||
R是并行化执行任务(以及所有子任务)产生的结果类型,
|
||||
如果不返回结果,是RecursiveAction类型,
|
||||
要定义RecursiveTask,实现它唯一的抽象方法compute
|
||||
|
||||
```java
|
||||
protected abstract R compute();
|
||||
```
|
||||
|
||||
这个方法定义了将任务拆分成子任务的逻辑,以及无法再拆或不便拆时生成单个子任务的逻辑
|
||||
|
||||
```
|
||||
if(任务足够小或不可分){
|
||||
顺序计算该任务
|
||||
} else {
|
||||
将任务分成两个子任务
|
||||
递归调用本方法,拆分每个子任务,等待所有子任务完成
|
||||
合并每个子任务的结果
|
||||
}
|
||||
```
|
||||
|
||||
### 使用分支/合并框架的最佳做法
|
||||
|
||||
- 对一个任务调用join犯法会阻塞调用方,直到该任务作出结果
|
||||
- 不应该在RescursiveTask内部使用ForkJoinPool的invoke方法,应该始终直接调用computer或fork方法
|
||||
- 对子任务调用fork方法可以把它排进ForkJoinPool
|
||||
- 调试使用分支/合并框架的并行计算可能有点棘手
|
||||
- 和并行流一样,不应理所当然认为在多核处理器上使用分支/合并框架比顺序计算快
|
||||
|
||||
### 工作窃取
|
||||
|
||||
每个子任务的执行时间都不一样,
|
||||
实际情况下可能会有一个线程早早完成了分配给它的任务,队列已近空了,而其他线程还在忙碌,
|
||||
这时,这个线程从随机选择一个线程,从队列尾巴上“偷走一个任务”,
|
||||
这个过程一直持续到所有任务执行完成
|
||||
|
||||
## Spliterator
|
||||
|
||||
可分迭代器,为了并行执行而设计的
|
||||
|
||||
```java
|
||||
public interface Spliterator<T> {
|
||||
boolean tryAdvance(Consumer<? super T> action);
|
||||
Spliterator<T> trySplit();
|
||||
long estimateSize();
|
||||
int characteristics();
|
||||
}
|
||||
```
|
||||
|
||||
拆分过程
|
||||
|
||||
对第一个Spliterator调用trysplit,生成第二个Spliterator,
|
||||
对两个Spliterator调用trysplit,生成4各spliterator,
|
||||
不断调用trysplit,直到返回null。
|
||||
|
||||
Spliterator的特性
|
||||
|
||||
最后一个方法characteristics,返回一个int,代表Spliterator本身特性集的编码
|
||||
@@ -1,93 +0,0 @@
|
||||
## JVM 运行机制
|
||||
|
||||
1. Java 源文件被编译器编译为字节码文件
|
||||
2. JVM 将字节码文件编译为相应操作系统的机器码
|
||||
3. 机器码调用相应操作系统的本地方法库执行相应方法
|
||||
|
||||
## JVM 后台运行线程
|
||||
|
||||
- 虚拟机线程:虚拟机线程在 JVM 达到安全点时出现
|
||||
- 周期性任务线程:通过定时器调度线程来实现周期性操作的执行
|
||||
- GC 线程:GC 线程支持 JVM 中不同的垃圾回收活动
|
||||
- 编译器线程:运行时将字节码动态编译成本地平台机器码,是 JVM 跨平台的具体体现
|
||||
- 信号分发线程:接收发送到 JVM 的信号并调用 JVM 方法
|
||||
|
||||
## JVM 内存区域
|
||||
|
||||
**线程私有**
|
||||
|
||||
- [[程序计数器]]
|
||||
|
||||
用于存储当前运行线程所执行的字节码行号指示器,执行 Native 方法则为空(Undefined),唯一无内存溢出问题区域
|
||||
|
||||
- [[虚拟机栈]]
|
||||
|
||||
存储局部变量表,操作数栈,动态连接,方法出口等,描述Java方法的执行过程
|
||||
|
||||
- [[本地方法区]]
|
||||
|
||||
为Native方法服务
|
||||
|
||||
**线程共享**
|
||||
|
||||
- [[JVM 堆]]
|
||||
|
||||
运行时数据区,线程共享,[[新生代]]、[[老年代]]、[[永久代]]
|
||||
|
||||
- [[方法区]]
|
||||
|
||||
- 存储常量,静态变量,类信息,即时编译器编译后的机器码,运行时常量池
|
||||
|
||||
**[[直接内存]]**
|
||||
|
||||
也叫对外内存, 不是 JVM 运行时数据区的一部分,NIO 模块提供对应的操作,可通过堆外内存避免 Java 堆与 Native 堆来回复制数据的性能和资源消耗,高并发场景下广泛使用
|
||||
|
||||
[[垃圾回收算法]]
|
||||
|
||||
4 种引用类型
|
||||
|
||||
[[强引用]]
|
||||
|
||||
把一个对象赋值给一个引用变量,强引用对象一定为可达性状态,不会被垃圾回收
|
||||
|
||||
[[软引用]]
|
||||
|
||||
只有在系统内存不足时会被回收
|
||||
|
||||
[[弱引用]]
|
||||
|
||||
只要垃圾回收就一定会被回收
|
||||
|
||||
[[虚引用]]
|
||||
|
||||
和应用队列联合使用,主要用于跟踪对象的垃圾回收状态,仅仅是为了被回收时获得一个通知
|
||||
|
||||
[[垃圾收集器]]
|
||||
|
||||
新生代
|
||||
|
||||
- [[Serial收集器]],单线程复制算法
|
||||
- [[ParNew]],多线程复制算法
|
||||
- [[Parallel Scavenge]],多线程复制算法
|
||||
|
||||
老年代
|
||||
|
||||
- [[CMS]],多线程标记清除算法
|
||||
- [[Serial Old]], 单线程标记整理算法
|
||||
- [[Parallel Old]],多线程标记整理算法
|
||||
|
||||
[[Garbage First]],多线程标记整理算法
|
||||
|
||||
网络编程模型
|
||||
|
||||
阻塞 I/O
|
||||
|
||||
非阻塞 I/O
|
||||
|
||||
多路复用 I/O
|
||||
|
||||
信号驱动 I/O
|
||||
|
||||
异步 I/O
|
||||
|
||||
[[类加载机制]]
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 135 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 131 KiB |
@@ -1,125 +0,0 @@
|
||||
## MySQL 逻辑架构
|
||||
|
||||
![[Pasted image 20230708181100.png]]
|
||||
|
||||
### 连接管理与安全性
|
||||
|
||||
默认情况下,每个客户端连接在服务器进程中拥有一个线程,服务器维护了一个缓冲区,用于存放已就绪的线程
|
||||
|
||||
当客户端连接时,服务器需要对其进行身份验证,基于用户名,发起主机名和密码,连接成功后验证器权限
|
||||
|
||||
### 优化与执行
|
||||
|
||||
解析查询以创建内部数据结构,然后对其进行优化,包括重写查询,决定表的读取顺序,选择何时的索引
|
||||
|
||||
## 并发控制
|
||||
|
||||
### 读写锁
|
||||
|
||||
[[共享锁]]和[[排他锁]]
|
||||
|
||||
资源上的读锁是共享的,多个客户端可以同时读取一个资源而互不干扰,
|
||||
写锁是排他的,一个写锁即会阻塞读锁也会阻塞其它的写锁,只有这样才能保证特定的时间点只有一个客户端执行写入,防止其它客户端读取正在写入的资源
|
||||
|
||||
锁的粒度
|
||||
|
||||
[[表锁]]
|
||||
|
||||
MySQL 中最基本也是开销最小的锁策略,锁定整张表
|
||||
|
||||
[[行级锁]]
|
||||
|
||||
可以最大程度地支持并发处理,也带来了最大的锁开销,锁定某一行
|
||||
|
||||
## 事务
|
||||
|
||||
### ACID
|
||||
|
||||
[[原子性]]
|
||||
|
||||
一个事物必须被视为一个不可分割的工作单元,整个事务中的所有操作要么全部提交成功,要么全部回滚失败
|
||||
|
||||
[[一致性]]
|
||||
|
||||
数据库总是从一个一致性状态转换到下一个一致性状态
|
||||
|
||||
[[隔离性]]
|
||||
|
||||
一个事务所做的修改在最终提交前,对其它事务是不可见的
|
||||
|
||||
[[持久性]]
|
||||
|
||||
一旦提交,事务所做的修改就会被永久保存到数据库中
|
||||
|
||||
### 隔离级别
|
||||
|
||||
[[READ UNCOMMITTED]] 未提交读
|
||||
|
||||
在事务中可以查看其他事务中还没有提交的修改,读取未提交的数据,也称为脏读
|
||||
|
||||
[[READ COMMITTED]] 提交读
|
||||
|
||||
一个事物可以看到其它事务在它开始之后提交的修改,但在该事务提交前,其所做的任何修改对其他事务都是不可见的,依然允许不可重复读
|
||||
|
||||
[[REPEATABLE READ]] 可重复读
|
||||
|
||||
保证了在同一个事务中多次读取相同行数据的结果是一样的
|
||||
|
||||
[[SERIALIZABLE]] 可串行化
|
||||
|
||||
强制事务按序执行
|
||||
|
||||
### 死锁
|
||||
|
||||
指两个或多个事务相互持有和请求相同资源上的锁,产生了循环依赖
|
||||
|
||||
### 事务日志
|
||||
|
||||
存储引擎秩序更改内存中的数据副本,不用修改磁盘中的表,然后把更改的记录写入事务日志中,事务日志会持久化保存到硬盘上
|
||||
|
||||
### MySQL 中的事务
|
||||
|
||||
AUTOCOMMIT
|
||||
|
||||
默认情况下,单个 INSERT、UPDATE、DELETE 语句会被隐式包装到一个事务中执行并在成功后提交,
|
||||
通过禁用该模式,可以在事务中执行一系列语句,并在结束时执行 COMMIT 或 ROLLBACK
|
||||
|
||||
MySQL 事务是由下层的存储引擎实现的,在同一个事务中,混合使用多种存储引擎是不可靠的
|
||||
|
||||
> 最好不要在应用程序中混合使用存储引擎。失败的事务可能导致不一致的结果,因为某些部分可以回滚,而其他部分不能回滚
|
||||
|
||||
隐式锁定和显示锁定
|
||||
|
||||
InnoDB 使用两阶段锁定协议,事务执行期间,随时都可以获得锁,但是锁只有在提交和回滚后才会释放,并且所有的锁会同时释放
|
||||
|
||||
> LOCK TABLES 命令和事务之间的交互非常复杂,并且在一些服务器版本中存在意想不到的行为。因此,本书建议,除了在禁用 AUTOCOMMIT 的事务中可以使用之外,其他任何时候都不要显式地执行 LOCK TABLES,不管使用的是什么存储引擎
|
||||
|
||||
## 多版本并发控制
|
||||
|
||||
[[MMVC]] 多版本并发控制
|
||||
|
||||
MVCC 仅适用于 REPEATABLE READ 和 READ COMMITTED 隔离级别
|
||||
|
||||
## 复制
|
||||
|
||||
源节点为每个副本提供一个线程,该线程作为复制客户端登录,写入发生时会被唤醒,发送新数据
|
||||
|
||||
## 数据文件结构
|
||||
|
||||
表的元数据重新设计为一种数据字典,包含在表的 ibd 文件中,操作期间引入了字典对象缓存
|
||||
|
||||
## InnoDB 引擎
|
||||
|
||||
默认事务型存储引擎,为处理大量短期事务而设计的
|
||||
|
||||
> 最佳实践是使用 InnoDB 存储引擎作为所有应用程序的默认引擎。在好几个大版本之前,MySQL 已经将 InnoDB 作为默认引擎,这让事情变得简单了
|
||||
|
||||
使用 MMVC 来实现高并发性,实现了 4 个标准隔离级别
|
||||
|
||||
基于聚簇索引构建的,提供了非常快的主键查找
|
||||
|
||||
JSON 文档支持
|
||||
|
||||
删除了基于文件的表元数据存储
|
||||
|
||||
引入了原子数据定义更改
|
||||
@@ -1,2 +0,0 @@
|
||||
什么是合规性
|
||||
建立合规控制体系
|
||||
@@ -1,51 +0,0 @@
|
||||
## Performance Scheme 介绍
|
||||
|
||||
[[程序插桩]] instrument
|
||||
|
||||
在 MySQL 代码中插入探测代码,以获取我们想了解的数据
|
||||
|
||||
[[消费者表]] Consumer
|
||||
|
||||
存储关于程序插桩代码的表
|
||||
|
||||
### 插桩元件
|
||||
|
||||
performance_schema 中,setup_instrument 表包含所有支持插桩的列表
|
||||
|
||||
- statement/sql/select
|
||||
- wait/synch/mutex/innodb/autoinc_mutex
|
||||
|
||||
## 配置
|
||||
|
||||
### 启用或禁用插桩
|
||||
|
||||
- 使用 setup_instruments 表
|
||||
- 调用 sys schema 中的 ps_setup_enable_instrument 存储过程
|
||||
- 使用 performance-schema-instrumet 启动参数
|
||||
|
||||
### 启用或禁用消费者表
|
||||
|
||||
- 使用 Performance Schema 中的 setup_consumers 表
|
||||
- 调用 sys schema 中的 ps_setup_enable_condumer 或 ps_setup_disable_consuper 存储过程
|
||||
- 使用 performance-schema-consumer 启动参数
|
||||
|
||||
## 使用 Performance Scheme
|
||||
|
||||
检查 SQL 语句
|
||||
|
||||
检查读写性能
|
||||
|
||||
检查元数据锁
|
||||
|
||||
检查内存使用情况
|
||||
|
||||
检查变量
|
||||
|
||||
- 服务器变量
|
||||
- 状态变量
|
||||
- 用户变量
|
||||
|
||||
检查最常见的错误
|
||||
|
||||
检查 Performance Schema 自身
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
选择优化的数据类型
|
||||
MySQL schema 设计中的陷阱
|
||||
schema 管理
|
||||
@@ -1,2 +0,0 @@
|
||||
托管 MySQL
|
||||
虚拟机上的 MySQL
|
||||
@@ -1,43 +0,0 @@
|
||||
## MySQL 的配置是如何工作的
|
||||
|
||||
从命令行参数和配置文件中的设置项获取配置信息
|
||||
|
||||
> 需要永久使用的任何设置都应该写入全局配置文件,而不是在命令行中指定。否则会有风险,可能会在没有指定命令行选项的情况下意外启动服务器。将所有配置文件保存在一个地方也是一个好主意,这样可以方便地检查它们
|
||||
|
||||
配置的作用域,服务器范围(全局作用于),每个连接(会话作用域)
|
||||
|
||||
> 如果在服务器运行时设置变量的全局值,则当前会话和其他现有会话的值将不受影响。如果客户端依赖数据库长连接,请务必记住这一点。这是因为在创建连接时,会话值是从全局值初始化的。在每次更改后应该检查 SHOW GLOBAL VARIABLES 的输出,以确保其达到预期效果
|
||||
|
||||
## 什么不该做
|
||||
|
||||
按比例调优
|
||||
|
||||
## 创建MySQL配置文件
|
||||
|
||||
|
||||
|
||||
## 配置内存使用
|
||||
|
||||
每个连接打内存需求
|
||||
为操作系统保留内存
|
||||
InnoDB 缓冲池
|
||||
线程缓存
|
||||
|
||||
## 配置 MySQL 的 I/O 行为
|
||||
|
||||
InnoDB 事务日志
|
||||
日志缓冲区
|
||||
|
||||
> 改变 InnoDB 执行 I/O 操作的方式会极大地影响性能,所以在改变任何东西之前,一定要理解你在做什么
|
||||
|
||||
InnoDB 表空间
|
||||
|
||||
## 配置 MySQL 并发
|
||||
|
||||
|
||||
|
||||
## 安全设置
|
||||
|
||||
|
||||
|
||||
## 高级 InnoDB 设置
|
||||
@@ -1,3 +0,0 @@
|
||||
索引基础
|
||||
高性能的索引策略
|
||||
维护索引和表
|
||||
@@ -1,47 +0,0 @@
|
||||
### 可靠性对 DBA 团队的影响
|
||||
|
||||
### 定义服务水平目标
|
||||
|
||||
[[服务水平指标]] SLI
|
||||
|
||||
[[服务水平目标]] SLO
|
||||
|
||||
[[服务水平协议]] SLA
|
||||
|
||||
### 监控解决方案
|
||||
|
||||
**商业选项**
|
||||
|
||||
SolarWinds
|
||||
|
||||
**开源选项**
|
||||
|
||||
Percona(PMM), Performance Schema
|
||||
|
||||
> 连接风暴是指在生产系统中,应用程序层感知到查询延迟增加,并通过打开更多到数据库层的连接进行响应的情况。这可能会导致数据库负载显著增加,因为它要处理大量涌入的新连接,这会占用执行查询请求的资源。连接风暴可能导致 max_connections 中的可用连接突然减少,并增加数据库可用性的风险
|
||||
|
||||
> 设置复制延迟告警需要谨慎。对于复制延迟,可立即采取行动的补救措施并不总是可行的。另外,假如你没有从副本读取数据,考虑一下监控系统将复制延迟告警发送给某人是否会过于激进。告警,尤其是非工作时间的告警,对于接收人来说应该是需要立即采取行动的
|
||||
|
||||
功能分片(Functional sharding)是指将服务于特定业务功能的特定表分割到一个专用的集群中,以便单独管理该数据集的正常运行时间、性能甚至访问控制
|
||||
|
||||
水平分片(Horizontal sharding)是指当数据集的大小超过了可以在单个集群中可靠地提供服务的规模时,将它拆分为多个集群,并从多个节点提供数据,这依赖于某种查找机制来定位所需的数据子集
|
||||
|
||||
### 度量长期性能
|
||||
|
||||
了解业务节奏
|
||||
|
||||
有效地跟踪指标
|
||||
|
||||
- 为未来的容量做规划
|
||||
- 预见何时需要重大改进,何时增量修改就够了
|
||||
- 为运行基础架构增加的成本做规划
|
||||
|
||||
使用性能监控工具检查性能
|
||||
|
||||
对平均值说不
|
||||
|
||||
与百分位为友
|
||||
|
||||
长保留期和性能
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
什么是可扩展性
|
||||
读限制与写限制工作负载
|
||||
功能拆分
|
||||
使用读池扩展读
|
||||
排队机制
|
||||
使用分片扩展写
|
||||
@@ -1,40 +0,0 @@
|
||||
## 什么限制了MySQL的性能
|
||||
|
||||
CPU 耗尽,I/O 饱和,内存耗尽
|
||||
|
||||
## 如何为 MySQL 选择 CPU
|
||||
|
||||
- 低延迟(快速响应时间)
|
||||
- 高吞吐量
|
||||
|
||||
平衡内存和磁盘资源
|
||||
|
||||
缓存、读取和写入
|
||||
|
||||
- 多次写操作,一次刷新
|
||||
- I/O 合并
|
||||
|
||||
## 固态存储
|
||||
|
||||
|
||||
|
||||
## RAID 性能优化
|
||||
|
||||
在数据冗余,存储空间大小,缓存和速度方面提供一些帮助
|
||||
|
||||
- RAID 0
|
||||
- RAID 1
|
||||
- RAID 5
|
||||
- RAID 6
|
||||
- RAID 10
|
||||
- RAID 50
|
||||
|
||||
## 网络配置
|
||||
|
||||
一个典型的应用程序会进行很多次小的网络传输,每次传输都会有轻微的延迟
|
||||
|
||||
## 选择文件系统
|
||||
|
||||
WIndows,NTFS
|
||||
|
||||
GUN/Linux,ext4,xfs
|
||||
@@ -1,6 +0,0 @@
|
||||
为什么查询速度回慢
|
||||
慢查询基础:优化数据访问
|
||||
重构查询的方式
|
||||
查询执行的基础
|
||||
MySQL 查询优化器的局限性
|
||||
优化特定类型的查询
|
||||
@@ -1,26 +0,0 @@
|
||||
[[MySQL 架构]]
|
||||
|
||||
[[可靠性工程世界中的监控]]
|
||||
|
||||
[[Performance Scheme]]
|
||||
|
||||
[[操作系统和硬件优化]]
|
||||
|
||||
[[优化服务器设置]]
|
||||
|
||||
[[scheme设计与管理]]
|
||||
|
||||
[[创建高性能的索引]]
|
||||
|
||||
[[查询性能优化]]
|
||||
|
||||
[[复制]]
|
||||
|
||||
[[备份与恢复]]
|
||||
|
||||
[[扩展MySQL]]
|
||||
|
||||
[[云端的MySQL]]
|
||||
|
||||
[[MySQL的合规性]]
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
优点
|
||||
|
||||
- 高可重用性
|
||||
- 低耦合
|
||||
- 快速开发和便捷部署
|
||||
|
||||
系统架构
|
||||
|
||||
- [[核心控制器]]
|
||||
|
||||
MVC 框架的入口,负责接收和反馈 HTTP 请求
|
||||
|
||||
- [[拦截器]]
|
||||
|
||||
对进出模型的数据进行过滤,不依赖系统容器,只过滤 MVC 框架内的业务数据
|
||||
|
||||
- [[过滤器]]
|
||||
|
||||
Servlet 容器内的过滤器,实现对数据的过滤处理,由于是容器内的,因此必须依赖容器才能运行
|
||||
|
||||
- [[模型管理器]]
|
||||
|
||||
提供一个模型框架,该框架内所有的业务操作都应该是无状态的,不关心容器对象,如 Session、线程池
|
||||
|
||||
- [[视图管理器]]
|
||||
|
||||
管理所有的视图,例如提供多语言的视图等
|
||||
|
||||
- 辅助工具
|
||||
|
||||
就是一大堆的辅助管理工具,如文件管理、对象管理等
|
||||
@@ -1 +0,0 @@
|
||||
[[HTTP Status Codes]]
|
||||
@@ -1,13 +0,0 @@
|
||||
[[栈]]
|
||||
|
||||
[[队列]]
|
||||
|
||||
[[链表]]
|
||||
|
||||
[[二叉树]]
|
||||
|
||||
[[红黑树]]
|
||||
|
||||
[[散列表]]
|
||||
|
||||
[[位图]]
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
@@ -1,39 +0,0 @@
|
||||
> 在对象池中,对象一旦产生,必然有一个唯一的、可访问的状态标志该对象,而且池中的对象声明周期是由池容器决定,而不是由使用者决定的。
|
||||
|
||||
> Use sharing to support large numbers of fine-grained objects efficiently.(使用共享对象可有效地支持大量的细粒度的对象。)
|
||||
|
||||
细粒度对象
|
||||
|
||||
- 内部状态
|
||||
|
||||
内部状态是对象共享出来的信息,存储在享元对象内部且不会随环境改变而改变
|
||||
|
||||
- 外部状态
|
||||
|
||||
外部状态是对象得以依赖的一个标记,是随环境改变而改变的,不可用共享的状态,如一批对象的统一标识
|
||||
|
||||
|
||||
- Flyweight 抽象享元角色
|
||||
- ConcreteFlyweight 具体享元角色
|
||||
- UnsharedConcreteFlyweighy 不可共享的享元角色
|
||||
- FlyweightFactory 享元工厂
|
||||
|
||||
> 在程序开发中,确认只需要一次赋值的属性则设置为 final 类型,避免无意修改导致逻辑混乱,特别是 Session 级的常量或变量
|
||||
|
||||
优缺点
|
||||
|
||||
大大减少应用程序创建的对象,降低程序内存的占用,同时提高了系统复杂度
|
||||
|
||||
使用场景
|
||||
|
||||
- 系统中存在大量的相似对象
|
||||
- 细粒度的对象都具备较接近的外部状态,且内部状态与环境无关,也就是说对象没有特定身份
|
||||
- 需要缓冲池的场景
|
||||
|
||||
线程安全的问题
|
||||
|
||||
性能平衡
|
||||
|
||||
> 如果把一个对象作为 Map 类的键值,一定要确保重写了 equals 和 hashCode 方法,否则会出现通过键值搜索失败的情况,例如 map.get(object)、map.contains(object)等会返回失败的结果
|
||||
|
||||
外部状态最好以 Java 的基本类型(String、int)作为标志,可以大幅提升效率
|
||||
@@ -1,28 +0,0 @@
|
||||
Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)
|
||||
|
||||
- Subject 抽象主题角色
|
||||
- RealSubject 具体主题角色 (委托角色, 被代理角色),业务的具体执行者
|
||||
- Proxy 代理主题角色(委托类、代理类),负责对真实角色的应用
|
||||
|
||||
优点
|
||||
|
||||
- 指责清晰
|
||||
- 高扩展性
|
||||
- 智能化
|
||||
|
||||
扩张
|
||||
|
||||
普通代理
|
||||
|
||||
客户端只能访问代理角色,不能访问真实角色
|
||||
|
||||
强制代理
|
||||
|
||||
必须通过真实角色找到代理角色,否则不能访问
|
||||
|
||||
动态代理
|
||||
|
||||
在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象,
|
||||
AOP 核心就是动态代理机制
|
||||
|
||||
> 要实现动态代理的首要条件是:被代理类必须实现一个接口,回想一下前面的分析吧。当然了,现在也有很多技术如 CGLIB 可以实现不需要接口也可以实现动态代理的方式
|
||||
@@ -1,36 +0,0 @@
|
||||
- [[工厂方法模式]]
|
||||
- [[建造者模式]]
|
||||
- [[抽象工厂模式]]
|
||||
- [[单例模式]]
|
||||
- [[原型模式]]
|
||||
|
||||
## 工厂模式 VS 建造者模式
|
||||
|
||||
工厂模式注重的是整体对象的创建方法,
|
||||
建造者模式注重部件构建的过程,旨在一步一步地精确创造构建出一个复杂对象
|
||||
|
||||
> 通过工厂方法模式生产出对象,然后由客户端进行对象的其他操作,但是并不代表所有生产出的对象都必须具有相同的状态和行为,它是由产品所决定
|
||||
|
||||
区别
|
||||
|
||||
- 意图不同
|
||||
|
||||
工厂方法里关注的是一个产品整体,无须关心产品的各部分是如何创建出来的,
|
||||
建造者模式,一个具体的产品的产生是依赖各个部件的产生以及装配顺序,它关注的是"由零件一步一步地组装出产品对象"
|
||||
|
||||
- 产品复杂度不同
|
||||
|
||||
工厂方法创建的产品一般都是单一性质产品,而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象不同
|
||||
|
||||
如何选择?
|
||||
取决于我们在做系统时的意图,
|
||||
如果需要详细关注一个产品部件的生产、安装步骤,选择建造者,
|
||||
否则选工厂方法模式
|
||||
|
||||
## 抽象工厂模式 VS 建造者模式
|
||||
|
||||
抽象工厂模式实现对产品家族的创建,一个产品家族必须是这样的一系列产品:
|
||||
具有不同分类维度的产品组合,
|
||||
采用抽象工厂模式则是不关心构建过程,只关心产品由什么工厂生产即可。
|
||||
构建者模式要求按照指定的蓝图构建产品,主要目的是通过组装零配件而产生一个新产品
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
## 搬移 UNIX 的命令
|
||||
|
||||
[[责任链模式]]
|
||||
[[命令模式]]
|
||||
[[模板方法模式]]
|
||||
[[迭代器模式]]
|
||||
@@ -1,29 +0,0 @@
|
||||
> Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)
|
||||
|
||||
- Receive 接受者角色
|
||||
- Command 命令角色
|
||||
- Invoker 调用者角色
|
||||
|
||||
优点
|
||||
|
||||
- 类间解耦
|
||||
- 可扩展性
|
||||
- 结合其它模式(命令链模式,模板方法模式)会更优秀
|
||||
|
||||
缺点
|
||||
|
||||
Command 子类如果有 N 个命令,就会有 N 个子类,这个类膨胀的非常大
|
||||
|
||||
使用场景
|
||||
|
||||
只要认为是命令的地方就可以用命令模式,
|
||||
GUI 开发一个按钮的点击,
|
||||
模拟 DOS 命令,
|
||||
触发-反馈机制的处理
|
||||
|
||||
反悔问题
|
||||
|
||||
发出一个命令,要撤回
|
||||
|
||||
- 结合备忘录模式还原最后状态
|
||||
- 增加一个新的命令,实现事件的回滚
|
||||
@@ -1,33 +0,0 @@
|
||||
> Without violating encapsulation,capture and externalize an object's internal state so that the object can be restored to this state later.(在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。)
|
||||
|
||||
- Originator 发起人角色
|
||||
- Memento 备忘录角色
|
||||
- CaraTaker 备忘录管理员角色
|
||||
|
||||
使用场景
|
||||
|
||||
- 需要保存和恢复数据的相关状态场景
|
||||
- 提供一个可回滚的操作
|
||||
- 需要监控的副本场景
|
||||
- 数据库连接的事务管理
|
||||
|
||||
注意事项
|
||||
|
||||
- 备忘录的生命周期
|
||||
- 备忘录的性能
|
||||
|
||||
clone 方式的备忘录
|
||||
|
||||
> 使用 Clone 方式的备忘录模式,可以使用在比较简单的场景或者比较单一的场景中,尽量不要与其他的对象产生严重的耦合关系
|
||||
|
||||
多状态的备忘录模式
|
||||
|
||||
使用 HashMap 储存状态,用 BeanUtil 恢复
|
||||
|
||||
> 如果要设计一个在运行期决定备份状态的框架,则建议采用 AOP 框架来实现,避免采用动态代理无谓地增加程序逻辑复杂性
|
||||
|
||||
多备份的备忘录模式
|
||||
|
||||
> 内存溢出问题,该备份一旦产生就装入内存,没有任何销毁的意向,这是非常危险的。因此,在系统设计时,要严格限定备忘录的创建,建议增加 Map 的上限,否则系统很容易产生内存溢出情况
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
## 迷你版的交易系统
|
||||
|
||||
[[策略模式]]
|
||||
[[工厂方法模式]]
|
||||
[[门面模式]]
|
||||
@@ -1,46 +0,0 @@
|
||||
```java
|
||||
public abstract class AbstractHumanFactory {
|
||||
public abstract <T extends Human> T createHuman(Class<T> c);
|
||||
}
|
||||
|
||||
public class HumanFactory extends AbstractHumanFactory {
|
||||
public <T extends Human> T createHuman(Class<T> c){
|
||||
//定义一个生产的人种
|
||||
Human human=null; try {
|
||||
//产生一个人种
|
||||
human = (T)Class.forName(c.getName()).newInstance();
|
||||
} catch (Exception e) {
|
||||
System.out.println("人种生成错误!");
|
||||
}
|
||||
return (T)human;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
|
||||
|
||||
优点
|
||||
|
||||
- 良好的封装性,代码结构清晰
|
||||
- 扩展性非常优秀
|
||||
- 屏蔽产品类
|
||||
- 典型的解耦框架
|
||||
|
||||
使用场景
|
||||
|
||||
- new 一个对象的替代品,在所有需要生成对象的地方都可以使用
|
||||
- 需要灵活的、可扩展的框架时,可以考虑使用
|
||||
- 可以用在异构项目中
|
||||
- 使用在测试驱动开发的框架下
|
||||
|
||||
扩展
|
||||
|
||||
1. 缩小为简单工厂模式(静态工厂模式)
|
||||
2. 升级为多个工厂类
|
||||
|
||||
![[Pasted image 20230705222905.png]]
|
||||
|
||||
> 抽象方法中已经不再需要传递相关参数了,因为每一个具体的工厂都已经非常明确自己的职责:创建自己负责的产品类对象
|
||||
|
||||
3. 替代单例模式
|
||||
4. 延迟初始化
|
||||
@@ -1,21 +0,0 @@
|
||||
> 上面每个方法都有一个 this.sequence.clear(),估计你一看就明白。但是作为一个系统分析师或是技术经理一定要告诉项目成员,ArrayList 和 HashMap 如果定义成类的成员变量,那你在方法中的调用一定要做一个 clear 的动作,以防止数据混乱。如果你发生过一次类似问题的话,比如 ArrayList 中出现一个“出乎意料”的数据,而你又花费了几个通宵才解决这个问题,那你会有很深刻的印
|
||||
|
||||
> Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
|
||||
|
||||
- Product 产品类
|
||||
- Builder 抽象建造者
|
||||
- ConcreteBuilder 具体建造者
|
||||
- Director 导演雷
|
||||
|
||||
优点
|
||||
|
||||
- 封装性
|
||||
- 建造者独立,容易扩展
|
||||
- 便于控制细节风险
|
||||
|
||||
使用场景
|
||||
|
||||
- 相同的方法,不同的执行顺序,产生不同的事件结果
|
||||
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
|
||||
- 产品类非常复杂,或者产品类中的调用顺序
|
||||
- 对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时
|
||||
@@ -1,23 +0,0 @@
|
||||
![[Pasted image 20230705223350.png]]
|
||||
|
||||
> Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。)
|
||||
|
||||
![[Pasted image 20230705223627.png]]
|
||||
|
||||
> 有 N 个产品族,在抽象工厂类中就应该有 N 个创建方法
|
||||
>
|
||||
> 有 M 个产品等级就应该有 M 个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
|
||||
|
||||
优点
|
||||
|
||||
- 封装性
|
||||
- 产品族内的约束为非公开状态
|
||||
|
||||
缺点
|
||||
|
||||
产品族扩展非常困难,需要修改抽象类及实现类违反开闭原则,
|
||||
横向扩展容易,纵向扩展困难
|
||||
|
||||
使用场景
|
||||
|
||||
一个对象族(一组没有任何关系的对象)都有相同的约束
|
||||
@@ -1,24 +0,0 @@
|
||||
> Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦,使得两者可以独立地变化。)
|
||||
|
||||
- Abstraction 抽象化角色
|
||||
- Implementor 实现化角色
|
||||
- RefinedAbstraction 修正抽象化角色
|
||||
- ConcreteImplementor 具体实现化角色
|
||||
|
||||
优点
|
||||
|
||||
- 抽象和实现分离
|
||||
- 优秀的扩充能力
|
||||
- 实现细节对客户透明
|
||||
|
||||
使用场景
|
||||
|
||||
- 不希望或不适用使用继承的场景
|
||||
- 接口或抽象类不稳定的场景
|
||||
- 重用性要求比较高的场景
|
||||
|
||||
注意事项
|
||||
|
||||
主要考虑如何拆分抽象和实现,并不是一涉及继承就考虑该模式,
|
||||
意图还是对变化的封装,把可能变化的因素封装到最细,最小的逻辑单元中,避免风险扩散
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
> 在软件开发过程中,如果相同的一段代码复制过两次,就需要对设计产生怀疑,架构师要明确地说明为什么相同的逻辑要出现两次或更多次
|
||||
|
||||
> Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.(定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。)
|
||||
|
||||
AbstractClass 叫做抽象模板,方法分为两类:
|
||||
|
||||
- 基本方法,也叫基本操作,由子类实现的方法,在模板方法被调用
|
||||
- 模板方法,一般是一个具体的方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑
|
||||
|
||||
> 为了防止恶意的操作,一般模板方法都加上 final 关键字,不允许被覆写
|
||||
|
||||
> 抽象模板中的基本方法尽量设计为 protected 类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为 protected 类型。实现类若非必要,尽量不要扩大父类中的访问权限
|
||||
|
||||
|
||||
优点
|
||||
|
||||
- 封装不变部分,扩展可变部分
|
||||
- 提取公共部分代码,便于维护
|
||||
- 行为由父类控制,子类实现
|
||||
|
||||
缺点
|
||||
|
||||
抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法,但是模板方式模式却颠倒了
|
||||
|
||||
使用场景
|
||||
|
||||
- 多个子类由公有的方法,并且逻辑基本相同
|
||||
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节则由各个子类实现
|
||||
- 重构时,模板方法模式是一个经常使用的模式
|
||||
|
||||
扩展
|
||||
|
||||
在抽象模板内部加开关(钩子方法)
|
||||
@@ -1,24 +0,0 @@
|
||||
> Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.(当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。)
|
||||
|
||||
- State 抽象状态角色
|
||||
- ConcreteState 具体状态角色
|
||||
- Context 环境角色
|
||||
- 把状态对象声明为常量,有几个状态对象就声明几个常量
|
||||
- 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式
|
||||
|
||||
优点
|
||||
|
||||
- 结构清晰
|
||||
- 遵循设计原则
|
||||
- 封装性非常好
|
||||
|
||||
缺点
|
||||
|
||||
子类太多,类膨胀
|
||||
|
||||
使用场景
|
||||
|
||||
- 行为随状态改变而改变
|
||||
- 条件、分支判断语句的替代者
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
> Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)
|
||||
|
||||
- Context 封装角色
|
||||
- Strategy 抽象策略角色
|
||||
- ConcretStrategy 具体策略角色
|
||||
|
||||
优点
|
||||
|
||||
- 算法可以自由切换
|
||||
- 避免使用多重条件判断
|
||||
- 扩展性良好
|
||||
|
||||
缺点
|
||||
|
||||
- 策略类数量增多
|
||||
- 所有的策略类都需要对外暴露
|
||||
|
||||
使用场景
|
||||
|
||||
- 多个类只有在算法和行为上稍有不同的场景
|
||||
- 算法需要自由切换的场景
|
||||
- 需要屏蔽算法规则的场景
|
||||
|
||||
如果一个策略家族的具体策略数量超过 4 个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题
|
||||
@@ -1,22 +0,0 @@
|
||||
> Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
|
||||
|
||||
- Component 抽象构件角色
|
||||
- Composite 树枝构件
|
||||
|
||||
优点
|
||||
|
||||
- 高层模块调用简单
|
||||
- 节点增加自由
|
||||
|
||||
缺点
|
||||
|
||||
树叶和树枝使用的定义直接使用了实现类,和依赖倒置原则冲突
|
||||
|
||||
使用场景
|
||||
|
||||
- 维护和展示部分-整体关系的场景,如树形菜单,文件和文件夹管理
|
||||
- 从一个整体中能够独立出部分模块或功能的场景
|
||||
|
||||
透明的组合模式
|
||||
|
||||
透明模式把用来组合的方法放到抽象类中
|
||||
@@ -1,34 +0,0 @@
|
||||
[[适配器模式]]
|
||||
[[桥梁模式]]
|
||||
[[组合模式]]
|
||||
[[装饰模式]]
|
||||
[[门面模式]]
|
||||
[[享元模式]]
|
||||
[[代理模式]]
|
||||
|
||||
## 代理模式 VS 装饰模式
|
||||
|
||||
装饰模式是代理模式的一个特殊应用,共同点是具有相同的接口,
|
||||
不同点是代理模式着重对代理过程的控制,装饰模式则是对类的功能进行加强和减弱,着重类的功能变化
|
||||
|
||||
## 装饰模式 VS 适配器模式
|
||||
|
||||
都是包装作用,通过委托方式实现其功能,装饰模式包装的是自己的兄弟类,隶属于同一个家族,适配器模式则修饰非血缘关系类,把一个非本家族的对象伪装成本家族的对象
|
||||
|
||||
最佳实践
|
||||
|
||||
- 意图不同
|
||||
|
||||
装饰模式意图是加强对象的功能,适配器模式关注的是转化
|
||||
|
||||
- 施于对象不同
|
||||
|
||||
装饰模式装饰的对象必须是自己的同宗,适配器模式必须是两个不同的对象
|
||||
|
||||
- 场景不同
|
||||
|
||||
装饰模式在任何时候都可以使用,适配器模式只是一个补救模式
|
||||
|
||||
- 扩展性不同
|
||||
|
||||
装饰模式很容易扩展,适配器模式建立容易,去掉比较困难
|
||||
@@ -1,73 +0,0 @@
|
||||
[[责任链模式]]
|
||||
[[命令模式]]
|
||||
[[解释器模式]]
|
||||
[[迭代器模式]]
|
||||
[[中介者模式]]
|
||||
[[备忘录模式]]
|
||||
[[状态模式]]
|
||||
[[策略模式]]
|
||||
[[模板方法模式]]
|
||||
[[访问者模式]]
|
||||
|
||||
## 命令模式 VS 策略模式
|
||||
|
||||
命令模式多了一个接收者角色,
|
||||
策略模式的意图是封装算法,它认为"算法"已经是一个完整的、不可拆分的原子业务,
|
||||
即其意图是让这些算法独立,并且可以相互替换,让行为的改变独立于拥有行为的客户;
|
||||
命令模式是对动作的解耦,把一个动作的执行分为执行对象(接收者)、执行行为(命令角色),让两者相互独立而不相互影响
|
||||
|
||||
区别
|
||||
|
||||
- 关注点不同
|
||||
|
||||
策略模式关注的是算法替换的问题,关注的是算法的完整性,封装性,只有具备了这两个条件才能保证其可以自由切换;
|
||||
命令模式关注的是解耦问题,如何让请求者解耦是它首先需要解决的,解耦的要就就是把请求的内容封装为一个一个的命令,由接收者执行
|
||||
|
||||
- 角色功能不同
|
||||
|
||||
策略模式中的具体算法是负责一个完整的算法逻辑,命令模式关注命令的实现,也就是功能的实现
|
||||
|
||||
- 使用场景不同
|
||||
|
||||
策略模式适用于算法要求变换的场景,命令模式适用于解耦两个由紧耦合关系的对象场合或者多命令撤销的场景
|
||||
|
||||
## 策略模式 VS 状态模式
|
||||
|
||||
策略模式封装的是不同的算法,算法之间没有交互,以达到短发可以自由切换的目的;
|
||||
状态模式封装的是不同的状态,以达到状态切换行为随之发生改变的目的
|
||||
|
||||
区别
|
||||
|
||||
- 环境角色的职责不同
|
||||
|
||||
两者都有一个叫做 Context 环境角色的类,策略模式的环境只是一个委托作用,负责算法的替换;
|
||||
环境模式的环境角色不仅仅是委托行为,还具有登记状态变化的功能,与具体的状态类协作,共同完成状态切换行为随之切换的任务
|
||||
|
||||
- 解决问题的重点不同
|
||||
|
||||
策略模式旨在解决内部算法如何改变的问题,也就是将内部算法的改变对外界的影响降低到最小,保证的是算法可以自由切换;
|
||||
状态模式旨在解决内在状态的改变而引起的行为改变的问题,出发点是事物的状态,封装状态而暴露行为,一个对象的状态改变,在外界来看就好像是行为改变
|
||||
|
||||
- 解决问题的方法不同
|
||||
|
||||
策略模式只是保证算法可以自由切换,什么时候用算法决定不了;
|
||||
状态模式对外暴露的是行为,状态的改变一般是由环境角色和具体状态共同完成的,也就是说状态模式封装了状态的变化而暴露了不同的行为或行为结果
|
||||
|
||||
- 应用场景不同
|
||||
|
||||
策略模式只是一个抽象算法的具体实现类,算法必须是平行的;
|
||||
状态模式要求是有状态且有行为的场景
|
||||
|
||||
- 复杂度不同
|
||||
|
||||
策略模式通常比较简单,状态模式通常比较复杂
|
||||
|
||||
## 观察者模式 VS 责任链模式
|
||||
|
||||
触发链模式
|
||||
|
||||
区别
|
||||
|
||||
- 链中的消息对象不同
|
||||
- 上下节点关系不同
|
||||
- 消息的分销渠道不同
|
||||
@@ -1,22 +0,0 @@
|
||||
> Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)
|
||||
|
||||
- Component 抽象构件
|
||||
- ConcreteComponent 具体构件
|
||||
- Decorator 装饰角色
|
||||
- 具体装饰角色
|
||||
|
||||
优点
|
||||
|
||||
- 装饰类和被装饰类可以独立发展
|
||||
- 装饰模式是继承关系的一个替代方案
|
||||
- 装饰模式可以动态扩展一个实现类的功能
|
||||
|
||||
缺点
|
||||
|
||||
多层的装饰是比较复杂的
|
||||
|
||||
使用场景
|
||||
|
||||
- 需要扩展一个类的功能,或给一个类增加附加功能
|
||||
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销
|
||||
- 需要为一批的兄弟类进行改装或加装功能
|
||||
@@ -1,10 +0,0 @@
|
||||
## 事件触发器的开发
|
||||
|
||||
> 采用单来源调用的两个对象一般是组合关系,两者有相同的生命期,它通常适用于有单例模式和工厂方法模式的场景中
|
||||
|
||||
> 设计原则只是一个理论,而不是一个带有刻度的标尺,因此在系统设计中不应该把它视为不可逾越的屏障,而是应该把它看成是一个方向标,尽量遵守,而不是必须恪守
|
||||
|
||||
[[工厂方法模式]]
|
||||
[[桥梁模式]]
|
||||
[[观察者模式]]
|
||||
[[中介者模式]]
|
||||
@@ -1,59 +0,0 @@
|
||||
也叫发布订阅模式
|
||||
|
||||
> Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)
|
||||
|
||||
- Subject 被观察着者
|
||||
- Observer 观察者
|
||||
- ConcreteSubject 具体被观察者
|
||||
- ConcreteObserver 具体观察者
|
||||
|
||||
优点
|
||||
|
||||
- 观察着和被观察者之间是抽象耦合
|
||||
- 建立一套触发机制
|
||||
|
||||
缺点
|
||||
|
||||
开发效率和运行效率问题,
|
||||
多级触发时的效率
|
||||
|
||||
使用场景
|
||||
|
||||
- 关联行为场景
|
||||
- 事件多级触发场景
|
||||
- 跨系统的消息交换场景,如消息队列的处理机制
|
||||
|
||||
注意事项
|
||||
|
||||
- 广播链的问题,
|
||||
消息最多只转发一次,只有一个对象即是观察者也是被观察者
|
||||
|
||||
> 它和责任链模式的最大区别就是观察者广播链在传播的过程中消息是随时更改的,它是由相邻的两个节点协商的消息结构;而责任链模式在消息传递过程中基本上保持消息不可变,如果要改变,也只是在原有的消息上进行修正
|
||||
|
||||
- 异步处理问题,
|
||||
观察者比较多,处理时间比较长,就需要用异步
|
||||
|
||||
Java 中的观察者模式
|
||||
|
||||
java. util. Observable 和 java. util. Oserver 这两个接口已经是可扩展的父类
|
||||
|
||||
项目中真实的观察者模式
|
||||
|
||||
- 观察者和被观察者之间的消息沟通
|
||||
|
||||
观察者中的 update 方法接收两个参数,一个是被观察者,一个是 DTO
|
||||
|
||||
- 观察者响应方式,
|
||||
观察者如何快速响应,
|
||||
一个是采用多线程,
|
||||
二是缓存技术
|
||||
|
||||
- 被观察者尽量自己做主
|
||||
|
||||
最佳实践
|
||||
|
||||
|
||||
- 文件系统
|
||||
- 猫鼠游戏
|
||||
- ATM 取钱
|
||||
- 广播收音机
|
||||
@@ -1,21 +0,0 @@
|
||||
> Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.(给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。)
|
||||
|
||||
- AbstractExpression 抽象解释器
|
||||
- TerminalExpression 终结符表达式
|
||||
- NonterminalExpression 非终结符表达式
|
||||
- Context 环境角色
|
||||
|
||||
优点
|
||||
|
||||
一个简单语法分析工具,扩展性好,修改语法规则只要修改相应的非终结符表达式,扩展语法只要增加非终结符类就可以了
|
||||
|
||||
缺点
|
||||
|
||||
- 引起类膨胀
|
||||
- 采用递归调用
|
||||
- 效率问题
|
||||
|
||||
使用场景
|
||||
|
||||
- 重复发生的问题
|
||||
- 一个简单语法需要解释的场景
|
||||
@@ -1 +0,0 @@
|
||||
[[底层网络协议]]
|
||||
@@ -1,52 +0,0 @@
|
||||
6 大设计原则
|
||||
|
||||
1. [[单一职责原则]]
|
||||
2. [[里氏替换原则]]
|
||||
3. [[依赖倒置原则]]
|
||||
4. [[接口隔离原则]]
|
||||
5. [[迪米特法则]]
|
||||
6. [[开闭原则]]
|
||||
|
||||
23 种设计模式
|
||||
|
||||
7. [[单例模式]]
|
||||
8. [[工厂方法模式]]
|
||||
9. [[抽象工厂模式]]
|
||||
10. [[模板方法模式]]
|
||||
11. [[建造者模式]]
|
||||
12. [[代理模式]]
|
||||
13. [[原型模式]]
|
||||
14. [[中介者模式]]
|
||||
15. [[命令模式]]
|
||||
16. [[责任链模式]]
|
||||
17. [[装饰模式]]
|
||||
18. [[策略模式]]
|
||||
19. [[适配器模式]]
|
||||
20. [[迭代器模式]]
|
||||
21. [[组合模式]]
|
||||
22. [[观察者模式]]
|
||||
23. [[门面模式]]
|
||||
24. [[备忘录模式]]
|
||||
25. [[访问者模式]]
|
||||
26. [[状态模式]]
|
||||
27. [[解释器模式]]
|
||||
28. [[享元模式]]
|
||||
29. [[桥梁模式]]
|
||||
|
||||
设计模式 PK
|
||||
|
||||
30. [[创建类模式大PK]]
|
||||
31. [[结构类模式大PK]]
|
||||
32. [[行为类模式大PK]]
|
||||
33. [[跨战区PK]]
|
||||
|
||||
设计模式混编
|
||||
|
||||
34. [[命令模式+策略模式]]
|
||||
35. [[工厂方法模式+策略模式]]
|
||||
36. [[观察者模式+中介模式]]
|
||||
|
||||
扩展篇
|
||||
|
||||
37. [[MVC框架]]
|
||||
38. [[新模式]]
|
||||
@@ -1,31 +0,0 @@
|
||||
> Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates. (封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。)
|
||||
|
||||
- Visitor 访问者角色
|
||||
- ConcreteVisitor 具体访问者
|
||||
- Element 抽象元素
|
||||
- ConcreteElement 具体抽象元素
|
||||
- ObjectStruct 结构对象
|
||||
|
||||
优点
|
||||
|
||||
- 符合单一职责原则
|
||||
- 优秀的扩展性
|
||||
- 灵活性非常高
|
||||
|
||||
缺点
|
||||
|
||||
- 具体元素对访问者公布细节
|
||||
- 具体元素变更比较困难
|
||||
- 违背了依赖倒置原则
|
||||
|
||||
使用场景
|
||||
|
||||
- 一个对象接结构包含很多类对象,它们拥有不同的接口,而你想对这些对象实施一些依赖于具体类的操作,也就是说用迭代器已经不能胜任的情况
|
||||
- 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作"污染"这些对象的类
|
||||
|
||||
统计功能
|
||||
|
||||
多个访问者
|
||||
|
||||
双分派
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
> Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)
|
||||
|
||||
> 在责任链模式中一个请求发送到链中后,前一节点消费部分消息,然后交由后续节点继续处理,最终可以有处理结果也可以没有处理结果,读者可以不用理会什么纯的、不纯的责任链模式。同时,请读者注意 handlerMessage 方法前的 final 关键字,可以阅读第10章的模板方法模式
|
||||
|
||||
优点
|
||||
|
||||
将请求与处理分开,请求者可以不知道谁处理的,处理者可以不用知道请求全貌
|
||||
|
||||
缺点
|
||||
|
||||
性能问题,每个请求都是链头遍历到链尾
|
||||
|
||||
调试不很方便
|
||||
|
||||
注意事项
|
||||
|
||||
链中节点数量需要控制,避免出现超长链的情况
|
||||
@@ -1,26 +0,0 @@
|
||||
## 策略模式 VS 桥梁模式
|
||||
|
||||
[[策略模式]]是一个行为模式,旨在封装一系列的行为,[[桥梁模式]]是解决在不破坏封装的情况下如何提取出它的抽象部分和实现部分
|
||||
|
||||
## 门面模式 VS 中介者模式
|
||||
|
||||
[[门面模式]]为复杂的提供一个同一的访问界面,定义的是一个高层接口;
|
||||
[[中介者模式]]使用一个中介对象来封装一系列同事对象的交互行为,使各对象之间不再显示地引用
|
||||
|
||||
区别
|
||||
|
||||
- 知晓状态不同,子系统不知道门面存在,每个同事类都知道中介者的存在
|
||||
- 封装程度不同,门面模式是一种简单的封装,所有请求处理委托给子系统完成,中介者模式需要有一个中心,由中心协调同事类完成
|
||||
|
||||
## 包装模式群 PK
|
||||
|
||||
[[代理模式]]主要用在不希望展现一个对象内部细节的场景中
|
||||
|
||||
[[装饰模式]]是一种特殊的代理模式,倡导的是在不改变接口的情况下位对象增强功能
|
||||
|
||||
[[适配器模式]]主要意图是接口转换,把一个对象的接口转换为系统希望的另外一个接口
|
||||
|
||||
[[桥梁模式]]是在抽象层产生耦合,解决的是自行扩展的问题
|
||||
|
||||
[[门面模式]]是一个粗粒度的封装,提供一个方便访问子系统的接口,不具有任何的业务逻辑
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
> Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.(它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。)
|
||||
|
||||
- Iterator 抽象迭代器
|
||||
- Concretelterator 具体迭代器
|
||||
- Aggregate 抽象容器
|
||||
- Concrete Aggregate 具体容器
|
||||
|
||||
> 开发系统时,迭代器的删除方法应该完成两个逻辑:一是删除当前元素,二是当前游标指向下一个元素
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)
|
||||
|
||||
- Target 目标角色
|
||||
- Adaptee 源角色
|
||||
- Adapter 适配器角色
|
||||
|
||||
优点
|
||||
|
||||
- 可以让两个没有任何关系的类在一起运行,只要适配器这个角色可以搞定他们就成
|
||||
- 增加了类的透明性
|
||||
- 提高了类的复用度
|
||||
- 灵活性非常好
|
||||
|
||||
使用场景
|
||||
|
||||
你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的模式,
|
||||
比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统的接口
|
||||
|
||||
详细设计阶段不要考虑,它是解决正在服役的项目问题
|
||||
@@ -1,28 +0,0 @@
|
||||
> Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。)
|
||||
|
||||
- Facade 门面角色
|
||||
- subsystem 子系统角色
|
||||
|
||||
优点
|
||||
|
||||
- 减少系统的相互依赖
|
||||
- 提高了灵活性
|
||||
- 提高安全性
|
||||
|
||||
缺点
|
||||
|
||||
不符合开闭模式,出现问题只能修改门面角色的代码
|
||||
|
||||
使用场景
|
||||
|
||||
- 为一个复杂的模块或子系统提供一个供外界访问的接口
|
||||
- 子系统相对独立——外界对子系统的访问只要黑箱操作即可
|
||||
- 预防低水平人员带来的风险扩散
|
||||
|
||||
注意事项
|
||||
|
||||
一个子系统可以有多个门面
|
||||
- 门面已经庞大到不能忍受的程度
|
||||
- 子系统可以提供不同访问路径
|
||||
|
||||
门面不参与子系统内的业务逻辑
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user