23种设计模式

23种设计模式总结(大白话,适合小白),完整例子讲解,明白怎么用,什么时候用,对比优缺点,不同之处

23种设计模式大白话总结(适合小白)

设计模式是解决代码问题的“经典套路”,就像烹饪的固定配方。以下是最通俗的解释+生活例子+代码片段,帮你快速理解每种模式的核心思想、适用场景和优缺点,并对比不同模式的区别!


一、创建型模式(5种)

核心目标:解决对象创建的问题,让代码灵活生成实例。

1. 单例模式(Singleton)

是什么:确保一个类只有一个实例,全局可访问。
例子:数据库连接池、全局配置对象。
代码

java

public class Singleton {
    private static Singleton instance;
    private Singleton() {} // 私有构造
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

何时用:需要严格控制实例数量时(如共享资源)。
优点:节省内存,避免重复创建。
缺点:多线程需加锁(可用双重检查锁优化)。


2. 工厂方法模式(Factory Method)

是什么:定义一个创建对象的接口,让子类决定实例化哪个类。
例子:物流系统,不同运输方式(卡车、轮船)由不同子工厂创建。
代码

java

interface Transport {
    void deliver();
}
class Truck implements Transport {
    public void deliver() { System.out.println("陆运"); }
}
class Ship implements Transport {
    public void deliver() { System.out.println("海运"); }
}

// 工厂接口
interface Logistics {
    Transport createTransport();
}
class RoadLogistics implements Logistics {
    public Transport createTransport() { return new Truck(); }
}
class SeaLogistics implements Logistics {
    public Transport createTransport() { return new Ship(); }
}

何时用:需要解耦对象创建和使用时。
优点:扩展性强(新增运输方式只需加子类)。
缺点:每新增一个产品就要新增一个工厂类。


3. 抽象工厂模式(Abstract Factory)

是什么:创建成套相关对象(如GUI组件:按钮+文本框)。
例子:Windows风格工厂生产Windows按钮和文本框,Mac工厂生产Mac风格组件。
代码

java

interface Button { void render(); }
interface TextBox { void input(); }

// Windows 系列组件
class WinButton implements Button {
    public void render() { System.out.println("Windows 按钮"); }
}
class WinTextBox implements TextBox {
    public void input() { System.out.println("Windows 输入框"); }
}

// Mac 系列组件
class MacButton implements Button {
    public void render() { System.out.println("Mac 按钮"); }
}
class MacTextBox implements TextBox {
    public void input() { System.out.println("Mac 输入框"); }
}

// 抽象工厂
interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}
class WinFactory implements GUIFactory {
    public Button createButton() { return new WinButton(); }
    public TextBox createTextBox() { return new WinTextBox(); }
}
class MacFactory implements GUIFactory {
    public Button createButton() { return new MacButton(); }
    public TextBox createTextBox() { return new MacTextBox(); }
}

何时用:需要保证产品兼容性时。
优点:产品族一致性高。
缺点:新增产品族需修改所有工厂。


4. 建造者模式(Builder)

是什么:分步骤构造复杂对象,支持灵活组合参数。
例子:组装电脑(CPU、内存、硬盘可自定义)。
代码

java

class Computer {
    private String CPU;
    private String RAM;
    // 私有构造,只能通过Builder创建
    private Computer(Builder builder) {
        this.CPU = builder.CPU;
        this.RAM = builder.RAM;
    }
    // 建造者
    public static class Builder {
        private String CPU;
        private String RAM;
        public Builder setCPU(String cpu) { this.CPU = cpu; return this; }
        public Builder setRAM(String ram) { this.RAM = ram; return this; }
        public Computer build() { return new Computer(this); }
    }
}

// 使用
Computer myPC = new Computer.Builder()
    .setCPU("Intel i9")
    .setRAM("32GB")
    .build();

何时用:对象构造参数多且可选时。
优点:避免构造方法过长。
缺点:代码量增加。


5. 原型模式(Prototype)

是什么:通过克隆现有对象创建新对象(而非new)。
例子:游戏中的怪物快速复制。
代码

java

class Monster implements Cloneable {
    private String type;
    public Monster(String type) { this.type = type; }
    @Override
    public Monster clone() throws CloneNotSupportedException {
        return (Monster) super.clone();
    }
}

// 使用
Monster dragon = new Monster("Dragon");
Monster dragon2 = dragon.clone(); // 克隆而不是新建

