23种设计模式-软件设计原则

        在软件开发过程中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性。要尽量根据6条开发原则来开发程序,从而提高软件开发效率、节约开发成本和维护成本。

一、开闭原则

        对扩展开放,对修改关闭。在程序需要进行扩展时,不能去修改原有的代码,而是增加新的接口来对功能进行升级,实现一个热插拔效果,总而言之,是为了是程序的扩展型提高,便于维护和迭代更新。

        而想实现这样的效果,我们需要使用接口和抽象类。

        之所以使用它们,是因为抽象类与接口的灵活性好,只要抽象方法合理,可以保持软甲架构的稳定。而软件中的容易发生变动的细节可以将其抽象出来,来进行扩展,当软件需求发生变化时,只需要在派生一个类即可实现新需求。即写一个新的实现类来实现原来的接口

        基类 --包含main方法

package com.xiao.principles.opendemo;

import com.xiao.principles.opendemo.impl.DefaultOpen;
import com.xiao.principles.opendemo.impl.NewOpen;

import java.util.HashMap;
import java.util.Map;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/13 23:17
 * @description: 开闭原则的基类
 * @modified By:Mr~肖
 * @version: 1.0
 */
public abstract class BaseOpenClose {
    /**
     * 抽象方法
     */
    public abstract void display();

    public static void main(String[] args) {
        //模拟接口
        //调用默认方法
        printDisPlay("default");
        System.out.println("---------------分割线---------------");
        //调用新方法
        printDisPlay("new");
    }
    private static void printDisPlay(String key) {
        //定义两个实现类
        BaseOpenClose defaultOpen = new DefaultOpen();
        BaseOpenClose newOpen = new NewOpen();
        //定义一个map进行存放数据
        Map<String,BaseOpenClose> map = new HashMap<>(4);
        map.put("default",defaultOpen);
        map.put("new",newOpen);
        //根据不同的选择调用不同的类
        map.get(key).display();
    }
}

默认实现类

package com.xiao.principles.opendemo.impl;

import com.xiao.principles.opendemo.BaseOpenClose;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/13 23:22
 * @description:默认实现类
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class DefaultOpen extends BaseOpenClose {
    @Override
    public void display() {
        System.out.println("我是默认的方法");
    }
}

新的实现类

package com.xiao.principles.opendemo.impl;

import com.xiao.principles.opendemo.BaseOpenClose;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/13 23:23
 * @description:新的扩展出来的方法
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class NewOpen extends BaseOpenClose {
    @Override
    public void display() {
        System.out.println("我是扩展出来的方法");
    }
}

输出结果

我是默认的方法
---------------分割线---------------
我是扩展出来的方法

以上模拟了一个调用,我在这里将每一个方法都放到map集合内部根据新的需求调用不同的方法,如果还需要新增类,则在继承抽象类BaseOpenClose即可,而无需在修改原来的抽象类与实现类

二、里氏代换原则

        里氏代换原则是面向对象设计的基本原则之一。

        里氏代换原则:任何基类可以出现的地方,子类一定也可以出现。即子类扩展父类的功能,但不能改变父类原有的功能,子类在继承父类时,除了添加新的方法完成新增功能外,尽量不重写父类原有的方法。

        如果通过重写父类的方法来完成新的功能,这样写起来简单,但是整个继承体系就变得非常差,特别是多态使用频繁的时候,程序大概率会出现问题。

        测试

package com.xiao.principles.richterdemo.before;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 22:12
 * @description:长方形类---父类
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeforeRectangle {
    /**
     * 定义长方形的长
     */
    private int length;
    /**
     * 定义长方形的宽
     */
    private int width;
}





package com.xiao.principles.richterdemo.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 22:14
 * @description:正方形
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class BeforeSquare extends BeforeRectangle {
    /**
     * 将长赋值给正方形的宽高
     * @param length 长
     */
    @Override
    public void setLength(int length) {
        super.setLength(length);
        super.setWidth(length);
    }
    /**
     * 将宽赋值给正方形的宽高
     * @param width 宽
     */
    @Override
    public void setWidth(int width) {
        super.setLength(width);
        super.setWidth(width);
    }
}





package com.xiao.principles.richterdemo.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 0:06
 * @description:里氏代换原则基类
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class RichterTest {
    public static void main(String[] args) {
        BeforeRectangle rectangle = new BeforeRectangle(5, 2);
        BeforeRectangle square = new BeforeSquare();
        reSize(rectangle);
        System.out.println("----------------");
        square.setWidth(5);
        reSize(square);
    }

    /**
     * 重新设定长方形的宽
     * @param b 长方形对象
     */
    public static void reSize(BeforeRectangle b) {
        while (b.getWidth() <= b.getLength()) {
            b.setWidth(b.getWidth() + 1);
        }
        //打印长方形的长和宽
        printLength(b);
    }

    /**
     * 打印长方形的长和宽
     * @param b 长方形对象
     */
    private static void printLength(BeforeRectangle b) {
        System.out.println("长:"+b.getLength());
        System.out.println("宽:"+b.getWidth());
    }

}


        其结果为:

