JavaScript设计模式实战

  最近在学习设计模式,真的感觉它是一个很悬的东西,就看文本真的很难看懂,所以我就打算用最习惯的 JavaScript 的代码,通过实现 用户管理系统 这一统一场景下的不同功能,使用不同的设计模式来帮助理解。

本文中对设计模式的描述来自此文档,更详细的关于设计模式的说明也可参考:设计模式 | 菜鸟教程

创建型模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

单例模式(Singleton Pattern)

意图:确保一个类只有一个实例,并提供一个全局访问点。

应用场景:用户系统中的全局用户状态管理器,避免用户信息在多个模块中被重复创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class UserManager {
static instance;
constructor() {
if (UserManager.instance) return UserManager.instance;
this.users = new Map();
UserManager.instance = this;
}
addUser(id, name) {
this.users.set(id, name);
}
}

const manager1 = new UserManager();
const manager2 = new UserManager();
console.log(manager1 === manager2); // true

工厂模式(Factory Pattern)

意图:通过工厂方法创建对象,避免直接使用 new,使对象创建逻辑集中、灵活。

应用场景:在用户管理系统中,不同类型的用户(普通用户、管理员、游客)拥有不同的权限,我们可以通过工厂来统一创建用户对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class User {
constructor(name) {
this.name = name;
this.role = 'user';
}
}

class Admin {
constructor(name) {
this.name = name;
this.role = 'admin';
}
}

class Guest {
constructor() {
this.name = 'Guest';
this.role = 'guest';
}
}

class UserFactory {
static createUser(type, name) {
switch (type) {
case 'admin':
return new Admin(name);
case 'guest':
return new Guest();
default:
return new User(name);
}
}
}

const admin = UserFactory.createUser('admin', 'Alice');
const guest = UserFactory.createUser('guest');
const user = UserFactory.createUser('user', 'Bob');

console.log(admin); // Admin { name: 'Alice', role: 'admin' }
console.log(guest); // Guest { name: 'Guest', role: 'guest' }
console.log(user); // User { name: 'Bob', role: 'user' }

抽象工厂模式(Abstract Factory Pattern)

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

应用场景:用户管理系统支持不同平台(Web 和 Mobile),不同平台上的用户组件(按钮、表单等)样式和行为不同,我们使用抽象工厂来统一创建它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 抽象产品
class WebButton {
render() { console.log('渲染 Web 按钮'); }
}
class MobileButton {
render() { console.log('渲染 Mobile 按钮'); }
}

class WebForm {
render() { console.log('渲染 Web 表单'); }
}
class MobileForm {
render() { console.log('渲染 Mobile 表单'); }
}

// 抽象工厂
class UIFactory {
createButton() {}
createForm() {}
}

// 具体工厂
class WebUIFactory extends UIFactory {
createButton() { return new WebButton(); }
createForm() { return new WebForm(); }
}

class MobileUIFactory extends UIFactory {
createButton() { return new MobileButton(); }
createForm() { return new MobileForm(); }
}

// 使用工厂
function renderUI(factory) {
const button = factory.createButton();
const form = factory.createForm();
button.render();
form.render();
}

renderUI(new WebUIFactory());
// 渲染 Web 按钮
// 渲染 Web 表单

renderUI(new MobileUIFactory());
// 渲染 Mobile 按钮
// 渲染 Mobile 表单

建造者模式(Builder Pattern)

意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

应用场景:注册用户时,可以选择性添加信息,比如昵称、头像、邮箱等,构建过程灵活。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class UserProfile {
constructor() {
this.data = {};
}
setName(name) {
this.data.name = name;
return this;
}
setAvatar(url) {
this.data.avatar = url;
return this;
}
setEmail(email) {
this.data.email = email;
return this;
}
build() {
return this.data;
}
}

const profile = new UserProfile()
.setName('Tom')
.setAvatar('avatar.jpg')
.setEmail('tom@example.com')
.build();

console.log(profile);
// { name: 'Tom', avatar: 'avatar.jpg', email: 'tom@example.com' }

原型模式(Prototype Pattern)

意图:通过复制已有对象来创建新对象,而不是通过类实例化。

应用场景:创建多个相似用户配置对象时,可以通过克隆的方式来快速复制。

1
2
3
4
5
6
7
8
9
10
11
12
13
const baseUser = {
role: 'user',
permissions: ['read'],
clone() {
return Object.assign({}, this);
}
};