何时用:对象创建成本高时(如数据库初始化)。
优点:性能高(比new快)。
缺点:深拷贝需额外处理。


二、结构型模式(7种)

结构型设计模式主要解决如何组合类和对象来形成更大的结构,同时保持灵活性和可复用性。

核心目标:解决类和对象的组合问题,优化代码结构。

6. 适配器模式(Adapter)

是什么:让不兼容的接口协同工作。
例子:Type-C转3.5mm耳机转接头。
代码

java

// 旧接口(3.5mm耳机)
interface OldHeadphone {
    void playSound();
}
// 新接口(Type-C)
interface TypeC {
    void transmitDigital();
}
// 适配器
class Adapter implements OldHeadphone {
    private TypeC typeC;
    public Adapter(TypeC typeC) { this.typeC = typeC; }
    public void playSound() {
        typeC.transmitDigital(); // 调用新接口的方法
    }
}

何时用:旧系统兼容新接口时,整合老代码或第三方库时接口不兼容。
优点:无需修改原有代码,让不兼容的类一起工作。
缺点:增加调用层级,代码复杂度增加。


7. 装饰器模式(Decorator)

是什么:动态给对象添加功能(替代继承)。
例子:给人穿不同衣服(装饰),给咖啡加糖、加牛奶。
代码

java

// 基础接口
interface Coffee {
    int cost();
}

// 基础实现
class BasicCoffee implements Coffee {
    @Override
    public int cost() {
        return 10;
    }
}

// 装饰器基类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
}

// 具体装饰器(加糖)
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public int cost() {
        return coffee.cost() + 2;
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Coffee coffee = new BasicCoffee();
        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.cost()); // 输出12
    }
}

何时用:不想用继承,但需要动态扩展功能,需要灵活扩展对象功能时。
优点:灵活,避免继承导致的类爆炸。
缺点:多层装饰复杂,可能难调试。


8. 代理模式(Proxy)

是什么:通过代理控制对象访问(如权限验证)。
例子:延迟加载图片。
代码

java

interface Image {
    void display();
}

// 真实图片
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("加载图片: " + filename);
    }

    @Override
    public void display() {
        System.out.println("显示图片: " + filename);
    }
}

// 代理类
class ProxyImage implements Image {
    private String filename;
    private RealImage realImage;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Image image = new ProxyImage("photo.jpg");
        image.display(); // 第一次真正加载
        image.display(); // 直接使用缓存
    }
}

何时用:需要延迟加载或权限控制时。
优点:解耦客户端和实际对象,保护目标对象。
缺点:增加请求处理时间。


9. 组合模式(Composite)

是什么:统一处理单个对象和组合对象,用树形结构表示“部分-整体”关系。
例子:文件系统(文件夹包含文件/子文件夹)。
代码

java

interface Component {
    void operation();
}

// 叶子节点(文件)
class Leaf implements Component {
    @Override
    public void operation() {
        System.out.println("执行叶子节点操作");
    }
}

// 组合节点(文件夹)
class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    @Override
    public void operation() {
        for (Component child : children) {
            child.operation();
        }
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Composite root = new Composite();
        root.add(new Leaf());
        root.add(new Leaf());
        root.operation(); // 输出两次叶子操作
    }
}

何时用:处理树形结构(菜单、文件系统)。
优点:统一处理单个对象和组合对象。
缺点:设计抽象,业务复杂时难实现,叶子节点可能被迫实现不相关的方法。


10. 桥接模式(Bridge)

是什么:将抽象与实现分离,各自独立变化。
例子:不同颜色和形状的图形(如红色圆形、蓝色方形)。
代码

java

abstract class Shape {
    protected Color color;
    public Shape(Color color) { this.color = color; }
}
class Circle extends Shape { /* 具体实现 */ }

java

// 实现部分(渲染器)
interface Renderer {
    void renderCircle(int radius);
}

class VectorRenderer implements Renderer {
    @Override
    public void renderCircle(int radius) {
        System.out.println("矢量圆,半径" + radius);
    }
}

// 抽象部分(形状)
abstract class Shape {
    protected Renderer renderer;

    public Shape(Renderer renderer) {
        this.renderer = renderer;
    }

    abstract void draw();
}

class Circle extends Shape {
    private int radius;

    public Circle(Renderer renderer, int radius) {
        super(renderer);
        this.radius = radius;
    }

    @Override
    void draw() {
        renderer.renderCircle(radius);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Renderer vectorRenderer = new VectorRenderer();
        Circle circle = new Circle(vectorRenderer, 5);
        circle.draw(); // 输出矢量圆,半径5
    }
}