长:5
宽:6
----------------

 可以看到正方形的数据没有打印出来(无法打印,会陷入死循环)则违背了里氏代换原则,对其修改

package com.xiao.principles.richterdemo.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 23:06
 * @description:四边形接口-将get方法提取出来
 * @modified By:Mr~肖
 * @version: 1.0
 */
public interface Quadrangle {
    /**
     * 获取宽
     * @return 返回宽
     */
    int getWidth();

    /**
     * 获取长
     * @return 返回长
     */
    int getLength();
}

package com.xiao.principles.richterdemo.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 23:09
 * @description:长方形类
 * @modified By:Mr~肖
 * @version: 2.0
 */
public class AfterRectangle implements Quadrangle{
    /**
     * 定义长方形的长
     */
    private int length;
    /**
     * 定义长方形的宽
     */
    private int width;

    @Override
    public int getLength() {
        return length;
    }

    @Override
    public int getWidth() {
        return width;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public void setWidth(int width) {
        this.width = width;
    }
}

package com.xiao.principles.richterdemo.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 23:12
 * @description:正方形类
 * @modified By:Mr~肖
 * @version: 2.0
 */
public class AfterSquare implements Quadrangle{
    /**
     * 边长
     */
    private int side;

    public int getSide() {
        return side;
    }

    public void setSide(int side) {
        this.side = side;
    }

    @Override
    public int getWidth() {
        return side;
    }

    @Override
    public int getLength() {
        return side;
    }
}

package com.xiao.principles.richterdemo.after;

import com.xiao.principles.richterdemo.before.BeforeRectangle;
import com.xiao.principles.richterdemo.before.BeforeSquare;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/14 23:14
 * @description: 修改后测试类
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class AfterTest {
    public static void main(String[] args) {
        AfterRectangle a = new AfterRectangle();
        a.setLength(5);
        a.setWidth(2);
        reSize(a);
        System.out.println("----------------");
    }

    /**
     * 重新设定长方形的宽
     * @param a 长方形对象
     */
    public static void reSize(AfterRectangle a) {
        while (a.getWidth() <= a.getLength()) {
            a.setWidth(a.getWidth() + 1);
        }
        //打印长方形的长和宽
        printLength(a);
    }

    /**
     * 打印长方形的长和宽
     * @param a 长方形对象
     */
    private static void printLength(AfterRectangle a) {
        System.out.println("长:"+a.getLength());
        System.out.println("宽:"+a.getWidth());
    }

}

        修改后的方法,此时的正方形接口就无法调用改变宽的接口了(未完成)

三、依赖倒转原则

