牛刀小试之设计模式

牛刀小试设计模式

目录

设计模式简介

什么是设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中一些不断重复出现的问题,以及该问题的解决方案。

设计模式的核心价值

1. 提高代码质量
  • 可读性:使用标准化的模式,代码更容易理解
  • 可维护性:结构清晰,便于修改和扩展
  • 可复用性:模式化的代码更容易在不同项目中复用
2. 解决常见问题
  • 解耦:降低类之间的耦合度
  • 扩展:便于功能的扩展和修改
  • 复用:提高代码的复用性
3. 团队协作
  • 沟通:团队成员对设计模式有共同理解
  • 规范:统一的代码设计规范
  • 效率:减少重复思考和设计时间

设计模式的历史

时间重要事件影响
1977年Christopher Alexander提出建筑模式概念为软件设计模式奠定基础
1994年Gang of Four (GoF) 发布《设计模式》正式确立23种经典设计模式
2002年Martin Fowler发布《企业应用架构模式》扩展了企业级应用设计模式
2008年微服务架构兴起涌现出新的架构模式
2014年响应式编程模式适应现代异步编程需求

设计模式分类

按目的分类

1. 创建型模式(Creational Patterns)

目的:解决对象创建的问题

模式名称英文名称主要作用使用频率
单例模式Singleton确保一个类只有一个实例⭐⭐⭐⭐⭐
工厂方法模式Factory Method创建对象而不指定具体类⭐⭐⭐⭐
抽象工厂模式Abstract Factory创建相关对象族⭐⭐⭐
建造者模式Builder分步构建复杂对象⭐⭐⭐
原型模式Prototype通过克隆创建对象⭐⭐
2. 结构型模式(Structural Patterns)

目的:解决类和对象的组合问题

模式名称英文名称主要作用使用频率
适配器模式Adapter让不兼容的接口协同工作⭐⭐⭐⭐
装饰器模式Decorator动态添加功能⭐⭐⭐⭐
代理模式Proxy为对象提供代理控制访问⭐⭐⭐⭐
外观模式Facade为子系统提供统一接口⭐⭐⭐
桥接模式Bridge分离抽象和实现⭐⭐
组合模式Composite树形结构处理⭐⭐
享元模式Flyweight共享细粒度对象
3. 行为型模式(Behavioral Patterns)

目的:解决对象间的通信和职责分配问题

模式名称英文名称主要作用使用频率
观察者模式Observer定义一对多依赖关系⭐⭐⭐⭐⭐
策略模式Strategy定义算法族,使它们可互换⭐⭐⭐⭐
命令模式Command将请求封装为对象⭐⭐⭐⭐
模板方法模式Template Method定义算法骨架⭐⭐⭐⭐
状态模式State改变对象行为⭐⭐⭐
责任链模式Chain of Responsibility避免请求发送者和接收者耦合⭐⭐⭐
迭代器模式Iterator顺序访问聚合对象⭐⭐⭐
中介者模式Mediator减少对象间直接交互⭐⭐
备忘录模式Memento保存和恢复对象状态⭐⭐
访问者模式Visitor在不改变类结构下定义新操作
解释器模式Interpreter定义语言语法

按范围分类

1. 类模式
  • 处理类与子类之间的关系
  • 通过继承建立关系
  • 编译时确定关系

典型模式

  • 模板方法模式
  • 工厂方法模式
  • 适配器模式(类适配器)
2. 对象模式
  • 处理对象间的关系
  • 通过组合建立关系
  • 运行时确定关系

典型模式

  • 单例模式
  • 观察者模式
  • 策略模式
  • 装饰器模式

设计模式使用场景

创建型模式使用场景

1. 单例模式

适用场景

  • 需要全局唯一实例的类
  • 资源管理器(数据库连接池、线程池)
  • 配置管理器
  • 日志记录器
// 线程安全的单例模式
public class DatabaseConnection {
    private static volatile DatabaseConnection instance;
  
    private DatabaseConnection() {}
  
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            synchronized (DatabaseConnection.class) {
                if (instance == null) {
                    instance = new DatabaseConnection();
                }
            }
        }
        return instance;
    }
}
2. 工厂方法模式

适用场景

  • 创建对象时不知道具体类型
  • 需要根据条件创建不同对象
  • 希望扩展产品类型
