设计模式:
- 创建型(创建对象角度):
- 行为型(对象间通信角度):
- 结构型(类和对象的关系)
序号 | 模式 & 描述 | 包括 |
---|---|---|
1 | 创建型模式这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 | 工厂模式(Factory Pattern)抽象工厂模式(Abstract Factory Pattern)单例模式(Singleton Pattern)建造者模式(Builder Pattern)原型模式(Prototype Pattern) |
2 | 结构型模式这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 | 适配器模式(Adapter Pattern)桥接模式(Bridge Pattern)过滤器模式(Filter、Criteria Pattern)组合模式(Composite Pattern)装饰器模式(Decorator Pattern)外观模式(Facade Pattern)享元模式(Flyweight Pattern)代理模式(Proxy Pattern) |
3 | 行为型模式这些设计模式特别关注对象之间的通信。 | 责任链模式(Chain of Responsibility Pattern)命令模式(Command Pattern)解释器模式(Interpreter Pattern)迭代器模式(Iterator Pattern)中介者模式(Mediator Pattern)备忘录模式(Memento Pattern)观察者模式(Observer Pattern)状态模式(State Pattern)空对象模式(Null Object Pattern)策略模式(Strategy Pattern)模板模式(Template Pattern)访问者模式(Visitor Pattern) |
简单工厂
思考一个业务场景, 商品促销有不同的促销策略, 比如正常、打折、满减、送积分。
CashFactory中的方法实现:
public class CashFactory {
public static CashSuper createCashAdapter(String type){
return switch (type){
case "正常收费" -> new CashNormal();
case "满300减100" -> new CashReturn(300,100);
case "打8折" -> new CashRebate(0.8);
default -> throw new IllegalStateException("Unexpected value: " + type);
};
}
}
调用方这样改造:
String discountText = "满300返100";
CashSuper csuper = CashFactory.createCashAdapter(discountText)
缺点:
- 每增加一种新的折扣类型,都需要修改Factory,还需要手动创建相应的策略类,不优雅。
- 调用方需要感知两个类型, CashFactory、CashSuper。
策略模式
CashContext中的实现:
public class CashContext {
private CashSuper cs;
public CashContext(String type){
this.cs = switch (type){
case "正常收费" -> new CashNormal();
case "满300返100" -> new CashReturn(300,100);
case "打8折" -> new CashRebate(0.8);
default -> throw new IllegalStateException("Unexpected value: " + type);
};
}
public double getResult(double money){
return cs.acceptCash(money);
}
}
调用方:
double cost = new CashContext(discountText).getResult(price * quantity);
特点:
- 调用方只需要感知CashContext一个类, 不需要感知具体的折扣策略
- CashContext中对策略的获取还是不够优雅
抽象工厂
需求:开发一个UI库,它需要能在Windows和MacOS上运行。
抽象工厂模式通常包含以下4个角色:(相对简单工厂多了一层抽象工厂)
抽象产品 (Abstract Product):为每种产品声明接口(例如,
Button
,TextBox
)。具体产品 (Concrete Product):实现抽象产品接口的不同产品变体(例如,
WindowsButton
,MacButton
)。抽象工厂 (Abstract Factory):声明一个创建一系列抽象产品的方法(例如,
createButton()
,createTextBox()
)。具体工厂 (Concrete Factory):实现抽象工厂的创建方法,生成一系列具体的产品(例如,
WindowsUIFactory
创建WindowsButton
和WindowsTextBox
)。
代码实现:
1. 抽象产品
// 抽象产品:按钮
public interface Button {
void render();
void onClick();
}
// 抽象产品:文本框
public interface TextBox {
void render();
void setText(String text);
}
2. 具体产品
// 具体产品:Windows风格按钮
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("Rendering a button in Windows style.");
}
@Override
public void onClick() {
System.out.println("Windows button clicked!");
}
}
// 具体产品:Mac风格按钮
public class MacButton implements Button {
@Override
public void render() {
System.out.println("Rendering a button in macOS style.");
}
@Override
public void onClick() {
System.out.println("Mac button clicked!");
}
}
// ... 类似的,实现 WindowsTextBox 和 MacTextBox
public class WindowsTextBox implements TextBox {
@Override
public void render() {
System.out.println("Rendering a textbox in Windows style.");
}
@Override
public void setText(String text) {
System.out.println("Windows textbox set to: " + text);
}
}
public class MacTextBox implements TextBox {
@Override
public void render() {
System.out.println("Rendering a textbox in macOS style.");
}
@Override
public void setText(String text) {
System.out.println("Mac textbox set to: " + text);
}
}
3. 抽象工厂
// 抽象工厂:知道如何创建一整套UI产品
public interface UIFactory {
Button createButton();
TextBox createTextBox();
}
4. 具体工厂
// 具体工厂:创建Windows家族的产品
public class WindowsUIFactory implements UIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextBox createTextBox() {
return new WindowsTextBox();
}
}
// 具体工厂:创建Mac家族的产品
public class MacUIFactory implements UIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextBox createTextBox() {
return new MacTextBox();
}
}
5. 客户端
public class Application {
private Button button;
private TextBox textBox;
// 构造函数接收一个抽象工厂,客户端代码只依赖于抽象
public Application(UIFactory factory) {
button = factory.createButton();
textBox = factory.createTextBox();
}
public void renderUI() {
button.render();
textBox.render();
}
public static void main(String[] args) {
// 配置:根据配置或环境决定使用哪个工厂
UIFactory factory;
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
factory = new WindowsUIFactory();
} else if (osName.contains("mac")) {
factory = new MacUIFactory();
} else {
throw new RuntimeException("Unknown OS");
}
// 客户端代码只与抽象工厂和抽象产品交互,完全不知道具体实现
Application app = new Application(factory);
app.renderUI();
}
}
单例模式
全局只有一个实例。
饿汉式:类创建的时候就创建出这个单例
public class SingletonEager {
// 1. 私有静态常量,在类加载时即初始化实例
private static final SingletonEager INSTANCE = new SingletonEager();
// 2. 私有构造函数,防止外部通过 new 创建实例
private SingletonEager() {
// 防止通过反射调用构造函数创建实例
if (INSTANCE != null) {
throw new RuntimeException("Use getInstance() method to get the single instance.");
}
}
// 3. 公共静态方法,返回唯一实例
public static SingletonEager getInstance() {
return INSTANCE;
}
}
懒汉式:实际使用的时候才创建单例
双重检查锁 (DCL - Double-Checked Locking)
public class SingletonLazyDCL {
// 使用 volatile 关键字禁止指令重排序,保证可见性
private static volatile SingletonLazyDCL instance;
private SingletonLazyDCL() {}
public static SingletonLazyDCL getInstance() {
// 第一次检查:避免不必要的同步
if (instance == null) {
// 同步代码块
synchronized (SingletonLazyDCL.class) {
// 第二次检查:确保实例在同步块内未被其他线程创建
if (instance == null) {
instance = new SingletonLazyDCL();
// new SingletonLazyDCL() 的非原子操作可能发生指令重排序,
// volatile 保证了写操作先行发生(happens-before),防止其他线程拿到未初始化完成的对象。
}
}
}
return instance;
}
}
静态内部类实现方式
public class SingletonLazyInnerClass {
private SingletonLazyInnerClass() {}
// 静态内部类
private static class SingletonHolder {
// 在内部类中持有外部类的实例
private static final SingletonLazyInnerClass INSTANCE = new SingletonLazyInnerClass();
}
public static SingletonLazyInnerClass getInstance() {
// 调用此方法时,JVM 才会加载静态内部类并初始化 INSTANCE
return SingletonHolder.INSTANCE;
}
}
原理:利用 JVM 的类加载机制。静态内部类 SingletonHolder
只有在被主动引用(如调用 getInstance()
)时才会被加载,从而实现懒加载。而类的初始化阶段是线程安全的。
代理模式
特点:
- 影藏真实主体
- 可以做一些增强处理
观察者模式
具体实现:
1. 抽象目标: 维护观察者集合、添加观察者方法、删除观察者方法、通知观察者方法
abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>();
//增加观察者方法
public void add(Observer observer) {
observers.add(observer);
}
//删除观察者方法
public void remove(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver(); //通知观察者方法
}
2. 具体目标: 通知观察者(调用观察者的响应方法)
class ConcreteSubject extends Subject {
public void notifyObserver() {
System.out.println("具体目标发生改变...");
System.out.println("--------------");
for (Object obs : observers) {
((Observer) obs).response();
}
}
}
3. 抽象观察者 + 具体观察者:响应通知
//抽象观察者
interface Observer {
void response(); //反应
}
//具体观察者1
class ConcreteObserver1 implements Observer {
public void response() {
System.out.println("具体观察者1作出反应!");
}
}
//具体观察者1
class ConcreteObserver2 implements Observer {
public void response() {
System.out.println("具体观察者2作出反应!");
}
}
原型模式
简单理解原型模式, 就是克隆。原型模式就是实现cloneable接口.
//原型模式的测试类
public class PrototypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
Realizetype obj1 = new Realizetype();
Realizetype obj2 = (Realizetype) obj1.clone();
System.out.println("obj1==obj2?" + (obj1 == obj2));
}
}
//具体原型类
class Realizetype implements Cloneable {
Realizetype() {
System.out.println("具体原型创建成功!");
}
public Object clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (Realizetype) super.clone();
}
}