何时用:避免多层继承,独立扩展不同维度,多维度变化的场景。
优点:减少类数量,灵活扩展,解耦抽象和实现。
缺点:设计复杂度高。


11. 享元模式(Flyweight)

是什么:共享大量细粒度对象(如文字处理中的字符库),共享对象以减少内存占用。
例子:游戏中的重复小兵模型共享。
代码

java

class Bullet {
    private final String type; // 内部状态(可共享)

    public Bullet(String type) {
        this.type = type;
    }

    public void fire(int x, int y) { // 外部状态由参数传递
        System.out.println(type + "子弹发射到(" + x + "," + y + ")");
    }
}

class BulletFactory {
    private static final Map<String, Bullet> bullets = new HashMap<>();

    public static Bullet getBullet(String type) {
        if (!bullets.containsKey(type)) {
            bullets.put(type, new Bullet(type));
        }
        return bullets.get(type);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Bullet bullet1 = BulletFactory.getBullet("9mm");
        Bullet bullet2 = BulletFactory.getBullet("9mm");
        System.out.println(bullet1 == bullet2); // 输出true
        bullet1.fire(100, 200);
    }
}

何时用:系统有大量相似对象时,需要减少内存开销时。
优点:节省内存,大幅降低内存占用。
缺点:需要区分内部/外部状态。


12. 外观模式(Facade)

是什么:提供一个简化接口,隐藏系统复杂性,为复杂子系统提供统一入口。
例子:一键启动电脑(封装开机自检、加载系统等步骤)。
代码

java

class CPU {
    void start() { System.out.println("CPU启动"); }
}

class Memory {
    void start() { System.out.println("内存启动"); }
}

// 外观类(一键开机)
class ComputerFacade {
    private CPU cpu;
    private Memory memory;

    public ComputerFacade() {
        cpu = new CPU();
        memory = new Memory();
    }

    public void start() {
        cpu.start();
        memory.start();
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start(); // 隐藏复杂步骤
    }
}

何时用:简化客户端调用复杂系统时。
优点:降低使用复杂度。
缺点:不符合开闭原则(修改需改外观类),外观类可能变成“上帝类”。


三、行为型模式(11种)

行为型设计模式主要解决 对象之间的交互和职责分配,让代码更灵活、可维护。

核心目标:解决对象间的交互与职责分配问题。

13. 观察者模式(Observer)

是什么:一对多依赖,对象状态变化时通知所有依赖者。
例子:微信公众号(发布文章时通知所有订阅用户)。
代码

java

// 观察者接口
interface Subscriber {
    void update(String message);
}

// 被观察者(主题)
class WeChatPublicAccount {
    private List<Subscriber> subscribers = new ArrayList<>();

    public void addSubscriber(Subscriber sub) {
        subscribers.add(sub);
    }

    public void notifySubscribers(String message) {
        for (Subscriber sub : subscribers) {
            sub.update(message);
        }
    }
}

// 具体观察者
class User implements Subscriber {
    private String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " 收到消息:" + message);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        WeChatPublicAccount account = new WeChatPublicAccount();
        account.addSubscriber(new User("张三"));
        account.addSubscriber(new User("李四"));
        account.notifySubscribers("新文章发布了!");
    }
}

何时用:需要动态联动多个对象时。
优点:解耦观察者和被观察者。
缺点:通知顺序可能影响效率。


14. 策略模式(Strategy)

是什么:封装算法族,可动态切换。
例子:支付方式(支付宝、微信、银行卡)。
代码

java

// 策略接口
interface PaymentStrategy {
    void pay(int amount);
}

// 具体策略
class Alipay implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}

class WechatPay implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("微信支付:" + amount + "元");
    }
}

// 上下文(使用策略的类)
class ShoppingCart {
    private PaymentStrategy strategy;

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void checkout(int amount) {
        strategy.pay(amount);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.setStrategy(new Alipay());
        cart.checkout(100);  // 支付宝支付:100元
    }
}

何时用:需要灵活替换算法时。
优点:避免多重条件判断。
缺点:策略类数量多。


15. 模板方法模式(Template Method)

是什么:定义算法骨架,子类实现细节。
例子:咖啡和茶的制作流程(烧水、冲泡、加料)。
代码

java

abstract class Beverage {
    // 模板方法(固定流程)
    public final void prepare() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    void boilWater() {
        System.out.println("烧水");
    }