        依赖倒转:高层模块不应该依赖低层模块,两者都应该以来其抽象;抽象不应该以来细节,细节应该依赖抽象。简单来说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块之间的耦合。是开闭原则的具体实现

package com.xiao.principles.demo1.c_dependenceinversion.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 20:00
 * @description:希捷硬盘
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class XiJieHardDisk {
    public void save(String data){
        System.out.println("使用硬盘存储"+data);
    }
    public String getData() {
        System.out.println("获取文件");
        return "文件1";
    }
}


package com.xiao.principles.demo1.c_dependenceinversion.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 20:04
 * @description:金士顿内存条
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class KingstonMemory {
    public void save(){
        System.out.println("使用金士顿内存条");
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 20:02
 * @description:英特尔cpu
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class IntelCpu {
    /**
     *使用Cpu运行
     */
    public void run() {
        System.out.println("使用英特尔cpu运行程序");
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.before;

import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 20:06
 * @description: 计算机类
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
public class Computer {
    /**
     * cpu
     */
    private IntelCpu cpu;
    /**
     * 内存条
     */
    private KingstonMemory memory;
    /**
     * 硬盘
     */
    private XiJieHardDisk hardDisk;

    public void run() {
        System.out.println("运行计算机");
        hardDisk.getData();
        cpu.run();
        memory.save();
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.before;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 20:11
 * @description:计算机测试类
 * @modified By:Mr~肖
 * @version:
 */
public class ComputerTest {
    public static void main(String[] args) {
        IntelCpu cpu = new IntelCpu();
        KingstonMemory memory = new KingstonMemory();
        XiJieHardDisk hardDisk = new XiJieHardDisk();
        Computer computer = new Computer();
        computer.setCpu(cpu);
        computer.setMemory(memory);
        computer.setHardDisk(hardDisk);
        computer.run();
    }
}

上面这些代码能满足条件,一旦用户要使用其他组件就需要更改代码,不满足开闭原则,因此对cpu,memory,hardDisk进行抽象化处理,以便满足开闭原则同时满足依赖倒转原则

接口

package com.xiao.principles.demo1.c_dependenceinversion.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:38
 * @description:cpu接口所有cpu的上级接口
 * @modified By:Mr~肖
 * @version: 1.0
 */
public interface Cpu {
    void run();
}



package com.xiao.principles.demo1.c_dependenceinversion.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:40
 * @description:硬盘接口
 * @modified By:Mr~肖
 * @version: 1.0
 */
public interface HardDisk {

    public void save(String data);
    public String getData() ;
}


package com.xiao.principles.demo1.c_dependenceinversion.after;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:39
 * @description:内存条接口
 * @modified By:Mr~肖
 * @version: 1.0
 */
public interface Memory {
    void save();
}

实现类

package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.Cpu;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:40
 * @description:A品牌Cpu
 * @modified By:Mr~肖
 * @version:1.0
 */
public class ACpu implements Cpu {
    @Override
    public void run() {
        System.out.println("CpuA开始运行");
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.Cpu;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:40
 * @description:B品牌Cpu
 * @modified By:Mr~肖
 * @version:1.0
 */
public class BCpu implements Cpu {
    @Override
    public void run() {
        System.out.println("CpuB开始运行");
    }
}
package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.HardDisk;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:44
 * @description:A品牌硬盘
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class AHardDisk implements HardDisk {
    @Override
    public void save(String data) {
        System.out.println("使用A硬盘存储"+data);
    }

    @Override
    public String getData() {
        System.out.println("获取文件A");
        return "文件A";
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.HardDisk;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:44
 * @description:B品牌硬盘
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class BHardDisk implements HardDisk {
    @Override
    public void save(String data) {
        System.out.println("使用B硬盘存储"+data);
    }

    @Override
    public String getData() {
        System.out.println("获取文件B");
        return "文件B";
    }
}
package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.Memory;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:42
 * @description:A品牌内存条
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class AMemory implements Memory {
    @Override
    public void save() {
        System.out.println("A品牌内存条保存文件");
    }
}

package com.xiao.principles.demo1.c_dependenceinversion.after.impl;

import com.xiao.principles.demo1.c_dependenceinversion.after.Memory;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:42
 * @description:B品牌内存条
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class BMemory implements Memory {
    @Override
    public void save() {
        System.out.println("B品牌内存条保存文件");
    }
}

计算机实体类

package com.xiao.principles.demo1.c_dependenceinversion.after.test;

import com.xiao.principles.demo1.c_dependenceinversion.after.Cpu;
import com.xiao.principles.demo1.c_dependenceinversion.after.HardDisk;
import com.xiao.principles.demo1.c_dependenceinversion.after.Memory;
import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:50
 * @description:计算机类1
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
public class Computer1 {

    /**
     * cpu
     */
    private Cpu cpu;
    /**
     * 内存条
     */
    private Memory memory;
    /**
     * 硬盘
     */
    private HardDisk hardDisk;

    public void run() {
        System.out.println("运行计算机");
        hardDisk.getData();
        cpu.run();
        memory.save();
    }
}

测试类

package com.xiao.principles.demo1.c_dependenceinversion.after.test;

import com.xiao.principles.demo1.c_dependenceinversion.after.Cpu;
import com.xiao.principles.demo1.c_dependenceinversion.after.HardDisk;
import com.xiao.principles.demo1.c_dependenceinversion.after.Memory;
import com.xiao.principles.demo1.c_dependenceinversion.after.impl.*;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 22:47
 * @description:测试1
 * @modified By:Mr~肖
 * @version:
 */
public class ComputerTest1 {
    public static void main(String[] args) {
        Computer1 c = new Computer1();
        Cpu  aCpu = new ACpu();
        Cpu bCpu = new BCpu();
        HardDisk aHardDisk = new AHardDisk();
        HardDisk bHardDisk = new BHardDisk();
        Memory aMemory = new AMemory();
        Memory bMemory = new BMemory();

        //此时可自己组装电脑类
        c.setHardDisk(aHardDisk);
        c.setCpu(bCpu);
        c.setMemory(bMemory);
        c.run();
    }
}

输出结果

运行计算机
获取文件A
CpuB开始运行
B品牌内存条保存文件

四、接口隔离原则

        客户端不应该被迫依赖于它不使用的方法:一个类对另一个类的依赖应该建立在最小的接口上。

接口

package com.xiao.principles.demo1.d_segregation;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:12
 * @description:b方法接口
 * @modified By:Mr~肖
 * @version: 1.0
 */
public interface AMethod {
    void method1();
}

package com.xiao.principles.demo1.d_segregation;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:13
 * @description: b方法接口
 * @modified By:Mr~肖
 * @version:1.0
 */
public interface BMethod {
    void method2();
}

 对应的品牌

package com.xiao.principles.demo1.d_segregation.impl;

import com.xiao.principles.demo1.d_segregation.AMethod;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:14
 * @description:测试
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class AMethodImpl implements AMethod {
    @Override
    public void method1() {
        System.out.println("执行方法1");
    }
}

package com.xiao.principles.demo1.d_segregation.impl;

import com.xiao.principles.demo1.d_segregation.AMethod;
import com.xiao.principles.demo1.d_segregation.BMethod;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:14
 * @description:测试
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class BMethodImpl implements BMethod {
    @Override
    public void method2() {
        System.out.println("执行方法2");
    }
}

package com.xiao.principles.demo1.d_segregation.impl;

import com.xiao.principles.demo1.d_segregation.AMethod;
import com.xiao.principles.demo1.d_segregation.BMethod;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:14
 * @description:测试
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class CMethodImpl implements AMethod , BMethod {
    @Override
    public void method1() {
        System.out.println("执行方法1");
    }

    @Override
    public void method2() {
        System.out.println("执行方法2");
    }
}

测试

package com.xiao.principles.demo1.d_segregation.impl;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:17
 * @description:
 * @modified By:Mr~肖
 * @version:
 */
public class MethodTest {
    public static void main(String[] args) {
        AMethodImpl aMethod = new AMethodImpl();
        aMethod.method1();
        BMethodImpl bMethod = new BMethodImpl();
        bMethod.method2();
        CMethodImpl cMethod = new CMethodImpl();
        cMethod.method1();
        cMethod.method2();
    }
}

如果还需要新的品牌则新增一个实现类即可实现,满足了开闭原则也满足了接口隔离原则

五、迪米特法则

        迪米特原则又称最少知识原则。只和你的“朋友”交谈,不和“陌生人”说话

        含义:如果俩个软件实体无需直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。目的是降低类之间的耦合度,提高模块的相对独立性。

迪米特法则中朋友指:当前对象本身、当前对象成员对象、当前对象所建的对象、当前对象的方法参数,这些对象存在关联、聚合或者组合关系,可以直接访问这些对象的方法。

明星类,粉丝类,公司类三个没有连接的类

package com.xiao.principles.demo1.e_lawdemeter;

import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:33
 * @description:明星类
 * @modified By:Mr~肖粉丝
 * @version: 1.0
 */
@Data
public class Star {
    private String name;
}

package com.xiao.principles.demo1.e_lawdemeter;

import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:34
 * @description:粉丝类
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
public class Fans {
    private String fansName;
}

package com.xiao.principles.demo1.e_lawdemeter;

import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:37
 * @description:公司类
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
public class Company {

    private String name;
}

聚合这三个类的类

package com.xiao.principles.demo1.e_lawdemeter;

import lombok.Data;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:35
 * @description:经纪人
 * @modified By:Mr~肖
 * @version: 1.0
 */
@Data
public class Agent {
    private Star star;

    private Fans fans;

    private Company company;

    public void meeting(){
        System.out.println(fans.getFansName()+"见面"+star.getName());
    }
    public void business(){
        System.out.println(company.getName()+"与"+star.getName()+"商讨业务");
    }

}

测试类

package com.xiao.principles.demo1.e_lawdemeter;

/**
 * @author :Mr~肖
 * @date :Created in 2023/9/17 23:40
 * @description:测试类
 * @modified By:Mr~肖
 * @version: 1.0
 */
public class StarTest {

    public static void main(String[] args) {
        Agent agent = new Agent();
        Star star = new Star();
        star.setName("芭芭拉");
        Fans fans = new Fans();
        fans.setFansName("可莉");
        Company company = new Company();
        company.setName("西风大教堂");

        agent.setStar(star);
        agent.setCompany(company);
        agent.setFans(fans);
        agent.meeting();
        agent.business();
    }
}

六、合成复用原则

        合成复用原则:尽量使用组合或者聚合等关联关系来实现,其次在考虑用继承关系实现

通常类的复用分为继承复用和合成复用两种。

继承复用虽然又简单和易实现的优点,但它也存在不少缺点:

        1.继承破坏了类的封装性。即父类对于子类来说是透明的

        2.子类与父类的耦合度极高。父类的任何变化都会导致子类变化,不利于维护与扩展

        3.限制了复用的灵活性。从父类继承的实现是静态的在编译时就定义,不能发生新的变化

组合/聚合复用,可以将已有对象纳入新对象内部,使其成为新对象的一部分,新对象可以调用已有对象的功能。优点有:

        1.它维持了类的封装性。因为成员对象的内部细节不能不发现

        2.对象之间的耦合的低,可以在类的成员位置声明抽象。

        3.复用灵活性高。这种复用可以在运行是动态进行,新对象可以动态引用与成员对象类型相同的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr~肖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值