const newUser = baseUser.clone();
newUser.name = 'Linda';

console.log(baseUser); // 原对象不变
console.log(newUser); // 拥有相同结构的新对象

结构型模式

这些模式关注对象之间的组合和关系,旨在解决如何构建灵活且可复用的类和对象结构。

适配器模式(Adapter Pattern)

意图:将一个类的接口转换成客户端期望的另一个接口。

应用场景:接入第三方用户系统,其返回字段与本地不一致,需要转换格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 第三方返回数据
const thirdUser = { uname: 'lucy', mail: 'lucy@mail.com' };

// 本地用户类
class LocalUser {
constructor(name, email) {
this.name = name;
this.email = email;
}
}

// 适配器
class UserAdapter {
static adapt(thirdData) {
return new LocalUser(thirdData.uname, thirdData.mail);
}
}

const localUser = UserAdapter.adapt(thirdUser);
console.log(localUser);

桥接模式(Bridge Pattern)

意图:将抽象与实现分离,使它们可以独立变化。

应用场景:用户通知模块支持多种发送方式(邮件、短信),不同平台用户可以使用不同方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 发送实现
class EmailSender {
send(msg) {
console.log('发送邮件:', msg);
}
}
class SMSSender {
send(msg) {
console.log('发送短信:', msg);
}
}

// 用户通知抽象类
class UserNotifier {
constructor(sender) {
this.sender = sender;
}
notify(message) {
this.sender.send(message);
}
}

const emailNotifier = new UserNotifier(new EmailSender());
const smsNotifier = new UserNotifier(new SMSSender());

emailNotifier.notify('欢迎注册!');
smsNotifier.notify('验证码:123456');

过滤器模式(Filter、Criteria Pattern)

意图:使用不同标准来过滤一组对象,并可组合多个标准。

应用场景:用户列表筛选功能,如按是否激活、角色等条件组合过滤。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const users = [
{ name: 'Tom', active: true, role: 'admin' },
{ name: 'Lucy', active: false, role: 'user' },
{ name: 'Mike', active: true, role: 'user' }
];

class ActiveFilter {
filter(users) {
return users.filter(u => u.active);
}
}
class RoleFilter {
constructor(role) {
this.role = role;
}
filter(users) {
return users.filter(u => u.role === this.role);
}
}

// 组合过滤器
class AndFilter {
constructor(...filters) {
this.filters = filters;
}
filter(users) {
return this.filters.reduce((result, f) => f.filter(result), users);
}
}

const activeUserFilter = new ActiveFilter();
const userRoleFilter = new RoleFilter('user');
const activeUsers = activeUserFilter.filter(users);
const activeUserRole = new AndFilter(activeUserFilter, userRoleFilter).filter(users);

console.log(activeUsers);
console.log(activeUserRole);

组合模式(Composite Pattern)

意图:将对象组合成树形结构以表示“部分-整体”的层次结构。

应用场景:权限管理系统中,角色可以由多个权限组合而成,甚至嵌套其他角色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Permission {
constructor(name) {
this.name = name;
}
display(indent = '') {
console.log(`${indent}- 权限:${this.name}`);
}
}

class Role {
constructor(name) {
this.name = name;
this.children = [];
}
add(child) {
this.children.push(child);
}
display(indent = '') {
console.log(`${indent}+ 角色:${this.name}`);
this.children.forEach(c => c.display(indent + ' '));
}
}

const read = new Permission('read');
const write = new Permission('write');
const editor = new Role('Editor');
editor.add(read);
editor.add(write);

const admin = new Role('Admin');
admin.add(editor);
admin.add(new Permission('delete'));

admin.display();

装饰器模式(Decorator Pattern)

意图:动态添加对象的额外功能。

应用场景:用户行为增强,如登录加上日志记录或权限验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class User {
constructor(name) {
this.name = name;
}
login() {
console.log(`${this.name} 登录成功`);
}
}

function withLogging(user) {
const originalLogin = user.login.bind(user);
user.login = () => {
console.log(`[LOG] ${user.name} 尝试登录`);
originalLogin();
};
return user;
}

const user = new User('Tom');
const enhancedUser = withLogging(user);
enhancedUser.login();

外观模式(Facade Pattern)

意图:为子系统提供一个统一的高层接口,使子系统更易使用。