    abstract void brew();       // 子类实现
    abstract void addCondiments();

    void pourInCup() {
        System.out.println("倒入杯子");
    }
}

class Coffee extends Beverage {
    @Override
    void brew() {
        System.out.println("冲泡咖啡粉");
    }

    @Override
    void addCondiments() {
        System.out.println("加糖和牛奶");
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        coffee.prepare();  // 执行模板方法
    }
}

何时用:多个子类有公共流程时。
优点:代码复用性强。
缺点:子类可能影响父类逻辑。


16. 责任链模式(Chain of Responsibility)

是什么:将请求沿处理链传递,直到被处理。
例子:审批流程(员工→经理→CEO)。
代码

java

// 处理者接口
interface Handler {
    void setNext(Handler next);
    void handleRequest(int amount);
}

// 具体处理者
class GroupLeader implements Handler {
    private Handler next;

    @Override
    public void setNext(Handler next) {
        this.next = next;
    }

    @Override
    public void handleRequest(int amount) {
        if (amount <= 1000) {
            System.out.println("组长审批通过");
        } else if (next != null) {
            next.handleRequest(amount);
        }
    }
}

class Manager implements Handler {
    private Handler next;

    @Override
    public void setNext(Handler next) {
        this.next = next;
    }

    @Override
    public void handleRequest(int amount) {
        if (amount <= 5000) {
            System.out.println("经理审批通过");
        } else if (next != null) {
            next.handleRequest(amount);
        }
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Handler groupLeader = new GroupLeader();
        Handler manager = new Manager();
        groupLeader.setNext(manager);

        groupLeader.handleRequest(3000);  // 经理审批通过
    }
}

何时用:请求需多级处理时。
优点:解耦请求和处理者。
缺点:链长时性能低。


17. 状态模式(State)

是什么:对象行为随内部状态改变而改变。
例子:订单状态(待支付→已发货→已完成)。
代码

java

// 状态接口
interface State {
    void handle();
}

// 具体状态
class OnState implements State {
    @Override
    public void handle() {
        System.out.println("灯已开");
    }
}

class OffState implements State {
    @Override
    public void handle() {
        System.out.println("灯已关");
    }
}

// 上下文(状态持有者)
class LightSwitch {
    private State state;

    public void setState(State state) {
        this.state = state;
    }

    public void press() {
        state.handle();
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        LightSwitch light = new LightSwitch();
        light.setState(new OffState());
        light.press();  // 灯已关
        light.setState(new OnState());
        light.press();  // 灯已开
    }
}

何时用:对象有多个状态且行为不同时。
优点:取代大量if-else判断。
缺点:状态类数量多。


18. 命令模式(Command)

是什么:将请求封装为对象,支持撤销、排队。
例子:遥控器按键(每个按键对应一个命令)。
代码

java

// 命令接口
interface Command {
    void execute();
}

// 具体命令(开灯)
class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }
}

// 接收者(实际执行操作的对象)
class Light {
    public void turnOn() {
        System.out.println("灯亮了");
    }
}

// 调用者(遥控器按钮)
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Light light = new Light();
        Command lightOn = new LightOnCommand(light);
        
        RemoteControl remote = new RemoteControl();
        remote.setCommand(lightOn);
        remote.pressButton();  // 灯亮了
    }
}

何时用:需要记录操作历史或支持撤销时。
优点:解耦请求发起者和执行者。
缺点:命令类膨胀36。


19. 中介者模式(Mediator)

是什么:通过中介对象管理多个对象交互。
例子:聊天室(用户不直接对话,通过服务器中转)。
代码

java

class ChatRoom {
    public static void send(User user, String msg) { /* 转发消息 */ }
}

何时用:多对象交互复杂时。
优点:减少类间依赖。
缺点:中介类可能过于复杂。


20. 访问者模式(Visitor)

是什么:在不修改类的前提下,为类添加新操作。
例子:超市商品计价(不同商品类型用不同计价策略)。
代码

java

// 元素接口(商品)
interface Product {
    void accept(Visitor visitor);
}

// 具体元素
class Book implements Product {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public double getPrice() {
        return 50.0;
    }
}

// 访问者接口
interface Visitor {
    void visit(Book book);
}

// 具体访问者(价格计算)
class PriceVisitor implements Visitor {
    @Override
    public void visit(Book book) {
        System.out.println("书的价格:" + book.getPrice());
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Product book = new Book();
        Visitor visitor = new PriceVisitor();
        book.accept(visitor);  // 书的价格:50.0
    }
}

