1.工厂模式:
工厂模式是一类创建型设计模式,目的是把对象的创建过程从使用者代码中分离出来,降低耦合、集中管理创建逻辑、方便扩展与测试;
有简单工厂,抽象工厂,工厂方法等;
工厂模式的核心思想是:
1 2
| 依赖倒置原则(DIP) 高层模块不依赖低层模块,二者都依赖抽象
|
如果在Service中new 对象 , 那么Service类 就会依赖于这个对象类;
但是如果使用工厂模式,那么Service类和对象类就都依赖于工厂类,符合了依赖倒置原则;
实现了解耦:
在配置环境中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class LoggerFactory {
public static Logger createLogger(){ String type = Config.get("logger.type"); switch(type){ case "file": return new FileLogger(); case "console": return new ConsoleLogger(); } throw new RuntimeException(); }
}
|
就可以通过修改配置文件来实现不同逻辑,而不用去修改代码
例如简单工厂:
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
| public interface Shape { void draw(); }
public class Circle implements Shape { public void draw() { System.out.println("draw circle"); } } public class Rectangle implements Shape { public void draw() { System.out.println("draw rectangle"); } }
public class ShapeFactory { public static Shape create(String type) { return switch (type) { case "circle" -> new Circle(); case "rect" -> new Rectangle(); default -> throw new IllegalArgumentException("unknown type: " + type); }; } }
public class Main { public static void main(String[] args) { Shape s1 = ShapeFactory.create("circle"); s1.draw(); } }
|
现代/实用写法:注册式工厂(Java 8+)
如果你不想为每个产品写一堆工厂类,可以用 Map<String, Supplier<T>> 注册工厂函数,便于扩展与配置(更贴近现代代码风格)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.*; import java.util.function.Supplier;
public class RegistryFactory { private static final Map<String, Supplier<Shape>> map = new HashMap<>();
static { map.put("circle", Circle::new); map.put("rect", Rectangle::new); }
public static Shape create(String key) { Supplier<Shape> s = map.get(key); if (s == null) throw new IllegalArgumentException("unknown: " + key); return s.get(); }
public static void register(String key, Supplier<Shape> supplier) { map.put(key, supplier); } }
|
这种方式便于通过配置文件或反射在运行时注册新类型,适合插件式架构。
在 Java 8 中引入了一组函数式接口,用于支持 Lambda 表达式和函数式编程,其中 Supplier 就是非常重要的一个接口。Supplier 位于 java.util.function 包中,它表示一个数据提供者(生产者),特点是不接收任何参数,但是会返回一个结果。从接口定义可以看出它的设计非常简单,本质上就是一个“提供数据”的函数。源码如下:
1 2 3 4
| @FunctionalInterface public interface Supplier<T> { T get(); }
|
这里的泛型 T 表示返回的数据类型,而 get() 方法就是唯一的抽象方法。当调用 get() 时,就会返回一个对象。因此可以理解为:Supplier 的作用就是在需要的时候提供一个对象或数据。由于它只有一个抽象方法,因此它是一个典型的函数式接口,可以直接使用 Lambda 表达式 或 方法引用 来实现。例如:
1 2 3 4 5 6 7 8 9 10 11 12
| import java.util.function.Supplier;
public class Test { public static void main(String[] args) {
Supplier<String> supplier = () -> "Hello World";
String result = supplier.get();
System.out.println(result); } }
|
在这段代码中,Supplier<String> 表示这个 Supplier 会返回一个 String 类型的数据,Lambda 表达式 () -> "Hello World" 实际上就是实现了 get() 方法。当调用 supplier.get() 时,就会返回 "Hello World" 并输出到控制台。这种写法相比传统的匿名内部类更加简洁。例如,如果不用 Lambda 表达式,传统写法如下:
1 2 3 4 5 6
| Supplier<String> supplier = new Supplier<String>() { @Override public String get() { return "Hello World"; } };
|
可以看到,Lambda 表达式极大简化了代码。
2.策略模式:
是一种行为型设计模式,它的核心思想是:定义一系列算法或行为,并将每一种算法封装起来,使它们可以相互替换,从而让算法的变化独立于使用算法的客户端
例如早期使用jdbc时需要用Class.forName(“com.mysql.cj.jdbc.Driver”);来配置mysql;也可以通过修改参数来切换到Oracle等;
如果使用switch语句或者if-else语句,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class PayService {
public void pay(String type, double amount) { if ("alipay".equals(type)) { System.out.println("使用支付宝支付:" + amount); } else if ("wechat".equals(type)) { System.out.println("使用微信支付:" + amount); } else if ("bank".equals(type)) { System.out.println("使用银行卡支付:" + amount); } else { throw new RuntimeException("不支持的支付方式"); } }
}
|
每增加一种新的支付方式,都需要修改原有代码。如果支付方式越来越多,这个方法会变得非常臃肿,同时违反了设计原则中的开闭原则(对扩展开放:当需求发生变化时,我们可以通过添加新的代码来增强系统的功能 ,对修改关闭:在不修改原有源代码的前提下,实现功能的变更); 策略模式正是为了解决这种问题。
策略模式的基本实现步骤通常包括三个部分。第一部分是定义一个策略接口,这个接口规定所有具体策略必须实现的行为。例如在支付系统中,我们可以定义一个支付策略接口:
1 2 3
| interface PayStrategy { void pay(double amount); }
|
这个接口代表“支付策略”,任何具体支付方式都必须实现 pay 方法。接下来我们创建多个具体策略类,每个类实现一种具体的支付方式。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class AliPayStrategy implements PayStrategy {
@Override public void pay(double amount) { System.out.println("使用支付宝支付:" + amount); } }
class WechatPayStrategy implements PayStrategy {
@Override public void pay(double amount) { System.out.println("使用微信支付:" + amount); } }
class BankPayStrategy implements PayStrategy {
@Override public void pay(double amount) { System.out.println("使用银行卡支付:" + amount); } }
|
这里每一个类都代表一种具体策略(Concrete Strategy)。每个策略类都实现了同一个接口,因此它们之间可以互相替换。接下来需要一个**上下文类(Context)**来使用这些策略。上下文类并不关心具体是哪一种支付方式,它只依赖策略接口:
1 2 3 4 5 6 7 8 9 10 11 12
| class PayContext {
private PayStrategy strategy;
public PayContext(PayStrategy strategy) { this.strategy = strategy; }
public void executePay(double amount) { strategy.pay(amount); } }
|
在这个 PayContext 类中,真正执行支付的逻辑是调用 strategy.pay()。由于 strategy 是接口类型,因此可以在运行时传入任何具体实现类。最后在客户端代码中,我们可以根据需要选择不同的策略:
1 2 3 4 5 6 7 8 9 10 11
| public class Test {
public static void main(String[] args) {
PayStrategy strategy = new AliPayStrategy();
PayContext context = new PayContext(strategy);
context.executePay(100); } }
|
如果现在需要改为微信支付,只需要更换策略对象即可:
1 2 3
| PayStrategy strategy = new WechatPayStrategy(); PayContext context = new PayContext(strategy); context.executePay(100);
|
可以看到,客户端代码不需要修改业务逻辑,只是替换策略对象。如果未来新增一种支付方式,例如 ApplePayStrategy,只需要新增一个实现类即可,而不需要修改已有代码,这就实现了“对扩展开放,对修改关闭”
在实际项目中,策略模式通常会和工厂模式结合使用,以避免客户端直接 new 不同的策略类。例如可以通过工厂根据类型返回对应的策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class PayStrategyFactory {
public static PayStrategy create(String type) {
switch (type) { case "alipay": return new AliPayStrategy(); case "wechat": return new WechatPayStrategy(); case "bank": return new BankPayStrategy(); default: throw new RuntimeException("不支持的支付方式"); } } }
|
客户端代码可以写成:
1 2 3 4 5 6 7 8 9 10 11
| public class Test {
public static void main(String[] args) {
PayStrategy strategy = PayStrategyFactory.create("alipay");
PayContext context = new PayContext(strategy);
context.executePay(200); } }
|
这样就把策略选择逻辑和策略执行逻辑进一步解耦。
3.备忘录模式
**备忘录模式(Memento Pattern)*是一种*行为型设计模式,它的核心思想是:
在不破坏对象封装性的前提下,捕获对象的内部状态,并在需要的时候恢复到之前的状态。
简单理解就是:
给对象做“快照”,需要的时候可以恢复到过去的某个状态。
常见场景:
- 撤销(Undo)功能:文本编辑器撤销操作
- 回滚操作:数据库事务回滚
- 游戏存档:保存和读取游戏进度
一、备忘录模式的角色
备忘录模式通常有 三个角色:
| 角色 |
作用 |
| Originator(发起人) |
需要保存状态的对象 |
| Memento(备忘录) |
用来存储对象状态 |
| Caretaker(管理者) |
负责保存和恢复备忘录 |
关系结构:
1 2 3 4 5
| Originator ----创建----> Memento ↑ | | | --------恢复状态----------- Caretaker
|
4.代理模式
**代理模式(Proxy Pattern)*是一种*结构型设计模式。
它的核心思想是:
为某个对象提供一个代理对象,由代理对象控制对原对象的访问。
简单理解:
客户端不直接访问真实对象,而是通过代理对象访问。
代理对象可以在调用真实对象方法 前后增加额外功能。
Spring Aop底层用的就是动态代理;
代理模式是为了保证原对象的安全,不去暴露太多原对象的信息; 同时代理类内有前置,后置方法,可以在真实对象中添加其他的逻辑;
一、代理模式的结构
代理分为静态代理和动态代理
静态代理是由程序写死的,动态代理是运行时动态生成的;
对于静态代理类,对每个类都要写一个代理类,会导致一个代码爆炸的问题;
代理模式一般有三个角色:
| 角色 |
作用 |
| Subject(抽象主题) |
定义公共接口 |
| RealSubject(真实对象) |
真正执行业务逻辑 |
| Proxy(代理对象) |
控制对真实对象的访问 |
结构图:
1 2 3 4 5 6 7
| Subject ↑ ---------------- | | RealSubject Proxy | RealSubject
|
调用流程:
1 2 3 4 5
| Client ↓ Proxy ↓ RealSubject
|
二、静态代理(Static Proxy)
静态代理指的是:
代理类在编译时就已经确定。
示例:用户服务代理
1 定义接口(Subject)
1 2 3 4 5
| public interface UserService {
void login();
}
|
2 实现真实对象(RealSubject)
1 2 3 4 5 6 7 8
| public class UserServiceImpl implements UserService {
@Override public void login() { System.out.println("用户登录..."); }
}
|
3 创建代理类(Proxy)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) { this.userService = userService; }
@Override public void login() {
System.out.println("记录日志...");
userService.login();
System.out.println("记录结束..."); } }
|
代理类做了什么:
4 测试代码
1 2 3 4 5 6 7 8 9 10 11 12
| public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = new UserServiceProxy(userService);
proxy.login(); }
}
|
输出:
四、JDK动态代理
JDK 提供了:
可以 在运行时动态生成代理类。
要求:
示例
1 接口
1 2 3 4 5
| public interface UserService {
void login();
}
|
2 实现类
1 2 3 4 5 6 7 8
| public class UserServiceImpl implements UserService {
@Override public void login() { System.out.println("用户登录..."); }
}
|
3 InvocationHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;
public class LogHandler implements InvocationHandler {
private Object target;
public LogHandler(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前记录日志");
Object result = method.invoke(target, args);
System.out.println("方法执行后记录日志");
return result; } }
|
4 创建代理对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new LogHandler(userService) );
proxy.login(); }
}
|
输出:
1 2 3
| 方法执行前记录日志 用户登录... 方法执行后记录日志
|
5.单例模式:
**单例模式(Singleton Pattern)*是一种*创建型设计模式。
它的核心思想是:
保证一个类在整个系统中只有一个实例,并提供一个全局访问点。
也就是说:
1 2 3 4 5
| 一个类 ↓ 只能创建一个对象 ↓ 所有地方都使用这个对象
|
常见使用场景:
1 2 3 4 5
| 线程池 数据库连接池 配置管理类 Spring Bean(默认单例) 日志对象
|
Sping中的Bean默认就是单例的,IOC容器管理它的生命周期,容器关闭,Bean也随之销毁; 对于多例的Bean可以使用@Scope注解来设置; 但是IOC容器只负责创建,不负责完整生命周期管理,需要自己来主动销毁;
实现方式一:饿汉式
特点:类加载时就创建对象
代码示例
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() { }
public static Singleton getInstance() { return INSTANCE; } }
|
实现方法一:懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Singleton {
private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
}
|
实现方式二:同步锁懒汉式
解决线程安全问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Singleton {
private static Singleton instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (instance == null) { instance = new Singleton(); }
return instance; } }
|
优点:
缺点:
实现方式三:双重检查锁(DCL)
这是面试最常问的单例写法。
代码示例
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
| public class Singleton {
private static volatile Singleton instance;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
} }
return instance; } }
|
为什么要 volatile
创建对象实际上有三步:
JVM 可能发生:
变成:
其他线程可能拿到:
volatile 可以:
6.迭代器模式
迭代器模式属于行为型设计模式。它的目的是为聚合对象提供一种顺序访问其元素的方法,而无需暴露该对象的内部表示
参与者(通常约定)
- Iterator(抽象迭代器):定义访问和遍历元素的接口,例如
hasNext(), next()。
- ConcreteIterator(具体迭代器):实现迭代器接口,对聚合进行遍历的具体算法与状态。
- Aggregate(抽象聚合):定义创建迭代器的接口,例如
iterator()。
- ConcreteAggregate(具体聚合):实现创建相应迭代器的工厂方法并持有元素。
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 52 53 54 55 56 57 58
| public interface MyIterator<T> { boolean hasNext(); T next(); }
public interface MyAggregate<T> { MyIterator<T> iterator(); }
import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException;
public class ConcreteAggregate<T> implements MyAggregate<T> { private final List<T> items = new ArrayList<>();
public void add(T item) { items.add(item); } public T get(int index) { return items.get(index); } public int size() { return items.size(); } @Override public MyIterator<T> iterator() { return new ConcreteIterator(); } private class ConcreteIterator implements MyIterator<T> { private int cursor = 0; @Override public boolean hasNext() { return cursor < items.size(); } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } return items.get(cursor++); } }
}
|
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class IteratorDemo { public static void main(String[] args) { ConcreteAggregate<String> menu = new ConcreteAggregate<>(); menu.add("咖啡"); menu.add("奶茶"); menu.add("果汁");
MyIterator<String> it = menu.iterator(); while (it.hasNext()) { System.out.println(it.next()); } MyIterator<String> it2 = menu.iterator(); if (it2.hasNext()) { System.out.println("第一个元素: " + it2.next()); } }
}
|
7.访问者模式
是一种行为型设计模式
核心思想是:将“数据结构”和“作用在数据结构上的操作”分离,从而在不修改数据结构类的情况下,新增新的操作。
简单理解一句话:
对象结构稳定,但需要在其上执行的操作经常变化 → 使用访问者模式
一、访问者模式解决什么问题
假设有一个系统:
1 2 3 4
| 公司员工: - 程序员 - 产品经理 - 设计师
|
公司需要做不同的统计:
1️⃣ CEO视角
- 程序员:看代码量
- 产品经理:看产品数
- 设计师:看设计稿数
2️⃣ CTO视角
- 程序员:看技术能力
- 产品经理:看逻辑能力
- 设计师:看创意能力
如果不用访问者模式:
1 2 3 4 5 6 7 8 9
| class Programmer { void acceptCEO(){...} void acceptCTO(){...} }
class Manager { void acceptCEO(){...} void acceptCTO(){...} }
|
问题:
- 类越来越臃肿
- 新增角色必须修改所有类
- 违反开闭原则
访问者模式就是为了解决这个问题。
二、访问者模式结构
访问者模式包含 5个角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Visitor(访问者接口) / \ CEOVisitor CTOVisitor | visit(Programmer) visit(Manager)
---------------------------------
Element(元素接口) | Employee / \ Programmer Manager
---------------------------------
ObjectStructure 员工集合
|
结构图(文字版)
1 2 3 4 5 6 7 8 9
| Visitor ↑ ConcreteVisitor
Element ↑ ConcreteElement
ObjectStructure
|
三、访问者模式核心原理
访问者模式依赖一个关键技术:
双分派(Double Dispatch)
普通Java只有 单分派
1
| employee.accept(visitor);
|
访问者模式通过两次调用:
第一步
1
| employee.accept(visitor)
|
第二步
这样就能根据:
执行不同逻辑。
四、完整代码示例(员工访问系统)
1 Visitor接口
1 2 3 4 5 6 7
| interface Visitor {
void visit(Programmer programmer);
void visit(Manager manager);
}
|
2 Element接口
1 2 3 4 5
| interface Employee {
void accept(Visitor visitor);
}
|
3 程序员类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Programmer implements Employee {
private int codeLines;
public Programmer(int codeLines) { this.codeLines = codeLines; }
public int getCodeLines() { return codeLines; }
@Override public void accept(Visitor visitor) { visitor.visit(this); } }
|
4 产品经理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Manager implements Employee {
private int products;
public Manager(int products) { this.products = products; }
public int getProducts() { return products; }
@Override public void accept(Visitor visitor) { visitor.visit(this); } }
|
5 CEO访问者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class CEOVisitor implements Visitor {
@Override public void visit(Programmer programmer) {
System.out.println( "CEO查看程序员代码量:" + programmer.getCodeLines() );
}
@Override public void visit(Manager manager) {
System.out.println( "CEO查看产品经理产品数:" + manager.getProducts() );
} }
|
6 CTO访问者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class CTOVisitor implements Visitor {
@Override public void visit(Programmer programmer) {
System.out.println( "CTO查看程序员技术能力" );
}
@Override public void visit(Manager manager) {
System.out.println( "CTO查看产品经理逻辑能力" );
} }
|
7 对象结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.util.*;
class Company {
private List<Employee> employees = new ArrayList<>();
public void add(Employee e) { employees.add(e); }
public void show(Visitor visitor) {
for (Employee e : employees) { e.accept(visitor); }
} }
|
8 测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Test {
public static void main(String[] args) {
Company company = new Company();
company.add(new Programmer(10000)); company.add(new Manager(5));
System.out.println("CEO查看:"); company.show(new CEOVisitor());
System.out.println("---------------");
System.out.println("CTO查看:"); company.show(new CTOVisitor()); }
}
|
五、运行结果
1 2 3 4 5 6 7 8
| CEO查看: CEO查看程序员代码量:10000 CEO查看产品经理产品数:5
--------------- CTO查看: CTO查看程序员技术能力 CTO查看产品经理逻辑能力
|
六、访问者模式优点
1 符合开闭原则
新增操作 → 只需要新增 Visitor
例如新增:
1 2
| HRVisitor FinanceVisitor
|
无需修改原有类。
2 职责清晰
操作逻辑集中在 Visitor 中。
1 2
| Visitor = 行为 Element = 数据
|
3 易于扩展功能
新增统计方式:
只需要新增访问者。
8.观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式。
它定义了一种 一对多的依赖关系:当一个对象(被观察者 / Subject)状态发生变化时,所有依赖它的对象(观察者 / Observer)都会自动收到通知并更新。
简单理解一句话:
一个对象变化,自动通知一群依赖它的对象。
类似于消息推送中的推模式
生活中的例子
最经典的例子:订阅通知
比如:
- 你关注了某个 UP 主
- UP 主发视频
- 所有关注者都会收到通知
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 52 53 54 55 56 57 58 59 60 61 62
|
public interface Subject { void notifyObservers(); }
class ConcreteSubject implements Subject{
List<Observer> list=new ArrayList<>();
void add(Observer observer){ list.add(observer); }
void remove(Observer observer){ list.remove(observer); }
@Override public void notifyObservers() { System.out.println("目标改变通知其他观察者"); for (Observer observer : list) { observer.response(); } } }
interface Observer{ public void response(); }
class Concrete1Observer implements Observer{
@Override public void response() { System.out.println("Concrete1观察者做出了相应反应"); } }
class Concrete2Observer implements Observer{
@Override public void response() { System.out.println("Concrete2观察者做出了相应反应"); } }
class Main3{ public static void main(String[] args) { Observer observer1=new Concrete1Observer(); Observer observer2=new Concrete2Observer();
ConcreteSubject concreteSubject=new ConcreteSubject(); concreteSubject.add(observer1); concreteSubject.add(observer2); concreteSubject.notifyObservers(); } }
|
9.解释器模式
**解释器模式(Interpreter Pattern)**是一种 行为型设计模式,用于 定义一种语言的语法规则,并提供一个解释器来解释执行这种语言的句子。
一句话理解:
解释器模式就是为一种简单语言构建一个“解释执行”的系统。
例如:
- 数学表达式计算
- SQL解析
- 正则表达式
- Spring SpEL
- 编译器解析语法树
本质都是:
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| import java.util.HashMap; import java.util.Map;
public class InterpreterPatternDemo {
interface Expression { boolean interpret(Context context); }
static class Context {
private Map<String, Boolean> map = new HashMap<>();
public void put(String key, Boolean value) { map.put(key, value); }
public boolean get(String key) { return map.get(key); } }
static class VariableExpression implements Expression {
private String name;
public VariableExpression(String name) { this.name = name; }
@Override public boolean interpret(Context context) { return context.get(name); } }
static class AndExpression implements Expression {
private Expression left; private Expression right;
public AndExpression(Expression left, Expression right) { this.left = left; this.right = right; }
@Override public boolean interpret(Context context) { return left.interpret(context) && right.interpret(context); } }
static class OrExpression implements Expression {
private Expression left; private Expression right;
public OrExpression(Expression left, Expression right) { this.left = left; this.right = right; }
@Override public boolean interpret(Context context) { return left.interpret(context) || right.interpret(context); } }
public static void main(String[] args) {
Context context = new Context();
context.put("A", true); context.put("B", false);
Expression a = new VariableExpression("A"); Expression b = new VariableExpression("B");
Expression expression = new AndExpression(a, b); boolean result = expression.interpret(context);
System.out.println("A AND B = " + result); } }
|
10.模板方法模式
模板方法模式(Template Method)是一种行为型设计模式。它在抽象类中定义一个算法的骨架(模板方法),将某些步骤的实现延迟到子类中,从而允许子类在不改变算法结构的前提下重新定义算法的某些步骤。
在父类里面封装不可变的部分,在子类里面封装可变的部分,用于扩展
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| abstract class AbstractProcessor { public final void templateMethod() { stepOne(); stepTwo(); optionalStep(); hook(); }
protected abstract void stepOne();
protected abstract void stepTwo();
protected void optionalStep() { }
protected void hook() { } }
class ConcreteProcessorA extends AbstractProcessor { @Override protected void stepOne() { System.out.println("ConcreteProcessorA: stepOne"); }
@Override protected void stepTwo() { System.out.println("ConcreteProcessorA: stepTwo"); }
@Override protected void hook() { System.out.println("ConcreteProcessorA: hook"); } }
class ConcreteProcessorB extends AbstractProcessor { @Override protected void stepOne() { System.out.println("ConcreteProcessorB: stepOne"); }
@Override protected void stepTwo() { System.out.println("ConcreteProcessorB: stepTwo"); }
@Override protected void optionalStep() { System.out.println("ConcreteProcessorB: optionalStep"); } }
public class TemplateMethodDemo { public static void main(String[] args) { AbstractProcessor a = new ConcreteProcessorA(); AbstractProcessor b = new ConcreteProcessorB();
System.out.println("Running ConcreteProcessorA:"); a.templateMethod();
System.out.println("\nRunning ConcreteProcessorB:"); b.templateMethod(); } }
|
11.适配器模式
适配器模式是一种结构型设计模式。
它的核心作用是:将一个类的接口转换成客户端期望的另一个接口,使原本由于接口不兼容而无法一起工作的类可以一起工作。
简单理解就是:
适配器 = 转换器
就像生活中的:
- 手机充电转换头
- 电源插头转换器
- Type-C 转 USB
设备本身没问题,只是接口不一样,适配器负责把接口转换一下。
适配器模式的角色
适配器模式通常包含 4 个角色:
1 Target(目标接口)
客户端希望使用的接口。
2 Adaptee(被适配者)
已经存在的类,但是接口不符合需求。
3 Adapter(适配器)
负责把 Adaptee 的接口转换成 Target 接口。
4 Client(客户端)
通过 Target 接口使用功能。
对象适配器结构:
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
| interface MediaPlayer { void play(String fileName); }
class Mp3Player { public void playMp3(String fileName) { System.out.println("Playing mp3 file: " + fileName); } }
class Mp3Adapter implements MediaPlayer {
private Mp3Player mp3Player;
public Mp3Adapter(Mp3Player mp3Player) { this.mp3Player = mp3Player; }
@Override public void play(String fileName) { mp3Player.playMp3(fileName); } }
public class AdapterDemo {
public static void main(String[] args) {
Mp3Player mp3Player = new Mp3Player();
MediaPlayer player = new Mp3Adapter(mp3Player);
player.play("music.mp3"); } }
|
类适配器结构:
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
|
public interface Target { void request(); }
class Adapter{ void specificRequest(){
System.out.println("适配者中业务方法被调用"); }; }
class ClassAdapter extends Adapter implements Target{
@Override public void request() { specificRequest(); } }
class Main5{ public static void main(String[] args) { System.out.println("实现适配器"); Target target = new ClassAdapter(); target.request(); } }
|
12.责任链模式
责任链模式是一种行为型设计模式。
它的核心思想是:
将多个处理对象连成一条链,请求沿着这条链传递,直到有对象处理它为止。
这样可以让请求的发送者和接收者解耦
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; }
public abstract void handleRequest(int days); }
class Leader extends Handler {
@Override public void handleRequest(int days) { if (days <= 1) { System.out.println("组长审批通过"); } else if (nextHandler != null) { nextHandler.handleRequest(days); } } }
class Manager extends Handler {
@Override public void handleRequest(int days) { if (days <= 3) { System.out.println("经理审批通过"); } else if (nextHandler != null) { nextHandler.handleRequest(days); } } }
class Director extends Handler {
@Override public void handleRequest(int days) { if (days <= 7) { System.out.println("总监审批通过"); } else { System.out.println("请假天数过多,无法审批"); } } }
public class ChainDemo {
public static void main(String[] args) {
Handler leader = new Leader(); Handler manager = new Manager(); Handler director = new Director();
leader.setNextHandler(manager); manager.setNextHandler(director);
leader.handleRequest(5); } }
|