什么是设计模式?
设计模式就像「编程界的套路」,是前人总结的 通用解决方案。
比如:
- 你想反复用一个东西(比如打印机),不想每次都新买,可以用 单例模式。
- 你想组装电脑(主板、CPU、显卡),不想直接跟零件打交道,可以用 建造者模式。
设计模式的分类
一共 23 种,主要分三类:
- 创建型模式(5 种):解决「怎么创建对象」的问题。
- 结构型模式(7 种):解决「对象怎么组合在一起」的问题。
- 行为型模式(11 种):解决「对象怎么交互」的问题。
一、创建型模式(创建对象)
1. 单例模式(Singleton)
核心思想:保证一个类 只有一个实例,比如公司的「公章」,全公司只能有一个。
例子:
- 你电脑里的「回收站」,不管打开多少次,都是同一个实例。
- 代码里的配置类(如数据库连接池),不需要重复创建。
代码演示(最简单的写法):
public class Singleton {
// 提前创建好唯一实例(静态变量)
private static final Singleton instance = new Singleton();
// 构造方法私有化,不让别人new
private Singleton() {}
// 提供一个方法,让别人获取实例
public static Singleton getInstance() {
return instance;
}
}
2. 工厂模式(Factory)
核心思想:找一个「工厂」帮你生产对象,比如「包子铺」生产包子,你不用自己揉面调馅。
例子:
- 你去奶茶店点「珍珠奶茶」,告诉店员需求,店员(工厂)会帮你组装好奶茶(对象)。
- Java 里的
Calendar.getInstance()
就是工厂模式,根据参数返回不同类型的日历对象。
代码演示(简单工厂):
// 产品接口:饮料
interface Drink {
void make();
}
// 具体产品:珍珠奶茶
class BubbleTea implements Drink {
public void make() {
System.out.println("制作珍珠奶茶:泡茶+加珍珠+加糖");
}
}
// 工厂类
class DrinkFactory {
public static Drink createDrink(String type) {
if ("bubble_tea".equals(type)) {
return new BubbleTea();
}
throw new IllegalArgumentException("不支持的饮料类型");
}
}
// 使用:
Drink tea = DrinkFactory.createDrink("bubble_tea");
tea.make(); // 输出:制作珍珠奶茶...
二、结构型模式(组合对象)
3. 装饰器模式(Decorator)
核心思想:给对象「动态添加功能」,像给蛋糕「加奶油、加水果」一样,不改变原有蛋糕的结构。
例子:
- 你点咖啡时,加奶泡、加糖浆、加焦糖,每次添加都是一个「装饰器」。
- Java IO 流中的
BufferedInputStream(new FileInputStream("file.txt"))
,就是用缓冲装饰文件流。
代码演示:
// 基础咖啡
abstract class Coffee {
public abstract String getDescription();
}
// 原味咖啡
class OriginalCoffee extends Coffee {
public String getDescription() {
return "原味咖啡";
}
}
// 装饰器:加奶泡
class MilkDecorator extends Coffee {
private Coffee coffee; // 持有被装饰的对象
public MilkDecorator(Coffee coffee) {
this.coffee = coffee;
}
public String getDescription() {
return coffee.getDescription() + " + 奶泡";
}
}
// 使用:
Coffee coffee = new MilkDecorator(new OriginalCoffee());
System.out.println(coffee.getDescription()); // 输出:原味咖啡 + 奶泡
4. 适配器模式(Adapter)
核心思想:把「不兼容的接口」转换成「兼容的接口」,像「电源适配器」把不同插头转为通用接口。
例子:
- 你有一个旧打印机(接口是 USB),但新电脑只有 Type-C 接口,需要一个 USB-Type-C 适配器。
- Java 中的
Arrays.asList()
把数组转为列表,就是适配器的一种应用。
代码演示(旧接口转新接口):
// 新接口:TypeC
interface TypeC {
void chargeWithTypeC();
}
// 旧设备:USB接口
class OldDevice {
public void chargeWithUSB() {
System.out.println("用USB充电");
}
}
// 适配器:将USB转为TypeC
class USBToTypeCAdapter implements TypeC {
private OldDevice oldDevice;
public USBToTypeCAdapter(OldDevice oldDevice) {
this.oldDevice = oldDevice;
}
public void chargeWithTypeC() {
oldDevice.chargeWithUSB(); // 调用旧接口实现新功能
}
}
// 使用:
OldDevice device = new OldDevice();
TypeC adapter = new USBToTypeCAdapter(device);
adapter.chargeWithTypeC(); // 输出:用USB充电(通过适配器实现)
三、行为型模式(对象交互)
5. 观察者模式(Observer)
核心思想:「观察者」关注「被观察者」的状态变化,一旦变化就触发动作,类似「粉丝关注明星动态」。
例子:
- 你关注了一个博主,他发新文章时(被观察者),你(观察者)会收到通知。
- Java 中的
ActionListener
(按钮点击监听)就是观察者模式的应用。
代码演示:
// 被观察者(博主)
class Blogger {
private List<Observer> observers = new ArrayList<>();
private String latestPost;
// 添加观察者(粉丝)
public void addObserver(Observer observer) {
observers.add(observer);
}
// 发布新文章
public void publishPost(String post) {
latestPost = post;
notifyObservers(); // 通知所有粉丝
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update(latestPost);
}
}
}
// 观察者(粉丝)
interface Observer {
void update(String post);
}
// 具体粉丝
class Fan implements Observer {
private String name;
public Fan(String name) {
this.name = name;
}
public void update(String post) {
System.out.println(name + " 收到新文章:" + post);
}
}
// 使用:
Blogger blogger = new Blogger();
Fan fan1 = new Fan("小明");
Fan fan2 = new Fan("小红");
blogger.addObserver(fan1);
blogger.addObserver(fan2);
blogger.publishPost("设计模式入门指南");
// 输出:
// 小明 收到新文章:设计模式入门指南
// 小红 收到新文章:设计模式入门指南
6. 策略模式(Strategy)
核心思想:定义一系列「策略」,可以动态切换使用,比如「出行方式」可以选开车、公交、步行。
例子:
- 电商平台的「支付方式」(支付宝、微信支付、银行卡),用户可以选择不同策略。
- Java 中的
Comparator
接口(排序策略),可以自定义不同的比较规则。
代码演示:
// 支付策略接口
interface PaymentStrategy {
void pay(double amount);
}
// 支付宝支付
class AlipayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("通过支付宝支付:" + amount + "元");
}
}
// 微信支付
class WechatPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("通过微信支付:" + amount + "元");
}
}
// 订单类(使用策略)
class Order {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void pay(double amount) {
paymentStrategy.pay(amount);
}
}
// 使用:
Order order = new Order();
order.setPaymentStrategy(new AlipayStrategy());
order.pay(100.0); // 输出:通过支付宝支付:100.0元
order.setPaymentStrategy(new WechatPayStrategy());
order.pay(50.0); // 输出:通过微信支付:50.0元
总结:为什么要用设计模式?
- 复用代码:避免重复写类似逻辑(如单例、工厂)。
- 解耦代码:让模块之间依赖更清晰(如观察者、策略)。
- 易维护:符合「开闭原则」(对扩展开放,对修改关闭),比如新增支付方式时,不用改订单类。