应用场景:用户注册流程中,涉及多个服务,如验证、存储、通知,通过外观简化调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Validator {
static validate(user) {
return !!user.name && !!user.email;
}
}
class UserService {
static save(user) {
console.log('保存用户:', user);
}
}
class Notifier {
static notify(user) {
console.log('发送欢迎邮件给:', user.email);
}
}

// 外观
class RegisterFacade {
static register(user) {
if (!Validator.validate(user)) return console.log('注册失败:信息不完整');
UserService.save(user);
Notifier.notify(user);
}
}

const newUser = { name: 'Tom', email: 'tom@mail.com' };
RegisterFacade.register(newUser);

享元模式(Flyweight Pattern)

意图:共享对象,减少内存使用,提高性能。

应用场景:大量用户头像使用相同样式,可以复用样式对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class AvatarStyle {
constructor(color) {
this.color = color;
}
}

class AvatarFactory {
constructor() {
this.cache = new Map();
}
getStyle(color) {
if (!this.cache.has(color)) {
this.cache.set(color, new AvatarStyle(color));
}
return this.cache.get(color);
}
}

const factory = new AvatarFactory();
const style1 = factory.getStyle('blue');
const style2 = factory.getStyle('blue');
console.log(style1 === style2); // true

代理模式(Proxy Pattern)

意图:为其他对象提供一个代理以控制访问。

应用场景:限制对敏感数据的访问,如用户管理界面中,普通用户不可查看 admin 信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const realUser = {
name: 'admin',
getSecret() {
return '系统核心数据';
}
};

const proxyUser = new Proxy(realUser, {
get(target, prop) {
if (prop === 'getSecret') {
throw new Error('无权访问');
}
return target[prop];
}
});

try {
console.log(proxyUser.getSecret());
} catch (e) {
console.error(e.message);
}

行为型模式

这些模式关注对象之间的通信和交互,旨在解决对象之间的责任分配和算法的封装。

好的,以下是用户管理系统场景下,继续补充的行为型设计模式示例:

责任链模式(Chain of Responsibility Pattern)

意图:将请求的发送者和接收者解耦,让多个对象有机会处理请求。形成一条处理链,沿着链传递请求,直到有对象处理它。

应用场景:用户注册流程中,依次执行验证用户名、邮箱、密码等规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Handler {
setNext(handler) {
this.next = handler;
return handler;
}
handle(request) {
if (this.next) return this.next.handle(request);
return true;
}
}

class UsernameValidator extends Handler {
handle(user) {
if (!user.username) {
console.log('用户名不能为空');
return false;
}
return super.handle(user);
}
}

class EmailValidator extends Handler {
handle(user) {
if (!user.email.includes('@')) {
console.log('邮箱格式错误');
return false;
}
return super.handle(user);
}
}

class PasswordValidator extends Handler {
handle(user) {
if (user.password.length < 6) {
console.log('密码长度不能少于6位');
return false;
}
return super.handle(user);
}
}

const user = { username: 'Tom', email: 'tom@example.com', password: '123456' };
const chain = new UsernameValidator();
chain.setNext(new EmailValidator()).setNext(new PasswordValidator());

chain.handle(user); // 全部通过

命令模式(Command Pattern)

意图:将请求封装成对象,从而使你可用不同的请求、队列或日志请求,并支持可撤销操作。

应用场景:管理员对用户执行批量操作(冻结、解冻、删除等)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Command {
execute() {}
}

class FreezeUserCommand extends Command {
constructor(user) {
super();
this.user = user;
}
execute() {
console.log(`冻结用户:${this.user.name}`);
}
}

class DeleteUserCommand extends Command {
constructor(user) {
super();
this.user = user;
}
execute() {
console.log(`删除用户:${this.user.name}`);
}
}

class AdminInvoker {
constructor() {
this.history = [];
}
run(command) {
this.history.push(command);
command.execute();
}
}

const user = { name: 'Alice' };
const invoker = new AdminInvoker();

invoker.run(new FreezeUserCommand(user));
invoker.run(new DeleteUserCommand(user));

解释器模式(Interpreter Pattern)

意图:定义语言的语法,并构建一个解释器来解释语言中的句子。

应用场景:用户管理系统中,自定义查询语法解析,比如“role == ‘admin’ AND active == true”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Expression {
interpret(context) {}
}

class EqualsExpression extends Expression {
constructor(key, value) {
super();
this.key = key;
this.value = value;
}
interpret(context) {
return context[this.key] === this.value;
}
}

