GPT摘要
本文主要介绍了面向对象设计中的五大原则(SOLID)以及几种常见的设计模式,包括策略模式、观察者模式、装饰者模式、单例模式、状态模式、模板方法模式和责任链模式。  五大设计原则: 1. 单一职责原则:每个类只负责单一功能,提升可维护性。 2. 开放封闭原则:通过扩展而非修改来增强功能,提高扩展性。 3. 里氏替换原则:子类应能完全替代父类而不影响程序。 4. 接口隔离原则:细化接口,避免依赖不必要的方法。 5. 依赖倒置原则:依赖于抽象而非具体实现,实现松耦合。  核心设计模式: - 策略模式:封装可变算法到独立策略对象,使算法可互换(如排序算法的灵活切换)。 - 观察者模式:建立一对多依赖,主题变化时自动通知所有观察者(如订单状态更新通知多模块)。 - 装饰者模式:通过包装对象动态扩展功能,避免继承膨胀(如Java I/O流的多层包装)。 - 单例模式:确保全局唯一实例,提供可控访问(数据库连接池等资源共享场景)。 - 状态模式:对象行为随内部状态改变(如订单状态流转对应不同操作)。 - 模板方法模式:定义算法骨架,子类实现具体步骤(如统一服务流程模板)。 - 责任链模式:请求沿处理链传递直至被处理(如多级审批或折扣策略链)。  关键实现方法均包含抽象接口定义、具体实现类及上下文管理,通过组合优于继承的方式提升系统灵活性和可维护性。每种模式通过示例代码(如咖啡订单装饰、订单状态机等)直观展示了应用场景和实现要点。
SOLID
- 单一职责原则(Single Responsibility Principle,SRP):一个类只负责单一的功能,避免一个类承担过多的职责,从而提高代码的可维护性。
- 开放封闭原则(Open Closed Principle,OCP):软件实体应该对扩展开放,对修改关闭,也就是说,应该通过增加代码而不是修改代码来扩展软件功能,从而提高代码的可维护性和扩展性。
- 里氏替换原则(Liskov Substitution Principle,LSP):子类应该能够替换父类并且不影响程序的正确性,也就是说,子类必须能够完全实现父类的功能,从而提高代码的可扩展性。
- 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口,也就是说,应该尽量将接口细化,将不同的功能分离开来,从而提高代码的灵活性和可复用性。
- 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,它们应该依赖于抽象,而不是具体实现,也就是说,应该通过接口或者抽象类来实现模块之间的松耦合,从而提高代码的可维护性和可扩展性。
找出会变的地方,把他们从不变的地方抽离出来(策略模式运用了)
策略模式
将不同的算法或行为封装成独立的策略对象,使它们可以相互替换,从而使系统更加灵活和可扩展。
提高代码的可复用性和可维护性:
- 如果每一个上下文都有该方法,我只需要设置成员变量即可,代码都写在策略中。不同的策略实现不同的方法
- 如果使用继承去获得该策略,那么有的上下文他不需要(有的鸭子不会叫)就需要覆盖
- 如果使用接口,接口可以扩展上下文,但每一个上下文都需要实现同样的方法,代码没有复用
- 拉取出变化的部分,重新建立一个类,并针对接口编程。最后把拉出来的作为成员变量插入
 
实现过程:
- 策略接口:定义一个抽象策略接口,该接口定义了算法的公共方法。(Fly)
- 具体策略:然后针对每种算法,创建一个具体的策略类,实现该接口。(FlyWings、NoWay)
- 环境类:最后,我们还需要创建一个上下文类,该类包含一个策略成员变量,可以在运行时设置具体的策略。
| 12
 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 SortingStrategy {
 void sort(int[] array);
 }
 
 
 class BubbleSort implements SortingStrategy {
 public void sort(int[] array) {
 
 }
 }
 
 
 class QuickSort implements SortingStrategy {
 public void sort(int[] array) {
 
 }
 }
 
 
 class SortingContext {
 private SortingStrategy strategy;
 
 public void setStrategy(SortingStrategy strategy) {
 this.strategy = strategy;
 }
 
 public void sort(int[] array) {
 strategy.sort(array);
 }
 }
 
 
 public class Client {
 public static void main(String[] args) {
 int[] array = {5, 2, 8, 4, 7};
 SortingContext context = new SortingContext();
 
 
 context.setStrategy(new BubbleSort());
 context.sort(array);
 
 
 context.setStrategy(new QuickSort());
 context.sort(array);
 }
 }
 
 
 | 
观察者模式
一(主题)对多(观察者);主题变化时需要通知所有人
普通写法:
| 12
 3
 4
 5
 6
 
 | {person1.update();
 person2.update();
 ...
 
 }
 
 | 
观察者模式:定义一个数组保存全部Observe,观察者在创建时加入主题数组,主题在变化时通知数组全部人
	我想要数组中每一个不同的观察者统一调用同一个函数,自然而然想到使用接口。