// 支付方式工厂
public interface PaymentFactory {
    Payment createPayment();
}

public class AlipayFactory implements PaymentFactory {
    @Override
    public Payment createPayment() {
        return new AlipayPayment();
    }
}

public class WechatPayFactory implements PaymentFactory {
    @Override
    public Payment createPayment() {
        return new WechatPayPayment();
    }
}
3. 建造者模式

适用场景

  • 构建复杂对象
  • 需要分步构建
  • 构建过程需要灵活配置
// 用户信息建造者
public class User {
    private String name;
    private String email;
    private int age;
    private String address;
  
    private User(Builder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.address = builder.address;
    }
  
    public static class Builder {
        private String name;
        private String email;
        private int age;
        private String address;
      
        public Builder name(String name) {
            this.name = name;
            return this;
        }
      
        public Builder email(String email) {
            this.email = email;
            return this;
        }
      
        public Builder age(int age) {
            this.age = age;
            return this;
        }
      
        public Builder address(String address) {
            this.address = address;
            return this;
        }
      
        public User build() {
            return new User(this);
        }
    }
}

结构型模式使用场景

1. 适配器模式

适用场景

  • 使用第三方库时接口不匹配
  • 系统升级时保持向后兼容
  • 集成不同厂商的组件
// 媒体播放器适配器
public interface MediaPlayer {
    void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer {
    void playVlc(String fileName);
    void playMp4(String fileName);
}

public class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer advancedMusicPlayer;
  
    public MediaAdapter(String audioType) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMusicPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMusicPlayer = new Mp4Player();
        }
    }
  
    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMusicPlayer.playVlc(fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMusicPlayer.playMp4(fileName);
        }
    }
}
2. 装饰器模式

适用场景

  • 需要动态添加功能
  • 不能使用继承时
  • 需要透明地扩展对象功能
// 咖啡装饰器
public abstract class Coffee {
    public abstract String getDescription();
    public abstract double cost();
}

public class SimpleCoffee extends Coffee {
    @Override
    public String getDescription() {
        return "Simple coffee";
    }
  
    @Override
    public double cost() {
        return 1.0;
    }
}

public abstract class CoffeeDecorator extends Coffee {
    protected Coffee coffee;
  
    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
}

public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
  
    @Override
    public String getDescription() {
        return coffee.getDescription() + ", milk";
    }
  
    @Override
    public double cost() {
        return coffee.cost() + 0.5;
    }
}
3. 代理模式

适用场景

  • 需要控制对对象的访问
  • 延迟加载
  • 缓存代理
  • 权限控制
// 图片代理
public interface Image {
    void display();
}

public class RealImage implements Image {
    private String fileName;
  
    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(fileName);
    }
  
    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }
  
    private void loadFromDisk(String fileName) {
        System.out.println("Loading " + fileName);
    }
}

public class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;
  
    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }
  
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}

行为型模式使用场景

1. 观察者模式

适用场景

  • 一对多依赖关系
  • 事件处理系统
  • 模型-视图架构
  • 发布-订阅系统
// 新闻发布订阅系统
public interface Observer {
    void update(String news);
}

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

public class NewsAgency implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;
  
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
  
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
  
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(news);
        }
    }
  
    public void setNews(String news) {
        this.news = news;
        notifyObservers();
    }
}

public class NewsChannel implements Observer {
    private String name;
  
    public NewsChannel(String name) {
        this.name = name;
    }
  
    @Override
    public void update(String news) {
        System.out.println(name + " received news: " + news);
    }
}
2. 策略模式

适用场景

  • 需要动态选择算法
  • 算法族需要互换
  • 避免使用多重条件判断
// 支付策略
public interface PaymentStrategy {
    void pay(double amount);
}

public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;
    private String cvv;
  
    public CreditCardPayment(String cardNumber, String cvv) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }
  
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card");
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;
  
    public PayPalPayment(String email) {
        this.email = email;
    }
  
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal");
    }
}

public class PaymentContext {
    private PaymentStrategy strategy;
  
    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
  
    public void executePayment(double amount) {
        strategy.pay(amount);
    }
}
3. 命令模式

适用场景

  • 需要撤销/重做操作
  • 需要将请求排队
  • 需要支持日志和事务
// 遥控器命令
public interface Command {
    void execute();
    void undo();
}

public class Light {
    public void on() {
        System.out.println("Light is on");
    }
  