何时用:需为复杂对象结构添加新功能时。
优点:符合开闭原则。
缺点:增加新元素类困难。


21. 备忘录模式(Memento)

是什么:保存对象状态,支持回滚。
例子:游戏存档。
代码

java

复制

class Game {
    private String state;
    public Memento save() { return new Memento(state); }
    public void load(Memento m) { state = m.getState(); }
}

何时用:需要撤销/恢复功能时。
优点:状态保存与业务逻辑分离。
缺点:消耗内存。


22. 迭代器模式(Iterator)

是什么:提供统一方式遍历集合元素。
例子:遍历书架的书籍(隐藏底层存储结构)。
代码

java

复制

interface Iterator { 
    boolean hasNext(); 
    Object next();
}

何时用:需要统一遍历不同数据结构时。
优点:隐藏集合内部实现。
缺点:增加额外类。


23. 解释器模式(Interpreter)

是什么:定义语法规则,解释特定语言。
例子:SQL解析、数学表达式计算。
代码

java

复制

interface Expression { int interpret(Context context); }
class Add implements Expression {
    private Expression left, right;
    public int interpret(Context c) { return left.interpret(c) + right.interpret(c); }
}

何时用:需要解析特定语法时。
优点:易于扩展语法规则。
缺点:复杂语法难维护。


四、模式对比与总结

1. 创建型模式对比

模式核心思想典型应用场景
单例模式全局唯一实例配置管理、线程池
工厂方法子类决定创建对象物流运输、支付方式
抽象工厂创建成套对象跨平台UI组件库
建造者分步骤构造复杂对象自定义电脑配置
原型模式克隆代替新建游戏怪物生成

2. 行为型模式对比

对比总结

模式核心区别适用场景
适配器转换接口,让旧代码兼容新系统接口不兼容
装饰器动态添加功能,不修改原类灵活扩展功能
代理控制访问(权限、延迟加载)保护或优化访问
组合统一处理树形结构的节点菜单、文件系统
外观简化复杂系统的调用入口提供简洁接口
桥接分离抽象和实现,避免类爆炸多维度独立变化
享元共享对象,减少内存占用大量重复对象

如何选择

  • 要兼容接口?→ 适配器

  • 动态加功能?→ 装饰器

  • 控制访问?→ 代理

  • 处理树形结构?→ 组合

  • 简化复杂调用?→ 外观

  • 避免多维继承?→ 桥接

  • 节省内存?→ 享元

实际应用场景

  • 适配器:Java 的 InputStreamReader 将字节流转换为字符流。

  • 装饰器:Java IO 中的 BufferedReader 包装 FileReader

  • 代理:Spring AOP 中的动态代理。

  • 享元:Java 的 String 常量池。

3. 结构型模式对比

对比总结

模式核心区别适用场景
策略模式动态切换算法(如支付方式)多种算法需要灵活替换
观察者模式一对多依赖通知(如消息订阅)对象状态变化通知其他对象
责任链模式链式处理请求(如审批流程)请求需要多个对象处理
命令模式封装请求为对象(如遥控器按钮)请求参数化、队列化
模板方法模式固定流程,子类实现细节(如冲泡饮料)多个类有相同流程但不同步骤
状态模式对象行为随状态改变(如电灯开关)对象状态影响行为
访问者模式分离算法与对象结构(如统计商品价格)对复杂结构执行多种操作

如何选择

  • 需要动态切换算法 → 策略模式

  • 状态变化通知其他对象 → 观察者模式

  • 请求需要多级处理 → 责任链模式

  • 封装请求为对象 → 命令模式

  • 固定流程但有不同步骤 → 模板方法模式

  • 行为随状态改变 → 状态模式

  • 对复杂结构执行多种操作 → 访问者模式

实际应用场景

  • 策略模式:Java 的 Comparator 接口排序不同对象。

  • 观察者模式:Java 的 Swing 事件监听。

  • 责任链模式:Servlet 中的过滤器链。

  • 命令模式:Java 的 Runnable 接口。


五、如何选择设计模式?

  1. 先明确问题类型:创建对象?组合结构?行为交互?

  2. 查看模式适用场景:如需要全局唯一实例→单例;需要灵活扩展算法→策略。

  3. 权衡优缺点:如单例节省内存但难扩展,工厂模式灵活但增加类数量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值