| 12
 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
 
 | interface Subject {
 void registerObserver(Observer observer);
 void removeObserver(Observer observer);
 void notifyObservers();
 
 @Override
 public void notifyObservers() {
 for (Observer observer : observers) {
 observer.update(temperature, humidity, pressure);
 }
 }
 }
 
 
 
 interface Observer {
 void update(float temperature, float humidity, float pressure);
 }
 
 class CurrentConditionsDisplay implements Observer {
 private float temperature;
 private float humidity;
 private Subject weatherData;
 
 public CurrentConditionsDisplay(Subject weatherData) {
 this.weatherData = weatherData;
 weatherData.registerObserver(this);
 }
 
 | 
”趣学架构“中的非主链路的统计、打点,使用观察者模式实现
装饰者模式
装饰器类将对象包装,通过构造函数传递给装饰器;装饰器和被装饰对象需要实现相同的接口,并在实现中进行叠加
| 12
 3
 4
 5
 6
 
 | public Decorator(Beverage beverage) {this.beverage = beverage;
 }
 public double getCost() {
 return beverage.getCost() + 0.10;
 }
 
 | 
- 允许你在运行时动态地扩展一个对象的功能。
- 组合而非继承
- 包装原始对象而不影响其原始结构和行为(通过成员变量引用访问到原始对象has-a的关系)
- 抽象组件(Component):定义了被装饰者和装饰者的共同接口。
- 具体组件(ConcreteComponent):实现了抽象组件接口,并定义了被装饰者的基本行为。
- 抽象装饰者(Decorator):定义了装饰者的接口,并持有一个被装饰者的引用。has-a
- 具体装饰者(ConcreteDecorator):实现了抽象装饰者的接口,并向被装饰者添加新的行为和责任。

| 12
 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
 
 | interface Beverage {
 String getDescription();
 double getCost();
 }
 
 
 class Espresso implements Beverage {
 public String getDescription() {
 return "Espresso";
 }
 
 public double getCost() {
 return 1.99;
 }
 }
 
 
 abstract class CondimentDecorator implements Beverage {
 protected Beverage beverage;
 
 public CondimentDecorator(Beverage beverage) {
 this.beverage = beverage;
 }
 
 public String getDescription() {
 return beverage.getDescription();
 }
 
 public abstract double getCost();
 }
 
 
 class Milk extends CondimentDecorator {
 public Milk(Beverage beverage) {
 super(beverage);
 }
 
 public String getDescription() {
 return beverage.getDescription() + ", Milk";
 }
 
 public double getCost() {
 return beverage.getCost() + 0.10;
 }
 }
 
 class Mocha extends CondimentDecorator {
 public Mocha(Beverage beverage) {
 super(beverage);
 }
 
 public String getDescription() {
 return beverage.getDescription() + ", Mocha";
 }
 
 public double getCost() {
 return beverage.getCost() + 0.20;
 }
 }
 
 
 public class Test {
 public static void main(String[] args) {
 Beverage beverage = new Espresso();
 System.out.println(beverage.getDescription() + " $" + beverage.getCost());
 
 Beverage beverage2 = new Espresso();
 beverage2 = new Milk(beverage2);
 beverage2 = new Mocha(beverage2);
 System.out.println(beverage2.getDescription() + " $" + beverage2.getCost());
 }
 }
 
 
 
 | 
Java I/O库
SQL查询通常由多个组件构成,如SELECT、FROM、WHERE、JOIN等。我们可以使用装饰者模式来构建这些组件,并动态地添加额外的功能,例如缓存、日志记录等。  Filter 和 SeqScan的关系
单例模式
全局变量可以提供全局访问,但不能确保唯一。
public的类,但private的构造方法,通过static方法访问private构造方法,构造一个static变量
饿汉模式
全局直接初始化
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | public class Singleton {private static Singleton instance = new Singleton();
 
 private Singleton() {}
 
 public static Singleton getInstance() {
 return instance;
 }
 }
 
 | 
懒汉模式
synchronized
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | public class Singleton {private static Singleton instance;
 
 private Singleton() {}
 
 public static synchronized Singleton getInstance() {
 if (instance == null) {
 instance = new Singleton();
 }
 return instance;
 }
 }
 
 | 
双重检查
volatile:强制立即写入内存,并强制内存读取,而不是缓存
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | 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;
 }
 }
 
 | 