    public void off() {
        System.out.println("Light is off");
    }
}

public class LightOnCommand implements Command {
    private Light light;
  
    public LightOnCommand(Light light) {
        this.light = light;
    }
  
    @Override
    public void execute() {
        light.on();
    }
  
    @Override
    public void undo() {
        light.off();
    }
}

public class RemoteControl {
    private Command command;
  
    public void setCommand(Command command) {
        this.command = command;
    }
  
    public void pressButton() {
        command.execute();
    }
  
    public void pressUndo() {
        command.undo();
    }
}

设计模式重难点分析

创建型模式重难点

1. 单例模式

重难点

  • 线程安全:多线程环境下的实例创建
  • 序列化:防止反序列化创建新实例
  • 反射攻击:防止通过反射创建实例
  • 内存泄漏:静态实例的生命周期管理

解决方案

// 枚举单例(推荐)
public enum Singleton {
    INSTANCE;
  
    public void doSomething() {
        // 业务逻辑
    }
}

// 双重检查锁定
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;
    }
}
2. 工厂模式

重难点

  • 简单工厂 vs 工厂方法:选择合适的工厂模式
  • 抽象工厂的复杂性:管理多个产品族
  • 扩展性:添加新产品时的修改成本

解决方案

// 使用反射的通用工厂
public class GenericFactory<T> {
    private Map<String, Class<? extends T>> registeredClasses = new HashMap<>();
  
    public void registerClass(String type, Class<? extends T> clazz) {
        registeredClasses.put(type, clazz);
    }
  
    public T create(String type) {
        Class<? extends T> clazz = registeredClasses.get(type);
        if (clazz == null) {
            throw new IllegalArgumentException("Unknown type: " + type);
        }
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Failed to create instance", e);
        }
    }
}

结构型模式重难点

1. 适配器模式

重难点

  • 类适配器 vs 对象适配器:选择合适的实现方式
  • 接口设计:如何设计合适的适配器接口
  • 性能影响:适配器可能带来的性能开销

解决方案

// 对象适配器(推荐)
public class ObjectAdapter implements Target {
    private Adaptee adaptee;
  
    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
  
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}
2. 装饰器模式

重难点

  • 装饰器链:多个装饰器的组合使用
  • 顺序问题:装饰器的应用顺序
  • 性能考虑:装饰器链的性能影响

解决方案

// 装饰器链管理
public class DecoratorChain {
    private List<Decorator> decorators = new ArrayList<>();
  
    public void addDecorator(Decorator decorator) {
        decorators.add(decorator);
    }
  
    public Component build(Component component) {
        Component result = component;
        for (Decorator decorator : decorators) {
            result = decorator.decorate(result);
        }
        return result;
    }
}

行为型模式重难点

1. 观察者模式

重难点

  • 内存泄漏:观察者未正确移除
  • 通知顺序:多个观察者的通知顺序
  • 异常处理:观察者处理异常时的策略

解决方案

// 安全的观察者模式
public class SafeSubject implements Subject {
    private List<Observer> observers = new CopyOnWriteArrayList<>();
  
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            try {
                observer.update();
            } catch (Exception e) {
                // 记录异常,不影响其他观察者
                System.err.println("Observer failed: " + e.getMessage());
            }
        }
    }
}
2. 策略模式

重难点

  • 策略选择:如何选择合适的策略
  • 策略切换:运行时策略切换的复杂性
  • 策略组合:多个策略的组合使用

解决方案

// 策略选择器
public class StrategySelector {
    private Map<String, Strategy> strategies = new HashMap<>();
  
    public void registerStrategy(String key, Strategy strategy) {
        strategies.put(key, strategy);
    }
  
    public Strategy selectStrategy(String key) {
        Strategy strategy = strategies.get(key);
        if (strategy == null) {
            throw new IllegalArgumentException("Unknown strategy: " + key);
        }
        return strategy;
    }
}

设计模式在实际项目中的应用

Spring框架中的设计模式

1. 单例模式
// Spring Bean默认单例
@Component
public class UserService {
    // Spring容器管理单例
}

// 配置单例
@Configuration
public class AppConfig {
    @Bean
    @Scope("singleton")
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}
2. 工厂模式
// Spring的BeanFactory
@Configuration
public class PaymentConfig {
    @Bean
    public PaymentFactory paymentFactory() {
        return new PaymentFactory();
    }
  