class AndExpression extends Expression {
constructor(expr1, expr2) {
super();
this.expr1 = expr1;
this.expr2 = expr2;
}
interpret(context) {
return this.expr1.interpret(context) && this.expr2.interpret(context);
}
}

const expr = new AndExpression(
new EqualsExpression('role', 'admin'),
new EqualsExpression('active', true)
);

const user1 = { role: 'admin', active: true };
const user2 = { role: 'user', active: true };

console.log(expr.interpret(user1)); // true
console.log(expr.interpret(user2)); // false

迭代器模式(Iterator Pattern)

意图:提供一种方法顺序访问一个集合对象中的各个元素,而不暴露其内部表示。

应用场景:遍历用户列表的不同过滤条件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class UserCollection {
constructor(users) {
this.users = users;
}
createIterator() {
let index = 0;
const users = this.users;
return {
next: () => {
if (index < users.length) {
return { value: users[index++], done: false };
}
return { done: true };
}
};
}
}

const users = [
{ name: 'Tom' },
{ name: 'Jerry' },
{ name: 'Alice' }
];

const collection = new UserCollection(users);
const iterator = collection.createIterator();

let result = iterator.next();
while (!result.done) {
console.log(result.value.name);
result = iterator.next();
}

中介者模式(Mediator Pattern)

意图:用一个中介对象封装一系列对象之间的交互。中介者使对象不需要显式地相互引用,从而使耦合松散。

应用场景:用户系统中,组件之间(如注册、通知、日志)通过中介通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class Mediator {
constructor() {
this.components = {};
}
register(name, component) {
this.components[name] = component;
component.setMediator(this);
}
notify(sender, event) {
if (event === 'register') {
this.components.logger.log('用户注册成功');
this.components.notifier.notify('欢迎新用户');
}
}
}

class Component {
setMediator(mediator) {
this.mediator = mediator;
}
}

class RegisterComponent extends Component {
registerUser(name) {
console.log(`注册用户:${name}`);
this.mediator.notify(this, 'register');
}
}

class LoggerComponent extends Component {
log(message) {
console.log(`[LOG]: ${message}`);
}
}

class NotifierComponent extends Component {
notify(message) {
console.log(`[通知]: ${message}`);
}
}

const mediator = new Mediator();
const register = new RegisterComponent();
const logger = new LoggerComponent();
const notifier = new NotifierComponent();

mediator.register('register', register);
mediator.register('logger', logger);
mediator.register('notifier', notifier);

register.registerUser('Linda');

备忘录模式(Memento Pattern)

意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在之后恢复。

应用场景:编辑用户信息时支持撤销操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class User {
constructor(name) {
this.name = name;
}
save() {
return new Memento(this.name);
}
restore(memento) {
this.name = memento.getState();
}
}

class Memento {
constructor(state) {
this.state = state;
}
getState() {
return this.state;
}
}

class Caretaker {
constructor() {
this.history = [];
}
backup(memento) {
this.history.push(memento);
}
undo() {
return this.history.pop();
}
}

const user = new User('Tom');
const caretaker = new Caretaker();

caretaker.backup(user.save());
user.name = 'Tommy';

console.log(user.name); // Tommy

user.restore(caretaker.undo());
console.log(user.name); // Tom

观察者模式(Observer Pattern)

意图:当一个对象状态发生改变时,自动通知所有依赖它的对象。

应用场景:当用户状态变更时(如登录、登出),通知多个子系统同步更新状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
this.observers = this.observers.filter(o => o !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}

class Logger {
update(data) {
console.log(`[Logger] 用户状态变更: ${data}`);
}
}

class UI {
update(data) {
console.log(`[UI] 更新界面,当前状态: ${data}`);
}
}

const userStatus = new Subject();
const logger = new Logger();
const ui = new UI();

userStatus.subscribe(logger);
userStatus.subscribe(ui);

userStatus.notify('已登录');

状态模式(State Pattern)

意图:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

应用场景:根据用户的登录状态,切换系统对其的响应行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class LoggedOutState {
handle() {
console.log('请先登录');
}
}

class LoggedInState {
handle() {
console.log('欢迎回来');
}
}

class UserContext {
constructor() {
this.state = new LoggedOutState();
}
setState(state) {
this.state = state;
}
request() {
this.state.handle();
}
}

const user = new UserContext();
user.request(); // 请先登录
user.setState(new LoggedInState());
user.request(); // 欢迎回来

空对象模式(Null Object Pattern)