享元模式
共享对象来减少内存使用和提高性能
字符串池、Integer常量池、数据库连接池
状态模式
当一个对象的行为取决于其状态,并且它必须在运行时根据状态改变其行为时。
订单处理系统:订单有多种状态,如新建订单、已支付、已发货、已收货、已完成等。每种状态下,订单可以执行的操作都可能不同。
以下是一个基于Java的状态模式示例:
| 12
 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
 
 | interface OrderState {
 void next(Order order);
 void prev(Order order);
 void printStatus();
 }
 
 
 class New implements OrderState {
 public void next(Order order) {
 order.setState(new Paid());
 }
 
 public void prev(Order order) {
 System.out.println("The order is in its root state.");
 }
 
 public void printStatus() {
 System.out.println("New order.");
 }
 }
 
 class Paid implements OrderState {
 public void next(Order order) {
 order.setState(new Shipped());
 }
 
 public void prev(Order order) {
 order.setState(new New());
 }
 
 public void printStatus() {
 System.out.println("Order paid.");
 }
 }
 
 class Shipped implements OrderState {
 public void next(Order order) {
 order.setState(new Delivered());
 }
 
 public void prev(Order order) {
 order.setState(new Paid());
 }
 
 public void printStatus() {
 System.out.println("Order shipped.");
 }
 }
 
 class Delivered implements OrderState {
 public void next(Order order) {
 System.out.println("This order is already delivered.");
 }
 
 public void prev(Order order) {
 order.setState(new Shipped());
 }
 
 public void printStatus() {
 System.out.println("Order delivered.");
 }
 }
 
 
 class Order {
 private OrderState state;
 
 public Order() {
 this.state = new New();
 }
 
 public void setState(OrderState state) {
 this.state = state;
 }
 
 public void next() {
 state.next(this);
 }
 
 public void prev() {
 state.prev(this);
 }
 
 public void printStatus() {
 state.printStatus();
 }
 }
 
 
 public class Main {
 public static void main(String[] args) {
 Order order = new Order();
 
 order.printStatus();
 
 order.next();
 order.printStatus();
 
 order.next();
 order.printStatus();
 
 order.prev();
 order.printStatus();
 }
 }
 
 | 
在这个例子中,OrderState接口定义了next、prev和printStatus三个方法,表示订单的下一个状态、上一个状态和打印当前状态。New、Paid、Shipped和Delivered类分别实现了OrderState接口,代表了订单的四种状态。Order类就是所谓的上下文,它持有一个OrderState对象,代表当前的状态。
模板方法模式
定义一个操作中的骨架,标准化流程
| 12
 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
 
 | import com.google.common.base.Stopwatch;import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
 public abstract class ServiceTemplate<T, R> {
 private final Logger logger = new LoggerImpl();
 
 
 
 
 public R process(T request) {
 
 logger.info("start invoke, request=" + request);
 
 Stopwatch stopwatch = Stopwatch.createStarted();
 try {
 
 validParam(request);
 
 R response = doProcess(request);
 
 long timeCost = stopwatch.elapsed(TimeUnit.MILLISECONDS);
 logger.info("end invoke, response=" + response + ", costTime=" + timeCost);
 return response;
 } catch (Exception e) {
 
 logger.error("error invoke, exception:" + Arrays.toString(e.getStackTrace()));
 return null;
 }
 }
 
 
 
 
 protected abstract void validParam(T request);
 
 
 
 
 protected abstract R doProcess(T request);
 }
 
 | 
责任链

责任链:沿着这条链传递请求,直到有一个对象处理它为止,具体由哪个对象处理则在运行时动态决定的情况。
| 12
 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
 
 | abstract class Handler {protected Handler successor;
 
 public void setSuccessor(Handler successor) {
 this.successor = successor;
 }
 
 public abstract void handleRequest(double amount);
 }
 
 class NoDiscountHandler extends Handler {
 public void handleRequest(double amount) {
 System.out.println("No discount applied.");
 }
 }
 
 class LowDiscountHandler extends Handler {
 public void handleRequest(double amount) {
 if (amount < 1000) {
 System.out.println("Low discount applied. Amount: " + amount);
 } else if (successor != null) {
 successor.handleRequest(amount);
 }
 }
 }
 
 class HighDiscountHandler extends Handler {
 public void handleRequest(double amount) {
 if (amount >= 1000) {
 System.out.println("High discount applied. Amount: " + amount);
 } else if (successor != null) {
 successor.handleRequest(amount);
 }
 }
 }
 
 class HandlerChain {
 private Handler head;
 private Handler tail;
 
 public HandlerChain add(Handler handler) {
 if (head == null) {
 head = handler;
 tail = handler;
 } else {
 tail.setSuccessor(handler);
 tail = handler;
 }
 return this;
 }
 
 public void handleRequest(double amount) {
 if (head != null) {
 head.handleRequest(amount);
 }
 }
 }
 
 public class ChainDemo {
 public static void main(String[] args) {
 HandlerChain chain = new HandlerChain();
 chain.add(new LowDiscountHandler())
 .add(new HighDiscountHandler())
 .add(new NoDiscountHandler());
 
 
 chain.handleRequest(500);
 chain.handleRequest(1500);
 }
 }
 
 
 | 
流程引擎
见 ”趣学架构“