    @Bean
    public PaymentService paymentService(PaymentFactory factory) {
        return new PaymentService(factory);
    }
}
3. 代理模式
// Spring AOP代理
@Service
public class UserService {
  
    @Transactional
    public void saveUser(User user) {
        // 业务逻辑
    }
  
    @Cacheable("users")
    public User findById(Long id) {
        // 查询逻辑
    }
}
4. 观察者模式
// Spring事件机制
@Component
public class UserEventListener {
  
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        // 处理用户创建事件
    }
  
    @EventListener
    public void handleUserUpdated(UserUpdatedEvent event) {
        // 处理用户更新事件
    }
}

// 发布事件
@Service
public class UserService {
  
    @Autowired
    private ApplicationEventPublisher eventPublisher;
  
    public void createUser(User user) {
        // 创建用户逻辑
        eventPublisher.publishEvent(new UserCreatedEvent(user));
    }
}

微服务架构中的设计模式

1. 服务发现模式
// 服务注册
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

// 服务发现
@Service
public class OrderService {
  
    @Autowired
    private DiscoveryClient discoveryClient;
  
    public List<ServiceInstance> getUserServiceInstances() {
        return discoveryClient.getInstances("user-service");
    }
}
2. 熔断器模式
// Hystrix熔断器
@Service
public class UserService {
  
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public User getUser(Long id) {
        // 调用远程服务
        return userClient.getUser(id);
    }
  
    public User getUserFallback(Long id) {
        return new User(id, "Default User");
    }
}
3. 网关模式
// Spring Cloud Gateway
@Configuration
public class GatewayConfig {
  
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service", r -> r.path("/api/users/**")
                .uri("lb://user-service"))
            .route("order-service", r -> r.path("/api/orders/**")
                .uri("lb://order-service"))
            .build();
    }
}

数据库操作中的设计模式

1. 仓储模式
// 通用仓储接口
public interface Repository<T, ID> {
    T save(T entity);
    Optional<T> findById(ID id);
    List<T> findAll();
    void deleteById(ID id);
}

// 用户仓储
@Repository
public class UserRepository implements Repository<User, Long> {
  
    @Autowired
    private JdbcTemplate jdbcTemplate;
  
    @Override
    public User save(User user) {
        // 保存用户逻辑
        return user;
    }
  
    @Override
    public Optional<User> findById(Long id) {
        // 查询用户逻辑
        return Optional.empty();
    }
}
2. 工作单元模式
// 工作单元接口
public interface UnitOfWork {
    void registerNew(Object entity);
    void registerDirty(Object entity);
    void registerDeleted(Object entity);
    void commit();
    void rollback();
}

// 工作单元实现
@Component
public class JpaUnitOfWork implements UnitOfWork {
  
    @Autowired
    private EntityManager entityManager;
  
    private List<Object> newEntities = new ArrayList<>();
    private List<Object> dirtyEntities = new ArrayList<>();
    private List<Object> deletedEntities = new ArrayList<>();
  
    @Override
    public void registerNew(Object entity) {
        newEntities.add(entity);
    }
  
    @Override
    public void commit() {
        try {
            for (Object entity : newEntities) {
                entityManager.persist(entity);
            }
            for (Object entity : dirtyEntities) {
                entityManager.merge(entity);
            }
            for (Object entity : deletedEntities) {
                entityManager.remove(entity);
            }
            entityManager.getTransaction().commit();
        } catch (Exception e) {
            entityManager.getTransaction().rollback();
            throw e;
        }
    }
}

缓存设计中的设计模式

1. 装饰器模式
// 缓存装饰器
public class CachedUserService implements UserService {
  
    private final UserService userService;
    private final CacheManager cacheManager;
  
    public CachedUserService(UserService userService, CacheManager cacheManager) {
        this.userService = userService;
        this.cacheManager = cacheManager;
    }
  
    @Override
    public User findById(Long id) {
        Cache cache = cacheManager.getCache("users");
        User user = cache.get(id, User.class);
      
        if (user == null) {
            user = userService.findById(id);
            cache.put(id, user);
        }
      
        return user;
    }
}
2. 策略模式
// 缓存策略
public interface CacheStrategy {
    void put(String key, Object value);
    Object get(String key);
    void evict(String key);
}

// LRU缓存策略
public class LRUCacheStrategy implements CacheStrategy {
    private final Map<String, Object> cache = new LinkedHashMap<String, Object>(16, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
            return size() > 1000;
        }
    };
  
    @Override
    public synchronized void put(String key, Object value) {
        cache.put(key, value);
    }
  
    @Override
    public synchronized Object get(String key) {
        return cache.get(key);
    }
}

设计模式最佳实践

1. 模式选择原则

何时使用设计模式
  • 问题重复出现:相同问题多次遇到
  • 代码结构复杂:需要更好的组织结构
  • 团队协作:需要统一的代码规范
  • 系统扩展:需要支持未来扩展
何时不使用设计模式
  • 过度设计:简单问题不需要复杂模式
  • 性能敏感:模式可能带来性能开销
  • 团队不熟悉:团队对模式理解不够
  • 项目时间紧张:没有足够时间设计

2. 模式组合使用

常见模式组合
// 工厂 + 单例 + 策略
public class PaymentProcessor {
    private static final PaymentProcessor INSTANCE = new PaymentProcessor();
    private final Map<String, PaymentStrategy> strategies = new HashMap<>();
  
    private PaymentProcessor() {
        // 注册策略
        strategies.put("credit", new CreditCardStrategy());
        strategies.put("paypal", new PayPalStrategy());
    }
  
    public static PaymentProcessor getInstance() {
        return INSTANCE;
    }
  
    public void processPayment(String type, double amount) {
        PaymentStrategy strategy = strategies.get(type);
        if (strategy != null) {
            strategy.pay(amount);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + type);
        }
    }
}

3. 反模式识别

常见反模式
  • God Object:一个类承担过多职责
  • Spaghetti Code:代码结构混乱
  • Copy-Paste Programming:重复代码过多
  • Golden Hammer:过度使用某个模式
解决方案
// 反模式:God Object
public class UserManager {
    public void createUser() { /* ... */ }
    public void updateUser() { /* ... */ }
    public void deleteUser() { /* ... */ }
    public void sendEmail() { /* ... */ }
    public void logActivity() { /* ... */ }
    public void generateReport() { /* ... */ }
}