意图:用一个空对象来代替 null,避免客户端做空判断。

应用场景:查询不到用户时返回一个空用户对象,避免后续代码出错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class RealUser {
constructor(name) {
this.name = name;
}
display() {
console.log(`用户:${this.name}`);
}
}

class NullUser {
display() {
console.log('无此用户');
}
}

function getUser(name) {
const users = ['Tom', 'Alice'];
if (users.includes(name)) return new RealUser(name);
return new NullUser();
}

const user1 = getUser('Tom');
const user2 = getUser('John');

user1.display(); // 用户:Tom
user2.display(); // 无此用户

策略模式(Strategy Pattern)

意图:定义一系列算法,把它们封装起来,使它们可以互换。

应用场景:不同的用户登录方式(邮箱、手机号、第三方)通过策略切换处理逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class EmailStrategy {
login(user) {
console.log(`使用邮箱登录:${user.email}`);
}
}

class PhoneStrategy {
login(user) {
console.log(`使用手机号登录:${user.phone}`);
}
}

class LoginContext {
setStrategy(strategy) {
this.strategy = strategy;
}
login(user) {
this.strategy.login(user);
}
}

const user = { email: 'a@example.com', phone: '123456789' };
const context = new LoginContext();

context.setStrategy(new EmailStrategy());
context.login(user);

context.setStrategy(new PhoneStrategy());
context.login(user);

模板方法模式(Template Pattern)

意图:在一个方法中定义算法的骨架,而将一些步骤延迟到子类中。

应用场景:不同用户注册流程类似,但某些步骤略有不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class UserRegistration {
register() {
this.inputInfo();
this.verifyIdentity();
this.save();
}
inputInfo() {
throw new Error('需要实现 inputInfo 方法');
}
verifyIdentity() {
console.log('默认身份验证');
}
save() {
console.log('保存用户信息');
}
}

class GuestRegistration extends UserRegistration {
inputInfo() {
console.log('输入游客信息');
}
}

class AdminRegistration extends UserRegistration {
inputInfo() {
console.log('输入管理员信息');
}
verifyIdentity() {
console.log('执行高级身份验证');
}
}

new GuestRegistration().register();
new AdminRegistration().register();

访问者模式(Visitor Pattern)

意图:在不改变元素类的前提下定义作用于元素的新操作。

应用场景:对用户对象执行不同操作,比如导出信息、统计分析等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class User {
constructor(name) {
this.name = name;
}
accept(visitor) {
visitor.visit(this);
}
}

class ExportVisitor {
visit(user) {
console.log(`导出用户信息:${user.name}`);
}
}

class StatsVisitor {
visit(user) {
console.log(`统计用户数据:${user.name}`);
}
}

const user = new User('Tom');
user.accept(new ExportVisitor());
user.accept(new StatsVisitor());

这些示例代码配合实际应用场景,应该能更好地帮助你理解设计模式的用途和写法。如果你希望我将这些内容整理成一个完整可复制的 Markdown 文档,我也可以继续处理。

你接下来是想整理输出所有模式,还是继续补充 J2EE 模式那部分?

J2EE 模式(表示层模式)

这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。

虽然这些模式源自 Java EE,但在现代前端/后端分离架构中依然有应用场景。

MVC 模式(Model-View-Controller Pattern)

意图:将数据(Model)、视图(View)和控制逻辑(Controller)分离,提高代码组织性。

应用场景:用户管理系统的前端页面组织。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Model
class UserModel {
constructor() {
this.users = ['Tom', 'Alice'];
}
getUsers() {
return this.users;
}
}

// View
class UserView {
render(users) {
console.log('用户列表:', users.join(', '));
}
}

// Controller
class UserController {
constructor(model, view) {
this.model = model;
this.view = view;
}
showUsers() {
const users = this.model.getUsers();
this.view.render(users);
}
}

const model = new UserModel();
const view = new UserView();
const controller = new UserController(model, view);

controller.showUsers();

业务代表模式(Business Delegate Pattern)

意图:为表示层客户端提供统一访问业务服务的接口,减少表示层和业务层的耦合。

应用场景:页面组件通过统一接口访问用户服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class UserService {
getUser(id) {
return { id, name: 'Tom' };
}
}

class BusinessDelegate {
constructor() {
this.userService = new UserService();
}
getUser(id) {
return this.userService.getUser(id);
}
}

