1.设计模式的7大设计原则
7大设计原则主要包括 开闭原则、 里氏替换原则、 依赖倒置原则、 单一职责原则、 接口隔离原则、 最小知识原则 和合成复用原则 下面是一个展示设计模式7大原则及其关系的可视化图表,采用了环形布局展示各原则间的内在联系:
1.1 开闭原则 (Open-Closed Principle)
-
核心思想:软件实体应对扩展开放,对修改关闭
-
关键实现:
- 使用抽象化定义
- 利用多态机制
- 依赖接口编程
1.2. 里氏替换原则 (Liskov Substitution Principle)
-
核心思想:子类必须能够替换其父类而不影响程序正确性
-
关键要点:
- 子类不改变父类方法行为
- 不强加额外约束条件
- 不削弱前置条件
-
应用场景:
- 继承体系设计
- 多态实现
- 接口实现
1.3. 依赖倒置原则 (Dependency Inversion Principle)
-
核心思想:
- 高层模块不依赖低层模块
- 二者都应依赖抽象
1.4. 单一职责原则 (Single Responsibility Principle)
-
核心思想:一个类只应有一个引起变化的原因
-
判断标准:
- 类描述是否包含"和"(如"用户管理和日志记录")
- 方法是否服务于不同功能
1.5. 接口隔离原则 (Interface Segregation Principle)
-
核心思想:客户端不应被迫依赖它不使用的接口
-
实现方法:
- 将臃肿接口拆分为多个专门接口
- 使用接口继承建立层次关系
-
优势:
- 减少接口污染
- 降低依赖耦合
- 提高系统灵活性
1.6. 最小知识原则 (Law of Demeter)
-
核心思想:一个对象应对其他对象保持最少的了解
-
通信规则:
- 与自身成员通信
- 与方法参数通信
- 与自身创建的对象通信
- 与直接组件对象通信
1.7. 合成复用原则 (Composite Reuse Principle)
-
核心思想:优先使用对象组合,而不是继承
-
应用场景:
- 功能扩展
- 代码复用
- 系统重构
七大原则关联关系
- 开闭原则是核心目标:其他原则都在不同角度支持开闭原则的实现
- 里氏替换是继承基础:保证子类替换父类时的系统稳定性
- 依赖倒置是架构关键:通过抽象解耦高层与低层模块
- 单一职责是设计前提:确保类的内聚性和可维护性
- 接口隔离是抽象手段:提供精确的抽象定义
- 最小知识是通信准则:限制对象间的过度耦合
- 合成复用是实践方案:提供比继承更灵活的复用方式
这七大原则共同构成了面向对象设计的基石,它们相互关联、相互支持,为创建灵活、可维护、可扩展的软件系统提供了理论指导和实践准则。
2.java的三大特性和设计模式的关系
Java三大特性与设计模式的关系图
2.1 封装
作用:隐藏对象内部状态,提供公共访问方式
设计模式应用:
- 工厂模式:封装对象创建过程
- 单例模式:封装实例化控制
- 外观模式:封装子系统复杂接口
2.2 继承
作用:实现代码复用和扩展
设计模式应用:
- 模板方法:父类定义算法骨架
- 装饰器模式:继承+组合实现功能扩展
- 适配器模式:通过继承适配接口
2.3 多态
作用:同一操作作用于不同对象产生不同行为
设计模式应用:
- 策略模式:运行时选择算法
- 观察者模式:通知不同类型观察者
- 命令模式:执行不同命令对象
Java三大特性与设计模式的关系可以概括为:
- 封装是设计模式实现的基础,用于隐藏复杂性和保护内部状态
- 继承为设计模式提供扩展能力,实现代码复用和层次化结构
- 多态赋予设计模式灵活性,支持运行时行为变化和接口统一
3.设计模式3大类型
设计模式全景图
3大设计模式主要包括创建型、结构型和行为型
3.1 创建型模式
目的:解耦对象的创建过程
| 模式 | 应用场景 | 关键特点 |
|---|---|---|
| 单例(Singleton) | 全局唯一对象 | 私有构造、静态实例 |
| 工厂方法(Factory) | 创建相关对象族 | 子类决定实例化类 |
| 抽象工厂(Abstract) | 创建产品家族 | 工厂的工厂 |
| 建造者(Builder) | 创建复杂对象 | 分步构建、分离构造与表示 |
| 原型(Prototype) | 克隆对象 | 实现Cloneable接口 |
3.2 结构型模式
目的:组合类和对象形成更大结构
| 模式 | 应用场景 | 关键特点 |
|---|---|---|
| 适配器(Adapter) | 接口转换 | 兼容不兼容接口 |
| 组合(Composite) | 树形结构 | 部分-整体层次结构 |
| 装饰器(Decorator) | 动态添加功能 | 透明扩展功能 |
| 外观(Facade) | 简化复杂系统 | 统一入口接口 |
| 享元(Flyweight) | 大量细粒度对象共享 | 内部状态与外部状态分离 |
| 代理(Proxy) | 控制对象访问 | 间接访问对象 |
3.3 行为型模式
目的:管理对象间的交互和职责分配
| 模式 | 应用场景 | 关键特点 |
|---|---|---|
| 责任链(Chain) | 请求处理链 | 多个对象处理请求 |
| 命令(Command) | 封装请求 | 命令对象化 |
| 解释器(Interpreter) | 特定语言解释 | 定义语法规则 |
| 迭代器(Iterator) | 集合遍历 | 统一遍历接口 |
| 中介者(Mediator) | 对象间交互 | 集中控制通信 |
| 备忘录(Memento) | 状态恢复 | 保存/恢复对象状态 |
| 观察者(Observer) | 一对多依赖 | 主题-观察者机制 |
| 状态(State) | 状态改变行为 | 状态封装行为 |
| 策略(Strategy) | 算法替换 | 封装可互换算法 |
| 模板方法(Template) | 算法骨架 | 步骤固定,实现可变 |
| 访问者(Visitor) | 元素操作分离 | 双重分发机制 |
4.Android 写一个完整的语音项目,包含,单例,构造者模式,工厂模式,策略模式,观察者模式,责任链模式,动态代理,模板方法,适配器模式,享元模式,外观模式
4.1 架构图说明
4.2 源码
// 1. 单例模式 - 全局配置管理
public class VoiceConfigManager {
private static volatile VoiceConfigManager instance;
private String language = "zh-CN";
private int volume = 80;
private boolean useOfflineMode = false;
private VoiceConfigManager() {}
public static VoiceConfigManager getInstance() {
if (instance == null) {
synchronized (VoiceConfigManager.class) {
if (instance == null) {
instance = new VoiceConfigManager();
}
}
}
return instance;
}
public void setLanguage(String lang) { this.language = lang; }
public String getLanguage() { return language; }
public void setVolume(int volume) { this.volume = volume; }
public int getVolume() { return volume; }
public void setUseOfflineMode(boolean use) { this.useOfflineMode = use; }
public boolean isOfflineMode() { return useOfflineMode; }
}
// 2. 建造者模式 - 语音命令构建
public class VoiceCommand {
private final String action;
private final String target;
private final String params;
private final String source;
private VoiceCommand(Builder builder) {
this.action = builder.action;
this.target = builder.target;
this.params = builder.params;
this.source = builder.source;
}
public String getAction() { return action; }
public String getTarget() { return target; }
public String getParams() { return params; }
public String getSource() { return source; }
public static class Builder {
private String action;
private String target;
private String params = "";
private String source = "user";
public Builder setAction(String action) {
this.action = action;
return this;
}
public Builder setTarget(String target) {
this.target = target;
return this;
}
public Builder setParams(String params) {
this.params = params;
return this;
}
public Builder setSource(String source) {
this.source = source;
return this;
}
public VoiceCommand build() {
return new VoiceCommand(this);
}
}
}
// 3. 工厂模式 - 语音处理器创建
public interface VoiceProcessor {
String process(String audio);
}
public class SpeechProcessorFactory {
public static VoiceProcessor createProcessor(String type) {
VoiceConfigManager config = VoiceConfigManager.getInstance();
if ("RECOGNITION".equals(type)) {
if (config.isOfflineMode()) {
return new OfflineSpeechRecognizer();
}
return new OnlineSpeechRecognizer();
} else if ("SYNTHESIS".equals(type)) {
if (config.isOfflineMode()) {
return new OfflineSpeechSynthesizer();
}
return new OnlineSpeechSynthesizer();
}
throw new IllegalArgumentException("Invalid processor type");
}
}
class OnlineSpeechRecognizer implements VoiceProcessor {
@Override
public String process(String audio) {
return "Online Recognition: " + audio;
}
}
class OfflineSpeechRecognizer implements VoiceProcessor {
@Override
public String process(String audio) {
return "Offline Recognition: " + audio;
}
}
class OnlineSpeechSynthesizer implements VoiceProcessor {
@Override
public String process(String text) {
return "Synthesized: " + text;
}
}
class OfflineSpeechSynthesizer implements VoiceProcessor {
@Override
public String process(String text) {
return "Offline Synthesized: " + text;
}
}
// 4. 策略模式 - 语音识别算法切换
public interface RecognitionStrategy {
String recognize(byte[] audioData);
}
public class AccurateRecognition implements RecognitionStrategy {
@Override
public String recognize(byte[] audioData) {
return "Accurate result: " + new String(audioData);
}
}
public class FastRecognition implements RecognitionStrategy {
@Override
public String recognize(byte[] audioData) {
return "Fast result: " + new String(audioData).substring(0, 10);
}
}
public class VoiceRecognitionContext {
private RecognitionStrategy strategy = new FastRecognition();
public void setStrategy(RecognitionStrategy strategy) {
this.strategy = strategy;
}
public String executeRecognition(byte[] audioData) {
return strategy.recognize(audioData);
}
}
// 5. 观察者模式 - 语音识别结果通知
public interface RecognitionListener {
void onRecognitionResult(String result);
void onError(String error);
}
public class VoiceRecognitionSubject {
private final List<RecognitionListener> listeners = new ArrayList<>();
public void addListener(RecognitionListener listener) {
listeners.add(listener);
}
public void removeListener(RecognitionListener listener) {
listeners.remove(listener);
}
public void notifyResult(String result) {
for (RecognitionListener listener : listeners) {
listener.onRecognitionResult(result);
}
}
public void notifyError(String error) {
for (RecognitionListener listener : listeners) {
listener.onError(error);
}
}
}
// 6. 责任链模式 - 语音命令处理
public abstract class CommandHandler {
protected CommandHandler next;
public void setNext(CommandHandler next) {
this.next = next;
}
public abstract boolean handleCommand(VoiceCommand command);
}
public class MusicCommandHandler extends CommandHandler {
@Override
public boolean handleCommand(VoiceCommand command) {
if ("PLAY".equals(command.getAction()) && "MUSIC".equals(command.getTarget())) {
System.out.println("Playing music: " + command.getParams());
return true;
}
return next != null && next.handleCommand(command);
}
}
public class SystemCommandHandler extends CommandHandler {
@Override
public boolean handleCommand(VoiceCommand command) {
if ("SET".equals(command.getAction()) && "VOLUME".equals(command.getTarget())) {
try {
int volume = Integer.parseInt(command.getParams());
VoiceConfigManager.getInstance().setVolume(volume);
System.out.println("Volume set to: " + volume);
return true;
} catch (NumberFormatException e) {
System.out.println("Invalid volume value");
}
}
return next != null && next.handleCommand(command);
}
}
public class WeatherCommandHandler extends CommandHandler {
@Override
public boolean handleCommand(VoiceCommand command) {
if ("GET".equals(command.getAction()) && "WEATHER".equals(command.getTarget())) {
System.out.println("Fetching weather for: " + command.getParams());
return true;
}
return next != null && next.handleCommand(command);
}
}
// 7. 动态代理 - 语音服务日志记录
public interface IVoiceService {
void processVoice(byte[] data);
String synthesizeText(String text);
}
public class RealVoiceService implements IVoiceService {
@Override
public void processVoice(byte[] data) {
System.out.println("Processing voice data...");
}
@Override
public String synthesizeText(String text) {
return "Synthesized: " + text;
}
}
public class VoiceServiceProxy implements InvocationHandler {
private final Object target;
public VoiceServiceProxy(Object target) {
this.target = target;
}
public static IVoiceService createProxy() {
return (IVoiceService) Proxy.newProxyInstance(
VoiceServiceProxy.class.getClassLoader(),
new Class[]{IVoiceService.class},
new VoiceServiceProxy(new RealVoiceService()));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("==> Calling method: " + method.getName());
long start = System.currentTimeMillis();
Object result = method.invoke(target, args);
long duration = System.currentTimeMillis() - start;
System.out.println("<== Method " + method.getName() + " executed in " + duration + "ms");
return result;
}
}
// 8. 模板方法 - 语音处理流程
public abstract class VoiceProcessingTemplate {
public final String process(byte[] audio) {
byte[] cleaned = preProcess(audio);
String text = recognize(cleaned);
String response = handleCommand(text);
return synthesizeResponse(response);
}
protected byte[] preProcess(byte[] audio) {
System.out.println("Applying noise reduction...");
// 模拟降噪处理
return Arrays.copyOf(audio, audio.length);
}
protected abstract String recognize(byte[] audio);
protected String handleCommand(String text) {
System.out.println("Handling command: " + text);
// 这里会连接责任链处理命令
return "Processed: " + text;
}
protected String synthesizeResponse(String response) {
System.out.println("Synthesizing response...");
return response;
}
}
public class StandardVoiceProcessing extends VoiceProcessingTemplate {
private final VoiceRecognitionContext recognitionContext = new VoiceRecognitionContext();
@Override
protected String recognize(byte[] audio) {
return recognitionContext.executeRecognition(audio);
}
}
// 9. 适配器模式 - 第三方语音库集成
public class ThirdPartyRecognizer {
public String recognize(byte[] input) {
return "ThirdParty result: " + input.length + " bytes";
}
}
public class ThirdPartyRecognizerAdapter implements VoiceProcessor {
private final ThirdPartyRecognizer thirdPartyRecognizer;
public ThirdPartyRecognizerAdapter(ThirdPartyRecognizer recognizer) {
this.thirdPartyRecognizer = recognizer;
}
@Override
public String process(String audio) {
byte[] data = audio.getBytes();
return thirdPartyRecognizer.recognize(data);
}
}
// 10. 享元模式 - 语音命令解析器复用
public class CommandParserFactory {
private static final Map<String, CommandParser> parserCache = new HashMap<>();
public static CommandParser getParser(String language) {
if (!parserCache.containsKey(language)) {
parserCache.put(language, new CommandParser(language));
}
return parserCache.get(language);
}
}
public class CommandParser {
private final String language;
public CommandParser(String language) {
this.language = language;
// 初始化解析器(模拟耗时操作)
System.out.println("Initializing parser for: " + language);
}
public VoiceCommand parse(String text) {
// 简化的解析逻辑
if (text.contains("播放")) {
return new VoiceCommand.Builder()
.setAction("PLAY")
.setTarget("MUSIC")
.setParams(text.replace("播放", "").trim())
.build();
} else if (text.contains("天气")) {
return new VoiceCommand.Builder()
.setAction("GET")
.setTarget("WEATHER")
.setParams(text.replace("天气", "").trim())
.build();
}
return new VoiceCommand.Builder()
.setAction("UNKNOWN")
.setTarget("UNKNOWN")
.setParams(text)
.build();
}
}
// 11. 外观模式 - 语音系统统一接口
public class VoiceAssistantFacade {
private final VoiceRecognitionSubject recognitionSubject = new VoiceRecognitionSubject();
private final VoiceProcessingTemplate processingTemplate = new StandardVoiceProcessing();
private final CommandHandler commandHandlerChain;
private final IVoiceService voiceService;
public VoiceAssistantFacade() {
// 创建责任链
CommandHandler musicHandler = new MusicCommandHandler();
CommandHandler weatherHandler = new WeatherCommandHandler();
CommandHandler systemHandler = new SystemCommandHandler();
musicHandler.setNext(weatherHandler);
weatherHandler.setNext(systemHandler);
this.commandHandlerChain = musicHandler;
// 创建带代理的语音服务
this.voiceService = VoiceServiceProxy.createProxy();
}
public void startListening() {
System.out.println("Listening for voice input...");
// 模拟语音输入
byte[] audioData = "播放周杰伦的歌".getBytes();
processAudio(audioData);
}
public void processAudio(byte[] audioData) {
new Thread(() -> {
try {
String result = processingTemplate.process(audioData);
recognitionSubject.notifyResult(result);
} catch (Exception e) {
recognitionSubject.notifyError("Processing error: " + e.getMessage());
}
}).start();
}
public void addRecognitionListener(RecognitionListener listener) {
recognitionSubject.addListener(listener);
}
// 处理命令的方法(被模板方法调用)
public String handleCommandInternal(String text) {
VoiceConfigManager config = VoiceConfigManager.getInstance();
CommandParser parser = CommandParserFactory.getParser(config.getLanguage());
VoiceCommand command = parser.parse(text);
if (commandHandlerChain.handleCommand(command)) {
return "Command executed: " + command.getAction() + " " + command.getTarget();
}
return "Unknown command: " + text;
}
// 语音合成
public String synthesize(String text) {
return voiceService.synthesizeText(text);
}
}
调用过程:
public class DesignActivity extends AppCompatActivity implements RecognitionListener {
private VoiceAssistantFacade voiceAssistant;
private TextView statusView;
private TextView resultView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_design);
statusView = findViewById(R.id.status_view);
resultView = findViewById(R.id.result_view);
// 初始化语音助手
voiceAssistant = new VoiceAssistantFacade();
voiceAssistant.addRecognitionListener(this);
// 设置配置
VoiceConfigManager.getInstance().setLanguage("zh-CN");
// 设置策略
Button fastBtn = findViewById(R.id.fast_btn);
Button accurateBtn = findViewById(R.id.accurate_btn);
fastBtn.setOnClickListener(v -> {
VoiceRecognitionContext context = new VoiceRecognitionContext();
context.setStrategy(new FastRecognition());
updateStatus("Fast recognition strategy set");
});
accurateBtn.setOnClickListener(v -> {
VoiceRecognitionContext context = new VoiceRecognitionContext();
context.setStrategy(new AccurateRecognition());
updateStatus("Accurate recognition strategy set");
});
// 开始监听
Button startBtn = findViewById(R.id.start_btn);
startBtn.setOnClickListener(v -> voiceAssistant.startListening());
// 语音合成
Button speakBtn = findViewById(R.id.speak_btn);
speakBtn.setOnClickListener(v -> {
String response = voiceAssistant.synthesize("你好,我是语音助手");
resultView.setText(response);
});
}
private void updateStatus(String message) {
runOnUiThread(() -> statusView.setText(message));
}
@Override
public void onRecognitionResult(String result) {
runOnUiThread(() -> {
resultView.setText(result);
statusView.setText("Recognition complete");
});
}
@Override
public void onError(String error) {
runOnUiThread(() -> {
resultView.setText("Error: " + error);
statusView.setText("Recognition failed");
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:background="@color/background">
<!-- 标题区域 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="语音助手"
android:textSize="24sp"
android:textColor="@color/primary"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="24dp"/>
<!-- 状态显示区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_mic"
/>
<TextView
android:id="@+id/status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="准备就绪"
android:textSize="16sp"
android:textColor="@color/text_primary"
android:layout_marginStart="8dp"/>
</LinearLayout>
<!-- 结果显示区域 -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:cardCornerRadius="8dp"
app:cardElevation="4dp"
android:layout_marginBottom="16dp"
tools:ignore="MissingClass">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:background="@color/card_background">
<TextView
android:id="@+id/result_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="识别结果将显示在这里..."
android:textSize="18sp"
android:textColor="@color/text_primary"/>
</ScrollView>
</androidx.cardview.widget.CardView>
<!-- 策略选择区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp"
android:gravity="center">
<Button
android:id="@+id/fast_btn"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="快速识别"
android:backgroundTint="@color/primary"
android:textColor="@android:color/white"
android:layout_marginEnd="8dp"/>
<Button
android:id="@+id/accurate_btn"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="准确识别"
android:backgroundTint="@color/secondary"
android:textColor="@android:color/white"/>
</LinearLayout>
<!-- 麦克风按钮 -->
<Button
android:id="@+id/start_btn"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="开始语音输入"
android:textSize="18sp"
android:drawableStart="@drawable/ic_mic"
android:drawablePadding="8dp"
android:backgroundTint="@color/accent"
android:textColor="@android:color/white"
android:layout_marginBottom="16dp"
style="@style/RoundedButton"/>
<!-- 语音合成按钮 -->
<Button
android:id="@+id/speak_btn"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="语音合成测试"
android:textSize="18sp"
android:drawableStart="@drawable/ic_mic"
android:drawablePadding="8dp"
android:backgroundTint="@color/secondary"
android:textColor="@android:color/white"
style="@style/RoundedButton"/>
</LinearLayout>
4.3 详细分析
4.3.1. 用户界面层
- MainActivity:用户交互界面
- RecognitionListener:观察者模式的UI监听器
4.3.2. 外观层(核心协调者)
-
VoiceAssistantFacade:
- 提供统一系统入口
- 协调各子系统工作
- 管理监听器注册
4.3.3. 语音处理引擎
(1) 模板方法模式
- VoiceProcessingTemplate: process(byte[] audio) { 1. 预处理(preProcess) 2. 语音识别(recognize) 3. 命令处理(handleCommand) 4. 响应合成(synthesizeResponse) }
(2) 策略模式
-
RecognitionStrategy:
- FastRecognition:快速识别
- AccurateRecognition:精确识别
-
支持运行时动态切换算法
(3) 适配器模式
-
ThirdPartyRecognizerAdapter:
- 集成第三方语音识别库
- 统一接口对接系统
(4) 工厂模式
-
SpeechProcessorFactory:
createProcessor(type) { if (离线模式) return OfflineProcessor else return OnlineProcessor }
4.3.4. 命令处理系统
(1) 享元模式
-
CommandParserFactory:
- 缓存和复用命令解析器
- 按语言类型共享解析器
(2) 建造者模式
-
VoiceCommand.Builder:
new VoiceCommand.Builder() .setAction("PLAY") .setTarget("MUSIC") .setParams("周杰伦") .build();
(3) 责任链模式
-
CommandHandler:
- MusicCommandHandler:处理音乐命令
- WeatherCommandHandler:处理天气查询
- SystemCommandHandler:处理系统设置
- 链式传递未处理命令
4.3.5. 服务层
(1) 动态代理
-
VoiceServiceProxy:
- 增强真实语音服务
- 添加日志、性能监控等横切关注点
(2) 单例模式
-
VoiceConfigManager:
- 全局唯一配置管理
- 统一访问点
4.3.6. 通知机制
-
观察者模式:
- VoiceRecognitionSubject:主题
- RecognitionListener:观察者接口
- 支持多监听器注册
- 状态变化自动通知
设计模式协同关系
| 设计模式 | 主要职责 | 协同对象 |
|---|---|---|
| 外观模式 | 系统入口 | 协调所有子系统 |
| 模板方法 | 定义处理流程 | 调用策略、工厂、责任链 |
| 策略模式 | 算法切换 | 被模板方法调用 |
| 工厂模式 | 对象创建 | 为模板方法提供处理器 |
| 享元模式 | 对象复用 | 为命令处理提供解析器 |
| 建造者 | 构建复杂对象 | 创建语音命令对象 |
| 责任链 | 命令处理 | 接收模板方法传递的命令 |
| 观察者 | 状态通知 | 接收外观模式的通知请求 |
| 动态代理 | 服务增强 | 包装真实语音服务 |
| 单例 | 配置管理 | 全局共享配置信息 |
5.项目中其他经典的场景,使用设计模式
5.1.抖音应用:图片要处理,美颜
在 Android 图片处理(旋转、缩放、裁剪、滤镜等)场景中
// 策略模式:滤镜算法接口
interface FilterStrategy {
Bitmap apply(Bitmap input);
}
// 具体策略实现
class VintageFilter implements FilterStrategy {
@Override public Bitmap apply(Bitmap input) {
// 简化的怀旧滤镜实现
Bitmap output = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig());
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
paint.setColorFilter(null);
canvas.drawBitmap(input, 0, 0, paint);
return output;
}
}
class BlurFilter implements FilterStrategy {
@Override public Bitmap apply(Bitmap input) {
// 简化的模糊实现
Bitmap output = Bitmap.createScaledBitmap(input,
input.getWidth()/2, input.getHeight()/2, true);
return Bitmap.createScaledBitmap(output,
input.getWidth(), input.getHeight(), true);
}
}
// 工厂模式:创建滤镜
class FilterFactory {
public static FilterStrategy createFilter(String type) {
switch (type.toUpperCase()) {
case "VINTAGE": return new VintageFilter();
case "BLUR": return new BlurFilter();
default: throw new IllegalArgumentException("Unknown filter: " + type);
}
}
}
// 命令模式:封装操作
interface ImageCommand {
Bitmap execute(Bitmap input);
Bitmap undo(Bitmap input);
}
// 基础命令
abstract class BaseCommand implements ImageCommand {
protected Bitmap originalState;
@Override
public Bitmap execute(Bitmap input) {
originalState = input.copy(input.getConfig(), false);
return process(input);
}
@Override
public Bitmap undo(Bitmap input) {
return originalState;
}
protected abstract Bitmap process(Bitmap input);
}
// 具体命令
class RotateCommand extends BaseCommand {
private final float degrees;
public RotateCommand(float degrees) {
this.degrees = degrees;
}
@Override
protected Bitmap process(Bitmap input) {
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
return Bitmap.createBitmap(input, 0, 0,
input.getWidth(), input.getHeight(), matrix, true);
}
}
class ScaleCommand extends BaseCommand {
private final float scaleX, scaleY;
public ScaleCommand(float scaleX, float scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
}
@Override
protected Bitmap process(Bitmap input) {
Matrix matrix = new Matrix();
matrix.postScale(scaleX, scaleY);
return Bitmap.createBitmap(input, 0, 0,
input.getWidth(), input.getHeight(), matrix, true);
}
}
class CropCommand extends BaseCommand {
private final Rect rect;
public CropCommand(int left, int top, int right, int bottom) {
this.rect = new Rect(left, top, right, bottom);
}
@Override
protected Bitmap process(Bitmap input) {
return Bitmap.createBitmap(input, rect.left, rect.top,
rect.width(), rect.height());
}
}
class FilterCommand extends BaseCommand {
private final FilterStrategy filter;
public FilterCommand(String filterType) {
this.filter = FilterFactory.createFilter(filterType);
}
@Override
protected Bitmap process(Bitmap input) {
return filter.apply(input);
}
}
// 责任链模式:处理管道
class ProcessingPipeline {
private final List<ImageCommand> commands = new ArrayList<>();
public ProcessingPipeline addCommand(ImageCommand command) {
commands.add(command);
return this;
}
public Bitmap execute(Bitmap input) {
Bitmap result = input;
for (ImageCommand cmd : commands) {
result = cmd.execute(result);
}
return result;
}
}
// 装饰者模式:添加额外功能
abstract class ImageDecorator implements ImageCommand {
protected ImageCommand wrapped;
public ImageDecorator(ImageCommand wrapped) {
this.wrapped = wrapped;
}
}
class WatermarkDecorator extends ImageDecorator {
private final Bitmap watermark;
public WatermarkDecorator(ImageCommand wrapped, Bitmap watermark) {
super(wrapped);
this.watermark = watermark;
}
@Override
public Bitmap execute(Bitmap input) {
Bitmap processed = wrapped.execute(input);
return addWatermark(processed, watermark);
}
@Override
public Bitmap undo(Bitmap input) {
return wrapped.undo(input);
}
private Bitmap addWatermark(Bitmap base, Bitmap watermark) {
Bitmap result = base.copy(base.getConfig(), true);
Canvas canvas = new Canvas(result);
canvas.drawBitmap(watermark,
base.getWidth() - watermark.getWidth() - 20,
base.getHeight() - watermark.getHeight() - 20, null);
return result;
}
}
// 建造者模式:构建处理流程
class ImageProcessorBuilder {
private final ProcessingPipeline pipeline = new ProcessingPipeline();
private final Stack<ImageCommand> commandStack = new Stack<>();
public ImageProcessorBuilder rotate(float degrees) {
ImageCommand cmd = new RotateCommand(degrees);
pipeline.addCommand(cmd);
commandStack.push(cmd);
return this;
}
public ImageProcessorBuilder scale(float scale) {
return scale(scale, scale);
}
public ImageProcessorBuilder scale(float scaleX, float scaleY) {
ImageCommand cmd = new ScaleCommand(scaleX, scaleY);
pipeline.addCommand(cmd);
commandStack.push(cmd);
return this;
}
public ImageProcessorBuilder crop(int left, int top, int right, int bottom) {
ImageCommand cmd = new CropCommand(left, top, right, bottom);
pipeline.addCommand(cmd);
commandStack.push(cmd);
return this;
}
public ImageProcessorBuilder applyFilter(String filterType) {
ImageCommand cmd = new FilterCommand(filterType);
pipeline.addCommand(cmd);
commandStack.push(cmd);
return this;
}
public ImageProcessorBuilder addWatermark(Bitmap watermark) {
if (!commandStack.isEmpty()) {
ImageCommand lastCmd = commandStack.peek();
WatermarkDecorator decorator = new WatermarkDecorator(lastCmd, watermark);
pipeline.addCommand(decorator);
commandStack.push(decorator);
}
return this;
}
public Bitmap execute(Bitmap input) {
return pipeline.execute(input);
}
}
// 外观模式:简化客户端调用
class ImageProcessorFacade {
private final ImageProcessorBuilder builder = new ImageProcessorBuilder();
public ImageProcessorFacade rotate(float degrees) {
builder.rotate(degrees);
return this;
}
public ImageProcessorFacade scale(float scale) {
builder.scale(scale);
return this;
}
public ImageProcessorFacade crop(int left, int top, int right, int bottom) {
builder.crop(left, top, right, bottom);
return this;
}
public ImageProcessorFacade applyFilter(String filterType) {
builder.applyFilter(filterType);
return this;
}
public ImageProcessorFacade addWatermark(Bitmap watermark) {
builder.addWatermark(watermark);
return this;
}
public Bitmap process(Bitmap input) {
return builder.execute(input);
}
}
// 客户端使用示例
public class ImageProcessingDemo {
public static void main(String[] args) {
// 原始图片
Bitmap original = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
Bitmap watermark = Bitmap.createBitmap(100, 40, Bitmap.Config.ARGB_8888);
// 使用外观模式简化调用
ImageProcessorFacade processor = new ImageProcessorFacade();
Bitmap result = processor
.rotate(90)
.scale(0.8f)
.crop(100, 100, 700, 700)
.applyFilter("VINTAGE")
.addWatermark(watermark)
.process(original);
System.out.println("Processing completed. Result size: "
+ result.getWidth() + "x" + result.getHeight());
// 工厂模式创建独立滤镜
FilterStrategy blurFilter = FilterFactory.createFilter("BLUR");
Bitmap blurred = blurFilter.apply(original);
}
}
架构图:
[原始图片]
│
▼
[外观控制台]───用户点击按钮───▶
│
▼
[建造者装配站]─┬─旋转模块🔄
├─缩放模块📏
├─裁剪模块✂️
└─滤镜卡带🎞️
│
▼
[处理流水线]───→ 🖼️ ──旋转─→ 🖼️ ──缩放─→ 🖼️ ──滤镜─→ 🖼️ ──水印─→
│ │ │ │ │ │
│ │ (保存状态)│ (保存状态)│ (保存状态)│ (保存状态)│
▼ ▼ ▼ ▼ ▼ ▼
[最终结果] + [撤销缓存] + [撤销缓存] + [撤销缓存] + [撤销缓存]
5.2. KEEP应用,运动锻炼场景
运动类型分为3种,计时,计数,计分
计数:俯卧撑
计时:平板支撑
计分:广播体操
他们有相同的一些流程可以复用: 都来自一个引擎,引擎的初始化,释放是相同的, 不同的是引擎统计是否计数,计时,计分 输入是一种类型的运动,输出可能是分数,时间,个数! 里面需要用到哪些设计模式 策略模式,工厂模式,模板方法, 继续优化需求:
1).引擎都是来自第三方SDK,有百度的和讯飞的!
2).期望在sdk的方法前面和后面统一添加日志!
3).结果都是通过回调,观察者拿到的结果
4).构造引擎的时候携带多个参数
5).组合模式产生多中健身运动,先做俯卧撑,然后做平板支持,再做广播体操,获取先平板支撑,再俯卧撑,再广播体操,或者先广播体操,再俯卧撑,再平板支撑
// ================== 基础类型和常量 ==================
enum ExerciseType {
COUNT, // 计数类型(俯卧撑)
TIME, // 计时类型(平板支撑)
SCORE // 计分类型(广播体操)
}
enum SDKProvider {
BAIDU, // 百度SDK
IFLYTEK // 讯飞SDK
}
// ================== 结果对象 ==================
class ExerciseResult {
private final int count;
private final long time;
private final float score;
public ExerciseResult(int count, long time, float score) {
this.count = count;
this.time = time;
this.score = score;
}
public int getCount() { return count; }
public long getTime() { return time; }
public float getScore() { return score; }
@Override
public String toString() {
if (count > 0) return "计数结果: " + count + "次";
if (time > 0) return "计时结果: " + time + "ms";
if (score > 0) return "计分结果: " + score + "分";
return "无结果";
}
}
// ================== 观察者模式 ==================
interface ExerciseObserver {
void onResult(ExerciseResult result);
}
// ================== 模板方法模式 + 策略模式 ==================
abstract class ExerciseEngine {
private final List<ExerciseObserver> observers = new ArrayList<>();
protected final EngineConfig config;
protected final SDKProvider provider;
public ExerciseEngine(EngineConfig config, SDKProvider provider) {
this.config = config;
this.provider = provider;
}
// 模板方法
public final void perform() {
start();
execute();
stop();
}
// 公共步骤
private void start() {
System.out.println("[" + provider + "] 运动引擎启动");
}
private void stop() {
System.out.println("[" + provider + "] 运动引擎停止");
}
// 抽象策略方法
protected abstract void execute();
// 观察者管理
public void registerObserver(ExerciseObserver observer) {
observers.add(observer);
}
public void unregisterObserver(ExerciseObserver observer) {
observers.remove(observer);
}
protected void notifyResult(ExerciseResult result) {
for (ExerciseObserver observer : observers) {
observer.onResult(result);
}
}
}
// ================== 具体引擎实现 ==================
class PushUpEngine extends ExerciseEngine {
public PushUpEngine(EngineConfig config, SDKProvider provider) {
super(config, provider);
}
@Override
protected void execute() {
System.out.println("[" + provider + "] 执行俯卧撑计数...");
// 模拟SDK逻辑
int count = (int) (Math.random() * 30) + 10;
notifyResult(new ExerciseResult(count, 0, 0));
}
}
class PlankEngine extends ExerciseEngine {
public PlankEngine(EngineConfig config, SDKProvider provider) {
super(config, provider);
}
@Override
protected void execute() {
System.out.println("[" + provider + "] 执行平板支撑计时...");
// 模拟SDK逻辑
long time = (long) (Math.random() * 30000) + 10000;
notifyResult(new ExerciseResult(0, time, 0));
}
}
class GymnasticsEngine extends ExerciseEngine {
public GymnasticsEngine(EngineConfig config, SDKProvider provider) {
super(config, provider);
}
@Override
protected void execute() {
System.out.println("[" + provider + "] 执行广播体操评分...");
// 模拟SDK逻辑
float score = (float) (Math.random() * 40) + 60;
notifyResult(new ExerciseResult(0, 0, score));
}
}
// ================== 建造者模式 ==================
class EngineConfig {
private final String deviceId;
private final int sensitivity;
private final boolean enableSound;
private EngineConfig(Builder builder) {
this.deviceId = builder.deviceId;
this.sensitivity = builder.sensitivity;
this.enableSound = builder.enableSound;
}
public String getDeviceId() { return deviceId; }
public int getSensitivity() { return sensitivity; }
public boolean isEnableSound() { return enableSound; }
public static class Builder {
private String deviceId = UUID.randomUUID().toString();
private int sensitivity = 5;
private boolean enableSound = true;
public Builder setDeviceId(String deviceId) {
this.deviceId = deviceId;
return this;
}
public Builder setSensitivity(int sensitivity) {
if (sensitivity < 1 || sensitivity > 10) {
throw new IllegalArgumentException("灵敏度范围1-10");
}
this.sensitivity = sensitivity;
return this;
}
public Builder setEnableSound(boolean enableSound) {
this.enableSound = enableSound;
return this;
}
public EngineConfig build() {
return new EngineConfig(this);
}
}
}
// ================== 抽象工厂模式 ==================
interface EngineFactory {
ExerciseEngine createPushUpEngine(EngineConfig config);
ExerciseEngine createPlankEngine(EngineConfig config);
ExerciseEngine createGymnasticsEngine(EngineConfig config);
}
class BaiduEngineFactory implements EngineFactory {
@Override
public ExerciseEngine createPushUpEngine(EngineConfig config) {
return new PushUpEngine(config, SDKProvider.BAIDU);
}
@Override
public ExerciseEngine createPlankEngine(EngineConfig config) {
return new PlankEngine(config, SDKProvider.BAIDU);
}
@Override
public ExerciseEngine createGymnasticsEngine(EngineConfig config) {
return new GymnasticsEngine(config, SDKProvider.BAIDU);
}
}
class IflytekEngineFactory implements EngineFactory {
@Override
public ExerciseEngine createPushUpEngine(EngineConfig config) {
return new PushUpEngine(config, SDKProvider.IFLYTEK);
}
@Override
public ExerciseEngine createPlankEngine(EngineConfig config) {
return new PlankEngine(config, SDKProvider.IFLYTEK);
}
@Override
public ExerciseEngine createGymnasticsEngine(EngineConfig config) {
return new GymnasticsEngine(config, SDKProvider.IFLYTEK);
}
}
// ================== 动态代理模式 ==================
class LoggingProxyHandler implements InvocationHandler {
private final Object target;
private final String engineName;
public LoggingProxyHandler(Object target, String engineName) {
this.target = target;
this.engineName = engineName;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
System.out.printf("[%s] 方法 %s 开始执行 | 时间: %d%n",
engineName, method.getName(), start);
Object result = method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.printf("[%s] 方法 %s 执行完成 | 耗时: %dms%n",
engineName, method.getName(), end - start);
return result;
}
public static ExerciseEngine createProxy(ExerciseEngine engine, String name) {
return (ExerciseEngine) Proxy.newProxyInstance(
engine.getClass().getClassLoader(),
engine.getClass().getInterfaces(),
new LoggingProxyHandler(engine, name)
);
}
}
// ================== 责任链模式 ==================
interface ExerciseCallback {
void onExercisePerformed(ExerciseType type, ExerciseResult result);
void onChainCompleted();
}
abstract class ExerciseHandler {
protected ExerciseHandler next;
public void setNext(ExerciseHandler next) {
this.next = next;
}
public abstract void perform(ExerciseCallback callback);
}
class PushUpHandler extends ExerciseHandler {
private final ExerciseEngine engine;
public PushUpHandler(ExerciseEngine engine) {
// 添加动态代理
this.engine = LoggingProxyHandler.createProxy(engine, "俯卧撑引擎");
}
@Override
public void perform(ExerciseCallback callback) {
engine.registerObserver(result -> {
callback.onExercisePerformed(ExerciseType.COUNT, result);
if (next != null) {
next.perform(callback);
} else {
callback.onChainCompleted();
}
});
engine.perform();
}
}
class PlankHandler extends ExerciseHandler {
private final ExerciseEngine engine;
public PlankHandler(ExerciseEngine engine) {
// 添加动态代理
this.engine = LoggingProxyHandler.createProxy(engine, "平板支撑引擎");
}
@Override
public void perform(ExerciseCallback callback) {
engine.registerObserver(result -> {
callback.onExercisePerformed(ExerciseType.TIME, result);
if (next != null) {
next.perform(callback);
} else {
callback.onChainCompleted();
}
});
engine.perform();
}
}
class GymnasticsHandler extends ExerciseHandler {
private final ExerciseEngine engine;
public GymnasticsHandler(ExerciseEngine engine) {
// 添加动态代理
this.engine = LoggingProxyHandler.createProxy(engine, "广播体操引擎");
}
@Override
public void perform(ExerciseCallback callback) {
engine.registerObserver(result -> {
callback.onExercisePerformed(ExerciseType.SCORE, result);
if (next != null) {
next.perform(callback);
} else {
callback.onChainCompleted();
}
});
engine.perform();
}
}
// 责任链建造者
class ExerciseChainBuilder {
private final List<ExerciseHandler> handlers = new ArrayList<>();
public ExerciseChainBuilder addHandler(ExerciseHandler handler) {
handlers.add(handler);
return this;
}
public void buildAndExecute(ExerciseCallback callback) {
if (handlers.isEmpty()) return;
// 构建责任链
for (int i = 0; i < handlers.size() - 1; i++) {
handlers.get(i).setNext(handlers.get(i + 1));
}
// 启动责任链
handlers.get(0).perform(callback);
}
}
// ================== 客户端代码 ==================
public class FitnessApp {
public static void main(String[] args) {
// 1. 创建配置(建造者模式)
EngineConfig config = new EngineConfig.Builder()
.setDeviceId("ANDROID_2023")
.setSensitivity(8)
.setEnableSound(true)
.build();
// 2. 创建工厂(抽象工厂模式)
SDKProvider provider = SDKProvider.BAIDU; // 可切换为IFLYTEK
EngineFactory factory = createEngineFactory(provider);
// 3. 创建引擎
ExerciseEngine pushUpEngine = factory.createPushUpEngine(config);
ExerciseEngine plankEngine = factory.createPlankEngine(config);
ExerciseEngine gymEngine = factory.createGymnasticsEngine(config);
// 4. 构建责任链(责任链模式)
ExerciseChainBuilder builder = new ExerciseChainBuilder()
.addHandler(new PushUpHandler(pushUpEngine))
.addHandler(new PlankHandler(plankEngine))
.addHandler(new GymnasticsHandler(gymEngine));
// 5. 执行运动链
builder.buildAndExecute(new ExerciseCallback() {
@Override
public void onExercisePerformed(ExerciseType type, ExerciseResult result) {
System.out.println(">>> 运动完成: " + type + " | " + result);
}
@Override
public void onChainCompleted() {
System.out.println("==============================");
System.out.println("所有运动完成!训练结束");
System.out.println("==============================");
}
});
}
private static EngineFactory createEngineFactory(SDKProvider provider) {
if (provider == SDKProvider.BAIDU) {
return new BaiduEngineFactory();
} else if (provider == SDKProvider.IFLYTEK) {
return new IflytekEngineFactory();
}else {
return new IflytekEngineFactory();
}
}
}