// 改进:职责分离
public class UserService {
    public void createUser() { /* ... */ }
    public void updateUser() { /* ... */ }
    public void deleteUser() { /* ... */ }
}

public class EmailService {
    public void sendEmail() { /* ... */ }
}

public class LoggingService {
    public void logActivity() { /* ... */ }
}

public class ReportService {
    public void generateReport() { /* ... */ }
}

4. 性能考虑

模式性能影响
模式性能影响建议
单例模式推荐使用
工厂模式推荐使用
装饰器模式注意装饰器链长度
代理模式考虑动态代理开销
观察者模式注意观察者数量
策略模式推荐使用
性能优化建议
// 对象池模式
public class ObjectPool<T> {
    private final Queue<T> pool = new ConcurrentLinkedQueue<>();
    private final Supplier<T> factory;
    private final int maxSize;
  
    public ObjectPool(Supplier<T> factory, int maxSize) {
        this.factory = factory;
        this.maxSize = maxSize;
    }
  
    public T acquire() {
        T object = pool.poll();
        if (object == null) {
            object = factory.get();
        }
        return object;
    }
  
    public void release(T object) {
        if (pool.size() < maxSize) {
            pool.offer(object);
        }
    }
}

总结

设计模式的核心价值

  1. 提高代码质量:使代码更加清晰、可维护、可扩展
  2. 解决常见问题:提供经过验证的解决方案
  3. 促进团队协作:建立统一的代码设计规范
  4. 降低学习成本:新团队成员更容易理解代码

学习建议

  1. 循序渐进:从简单模式开始,逐步学习复杂模式
  2. 实践为主:通过实际项目应用模式
  3. 理解原理:不仅要知道如何使用,更要理解为什么
  4. 避免过度使用:根据实际需要选择合适的模式

未来趋势

  1. 函数式编程模式:适应现代编程范式
  2. 响应式编程模式:处理异步和流式数据
  3. 微服务架构模式:支持分布式系统设计
  4. 云原生模式:适应云计算环境

设计模式是软件工程中的重要工具,掌握它们能够显著提高代码质量和开发效率。但记住,模式是工具,不是目的,应该根据实际需要合理使用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值