// 表示层
class Client {
constructor(delegate) {
this.delegate = delegate;
}
showUser(id) {
const user = this.delegate.getUser(id);
console.log('用户信息:', user);
}
}

const delegate = new BusinessDelegate();
const client = new Client(delegate);
client.showUser(1);

组合实体模式(Composite Entity Pattern)

意图:用于表示一个由多个对象组成的复杂数据模型。

应用场景:一个用户对象包括多个子对象,如基本信息、权限、设置等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class UserInfo {
constructor(name) {
this.name = name;
}
}

class UserSetting {
constructor(theme) {
this.theme = theme;
}
}

class UserCompositeEntity {
constructor(name, theme) {
this.userInfo = new UserInfo(name);
this.userSetting = new UserSetting(theme);
}
getData() {
return {
name: this.userInfo.name,
theme: this.userSetting.theme
};
}
}

const userEntity = new UserCompositeEntity('Alice', 'dark');
console.log(userEntity.getData());

数据访问对象模式(DAO Pattern)

意图:将数据库操作和业务逻辑分离,封装对数据源的访问。

应用场景:封装用户数据的读写逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class UserDAO {
constructor() {
this.users = new Map();
}
save(user) {
this.users.set(user.id, user);
}
find(id) {
return this.users.get(id);
}
}

const dao = new UserDAO();
dao.save({ id: 1, name: 'Tom' });
console.log(dao.find(1)); // { id: 1, name: 'Tom' }

前端控制器模式(Front Controller Pattern)

意图:提供单一入口处理请求,统一处理认证、日志等。

应用场景:前端路由或 API 请求的统一入口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Dispatcher {
dispatch(request) {
console.log(`处理请求:${request}`);
}
}

class FrontController {
constructor() {
this.dispatcher = new Dispatcher();
}
handleRequest(request) {
console.log('日志记录:', request);
this.dispatcher.dispatch(request);
}
}

const controller = new FrontController();
controller.handleRequest('查看用户列表');

拦截过滤器模式(Intercepting Filter Pattern)

意图:在请求到达目标对象前进行预处理,如认证、日志记录。

应用场景:在访问用户数据前执行权限校验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class AuthFilter {
execute(request) {
console.log(`权限检查:${request}`);
}
}

class LogFilter {
execute(request) {
console.log(`请求日志:${request}`);
}
}

class FilterChain {
constructor() {
this.filters = [];
this.target = null;
}
addFilter(filter) {
this.filters.push(filter);
}
setTarget(target) {
this.target = target;
}
execute(request) {
this.filters.forEach(f => f.execute(request));
this.target.execute(request);
}
}

class Target {
execute(request) {
console.log(`处理请求:${request}`);
}
}

const filterChain = new FilterChain();
filterChain.addFilter(new AuthFilter());
filterChain.addFilter(new LogFilter());
filterChain.setTarget(new Target());

filterChain.execute('删除用户');

服务定位器模式(Service Locator Pattern)

意图:隐藏服务的创建逻辑,通过名称查找服务。

应用场景:统一注册和查找服务,如用户服务、日志服务等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ServiceLocator {
constructor() {
this.services = new Map();
}
register(name, service) {
this.services.set(name, service);
}
getService(name) {
return this.services.get(name);
}
}

class UserService {
execute() {
console.log('执行用户服务');
}
}

const locator = new ServiceLocator();
locator.register('userService', new UserService());
locator.getService('userService').execute();

传输对象模式(Transfer Object Pattern)

意图:使用简单对象封装数据,用于网络或模块之间传输。

应用场景:用户模块将用户数据封装为 DTO(Data Transfer Object)传给其他模块或前端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UserDTO {
constructor(id, name) {
this.id = id;
this.name = name;
}
}

class UserService {
getUserDTO() {
return new UserDTO(1, 'Tom');
}
}

const service = new UserService();
const userDTO = service.getUserDTO();
console.log('传输对象:', userDTO);

总结

本文中,围绕「用户管理系统」这个通用的业务场景,通过 JavaScript 代码演示了讲解了 23 种 GoF 设计模式 和 8 种 J2EE 模式,并结合 JavaScript 示例进行了实际演示。通过对设计模式的学习我们可以知道:

  1. 设计模式不是框架,而是思想

    每种模式的本质都是为了解决「重复出现的结构性问题」,它们不是强制要套的模板,而是我们在构建复杂系统时总结出的经验智慧。学习设计模式,是尝试去理解他们而不是死记硬背,这才是学习设计模式的关键。

  2. 场景驱动,理解更深

    设计模式真的很难通过语言来讲述,所以这篇文章才尝试着以用户管理为例,无论是添加用户、展示用户列表,还是用户的登录认证、权限控制、服务抽象……都有对应的设计模式提供灵感和规范。把设计模式用在实际业务中,才真正理解它的价值。

  3. JS 不是静态语言,也可以优雅地使用模式
    虽然 JavaScript 是动态语言,很多时候我们不用过度抽象,但设计模式依然能提升可读性、复用性和协作性。通过对象组合、闭包、类等手段,同样可以表达出清晰的结构和职责分离。

最后,列出一张简单的总览表吧:

类别 模式名称 主要意图 应用场景
创建型 单例模式 (Singleton) 保证一个类只有一个实例 全局配置、缓存、数据库连接、用户状态管理
工厂模式 (Factory) 创建对象由工厂统一管理 用户角色创建、日志系统、插件系统
抽象工厂 (Abstract Factory) 创建一族相关对象,保持产品一致性 UI 组件库(按钮 + 表单)、多平台适配
建造者模式 (Builder) 将复杂对象的构建过程封装,使构建与表示分离 用户注册配置、表单配置生成器
原型模式 (Prototype) 通过克隆已有对象创建新对象 克隆用户模板、复制设置项
结构型 适配器模式 (Adapter) 统一接口格式,实现兼容 第三方 API 接入、老旧系统接口兼容
桥接模式 (Bridge) 分离抽象与实现,解耦变化 消息发送(文本/图像)+ 渠道(微信/邮件)
过滤器模式 (Filter/Criteria) 使用多个标准过滤数据集合 用户搜索筛选、数据权限过滤
组合模式 (Composite) 将对象组合成树形结构,统一处理单个对象与组合对象 权限树、组织架构、菜单系统
装饰器模式 (Decorator) 动态添加行为,不修改原对象 登录功能增强、日志记录、数据校验
外观模式 (Facade) 提供统一接口,简化系统使用 用户注册流程封装、复杂子系统统一调用
享元模式 (Flyweight) 共享相似对象,节省内存 用户列表头像复用、大量标签复用
代理模式 (Proxy) 控制对象访问,可添加权限、延迟加载等功能 权限代理、缓存代理、懒加载图像
行为型 责任链模式 (Chain of Resp.) 请求沿链传递,直到某个对象处理 表单校验链、权限处理链
命令模式 (Command) 将请求封装成对象,支持撤销、排队等操作 操作历史、按钮动作、任务调度
解释器模式 (Interpreter) 定义语言语法,解释表达式 表达式解析器、权限规则 DSL
迭代器模式 (Iterator) 按序访问集合元素,隐藏内部实现 用户分页浏览、日志遍历
中介者模式 (Mediator) 对象通过中介解耦通信 聊天系统、组件交互协调
备忘录模式 (Memento) 保存和恢复对象状态 表单状态保存、草稿功能
观察者模式 (Observer) 一对多依赖,状态变化通知所有观察者 登录状态广播、数据变更通知
状态模式 (State) 对象行为随状态变化 用户账号状态(禁用/激活)、审批流程
空对象模式 (Null Object) 提供默认无操作对象,避免 null 判断 默认用户、日志记录器空实现
策略模式 (Strategy) 定义一系列算法或行为,动态替换 登录策略、计费方式、过滤条件
模板方法模式 (Template) 定义算法骨架,子类实现具体步骤 表单提交流程、导出流程
访问者模式 (Visitor) 封装对对象结构的操作,增加新行为无需修改结构 用户报告生成器、元素批量处理
J2EE 模式 MVC 模式 分离模型、视图、控制器 Web 应用架构、Vue/React 应用
业务代表模式 屏蔽表示层和业务层之间的交互细节 封装 API 请求层
组合实体模式 使用组合实体表示依赖关系的数据模型 复杂用户资料管理
DAO 模式 抽象和封装数据访问逻辑 封装数据库查询、用户持久化
前端控制器模式 统一请求处理入口 单页应用路由、请求中间层
拦截过滤器模式 预处理/后处理请求 登录验证、日志、XSS 过滤
服务定位器模式 查找服务对象,隐藏查找逻辑 动态依赖注入、插件定位
传输对象模式 使用对象封装数据传输内容 用户 DTO、前后端传参结构
作者

Fu9Zhou

发布于

2025-05-09

许可协议