GoF(Gang of Four)23种经典的设计模式

设计模式概念:

设计模式(Design Pattern)是一套被反复使用,多人知晓,经过分类编目的优秀代码设计经验的总结。使用设计模式是为了重用代码,使代码更容易理解并保证代码的可靠性。使用设计模式对于自己,对他人,对系统都是有利的。设计模式使代码编制更加工程化,是软件工程的基石。

java设计模式贯彻的原理:

面向接口编程,而不是面向实现。

目标原则:

降低耦合,增强灵活性。

设计模式(Design Pattern)

 创建型结构型行为型J2EE 模式
Factor Method(工厂方法)Abapter_Class(适配器类)

Interpreterm(解释器)

Template Method(模板方法)

对象

Abstract Factory(抽象工厂)

Builder(生成器)

Prototype(原型)

Singleton(单例)

Abapter_Object(适配器对象)

Bridge(桥接)

Composite(组合)

Decorator(装饰)

Facade(外观)

Flyweight(享元)

Proxy(代理)

Chain of Responsibility(责任链)

Command(命令)

Iterator(迭代器) 

Mediator(中介者)

Memento(备忘录)

Observer(观察者)

State(状态)

 

Strategy(策略)

Visitor(访问者)

MVC 模式(MVC Pattern)

业务代表模式(Business Delegate Pattern)

 

组合实体模式(Composite Entity Pattern)

 

数据访问对象模式(Data Access Object Pattern)

前端控制器模式(Front Controller Pattern)

 

拦截过滤器模式(Intercepting Filter Pattern)

 

服务定位器模式(Service Locator Pattern)

 

传输对象模式(Transfer Object Pattern)

设计模式要素:

  1. 模式名称
  2. 问题
  3. 解决方案
  4. 效果
  5. 举例
  6. 末态环境
  7. 推理
  8. 其他有关模式
  9. 已知的应用

 

工厂模式

让其子类实现工厂接口,返回的也是一个抽象的产品。

  1.  创建一个接口

  2. 创建实现接口的抽象类

  3. 创建一个工厂,生成基于给定信息的实体类的对象 

  4. 使用工厂,通过传递信息来获取工厂实体的对象

抽象工厂

主要解决接口选择的问题,在一个产品族里面,定义多个产品。

  1. 为形状创建一个接口
  2. 创建实现接口的实体类
  3. 为颜色创建一个接口
  4. 创建实现接口的实体类
  5. 为现状,颜色对象创建抽象类来获取工厂
  6. 扩展工厂类,基于给定信息生成实体类的对象
  7. 创造工厂生成器/创造器类,通过现状或者颜色来回去工厂
  8. 调用生成器通过传递信息来获取实体类对象

单例模式

一般用饿汉式 ,保证一个类仅有一个实例,并提供一个访问它的全局访问点。当想要控制实例数目,节省系统开销时使用,判断系统是否已有单例,构造函数是私有的。

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}


public class SingletonPatternDemo {
   public static void main(String[] args) {
      SingleObject object = SingleObject.getInstance();
      object.showMessage();
   }
}

建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

  1. 创建一个表示食物条目item和食物包装packing的接口(食物,包装)
  2. 实现item和packing接口的实体类burger,colddringk,wrapper,bottle(给食物包装)
  3. 扩展burger和colddrink的实体类(实例化食物,名称,价钱)
  4. 创建一个meal类,带有上面定义的item对象(套餐框架,存放多个食物)
  5. 创建一个mealbuilder类(具体套餐A,套餐B)
  6. builderpatterdemo使用mealbuilder来演示建造者模式(点菜)

原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

浅克隆  Shollow Clone 

public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();   //可能涉及的强制类型转换
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;   //可以return 0;
   }


main(){
    Obj b = (Obj)a.clone();
}

深克隆   代码:https://blog.csdn.net/qq_41835813/article/details/93400116

当开发人员自定义赋值构造函数时,会涉及

当类中包含有一些对象时,对对象中的非基本类型的属性调用clone() 方法 完成深复制

例如类中含有

private Date birth = new Deat();
public Date(){
    return birth;
}

实现

public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();   //可能涉及的强制类型转换
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
//实现深复制
      clone.birth = (Date)this.getBirth().clone();
      return clone;   //可以return 0;
   }


main(){
    Obj b = (Obj)a.clone();
}

浅克隆与深克隆的区别

  1. 浅复制仅仅复制所考虑的对象,不复制所引用的对象
  2. 深复制那些引用其他对象的变量将指向被复制的新对象,而不是用来的那些被引用的对象,深复制把复制的对象所引用的对象都复制了一遍

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。  好比读卡器

 

桥接模式

把抽象化和实现化解耦,使二者可以独立变化

抽象类依赖实现类。

 

过滤器模式

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

 

组合模式

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

import java.util.ArrayList;
import java.util.List;
 
public class Employee {
   
   private List<Employee> subordinates;
 
   //构造函数
   public Employee() {
      subordinates = new ArrayList<Employee>();
   }
 
   public void add(Employee e) {
      subordinates.add(e);
   }
 
   public void remove(Employee e) {
      subordinates.remove(e);
   }
 
   public List<Employee> getSubordinates(){
     return subordinates;
   }
 
    
}

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

在用来的基础上创建一个抽象装饰类,实现原来的接口,然后创建扩展了抽象类的实体装饰类,增加想要实现的功能。

 

外观模式

接口--实体类--外观类

降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;
 
   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }
 
   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

享元模式

减少创建对象的数量,减少内存占用和提高性能,用现有的同类对象,如果未找到匹配的对象,则创建新对象。

缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap<>();
 
   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);
 
      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

代理模式

一个类里代表另一个类的功能,增加中间层,实现与被代理类组合。

public class ProxyImage implements Image{
 
   private RealImage realImage;
   private String fileName;
 
   public ProxyImage(String fileName){
      this.fileName = fileName;
   }
 
   
   public void display() {
      if(realImage == null){  //实现代理
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

 

责任链模式

责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;
 
   protected int level;
 
   //责任链中的下一个元素
   protected AbstractLogger nextLogger;
 
   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }
 
   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }
 
   abstract protected void write(String message);
   
}

 

 

命令模式

调用者→接受者→命令

将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

 

public class Broker {
   private List<Order> orderList = new ArrayList<Order>(); 
 
   public void takeOrder(Order order){
      orderList.add(order);      
   }
 
   public void placeOrders(){
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}

 

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

在抽象类里有一个 ArrayList 存放观察者们。还有一个更新方法

Subject   观察者类

package 观察者模式;

import java.util.ArrayList;
import java.util.Iterator;

public class Subject {
	ArrayList<Obsever> list = new ArrayList<Obsever>();
	private int state;
	public void setSubject(int i){
		state = i;
	}
	public int getState(){
		return state;
	}
	public void addSubject(Obsever obsever){
		list.add(obsever);
	}
	public void updateSubject(){
		Iterator<Obsever> iterator= list.iterator();
		while(iterator.hasNext()){
			iterator.next().update();
		}
	}
}

Obsever 抽象对象类

package 观察者模式;

public abstract class Obsever {
	protected Subject subject;
	public abstract void update();
	
}

 BinaryObject  转二进制类

package 观察者模式;

public class BinaryObject extends Obsever{

	public BinaryObject(Subject subject){
		this.subject = subject;
		this.subject.addSubject(this);
	}
	
	public void update() {
		// TODO 自动生成的方法存根
		System.out.println("二进制"+Integer.toBinaryString(subject.getState()));
	}

}

OctalObject 转八进制类

package 观察者模式;

public class OctalObject extends Obsever{

	public OctalObject(Subject subject){
		this.subject = subject;
		this.subject.addSubject(this);
	}
	@Override
	public void update() {
		// TODO 自动生成的方法存根
		System.out.println("八进制"+Integer.toOctalString(subject.getState()));
	}
	
}

HexaObject 转十六进制类

package 观察者模式;

public class HexaObject extends Obsever{
	public HexaObject(Subject subject) {
		// TODO 自动生成的构造函数存根
		this.subject = subject;
		this.subject.addSubject(this);
	}
	@Override
	public void update() {
		// TODO 自动生成的方法存根
		System.out.println("十六进制"+Integer.toHexString(subject.getState()));
	}
		
}

Main 

package 观察者模式;

public class Main {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Subject subject = new Subject() ;
		new BinaryObject(subject);
		new OctalObject(subject);
		new HexaObject(subject);
		System.out.println("第一次");
		subject.setSubject(15);
		subject.updateSubject();
		System.out.println("第二次");
		subject.setSubject(10);
		subject.updateSubject();
		
	}

}

运行结果 

第一次
二进制1111
八进制17
十六进制f
第二次
二进制1010
八进制12
十六进制a

 

解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子

对于一些固定文法构建一个解释句子的解释器。

构建语法树,定义终结符与非终结符。

 

 迭代器模式

提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。

定义接口:hasNext, next。

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

public interface Container {
   public Iterator getIterator();
}

public class NameRepository implements Container {
   public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};
 
   @Override
   public Iterator getIterator() {
      return new NameIterator();
   }
 
   private class NameIterator implements Iterator {
 
      int index;
 
      @Override
      public boolean hasNext() {
         if(index < names.length){
            return true;
         }
         return false;
      }
 
      @Override
      public Object next() {
         if(this.hasNext()){
            return names[index++];
         }
         return null;
      }     
   }
}
public class IteratorPatternDemo {
   
   public static void main(String[] args) {
      NameRepository namesRepository = new NameRepository();
 
      for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){
         String name = (String)iter.next();
         System.out.println("Name : " + name);
      }  
   }
}

 

 

中介者模式

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式

对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。

多个类相互耦合,形成了网状结构,将上述网状结构分离为星型结构。

聊天室

import java.util.Date;
 
public class ChatRoom {
   public static void showMessage(User user, String message){
      System.out.println(new Date().toString()
         + " [" + user.getName() +"] : " + message);
   }
}
public class User {
   private String name;
 
   public User(String name){
      this.name  = name;
   }
 
   public void sendMessage(String message){
      ChatRoom.showMessage(this,message);
   }
}
public class MediatorPatternDemo {
   public static void main(String[] args) {
      User robert = new User("Robert");
      User john = new User("John");
 
      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}

 

备忘录模式

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。

通过一个备忘录类专门存储对象状态。用list存,然后调用get读取

import java.util.ArrayList;
import java.util.List;
 
public class CareTaker {
   private List<Memento> mementoList = new ArrayList<Memento>();
 
   public void add(Memento state){
      mementoList.add(state);
   }
 
   public Memento get(int index){
      return mementoList.get(index);
   }
}

 

状态模式

允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if...else 等条件选择语句。

实体类的方法参数为状态类的对象

public class StartState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Start State";
   }
}
public class Context {
   private State state;
 
   public Context(){
      state = null;
   }
 
   public void setState(State state){
      this.state = state;     
   }
 
   public State getState(){
      return state;
   }
}
public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();
 
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());
 
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}

空对象模式

equalsIgnoreCase 方法是比较两个String对象是否相等(并且忽略大小写)

在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。

在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。

public class CustomerFactory {
   
   public static final String[] names = {"Rob", "Joe", "Julie"};
 
   public static AbstractCustomer getCustomer(String name){
      for (int i = 0; i < names.length; i++) {
         if (names[i].equalsIgnoreCase(name)){
            return new RealCustomer(name);
         }
      }
      return new NullCustomer();
   }
}
public class NullPatternDemo {
   public static void main(String[] args) {
 
      AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");
      AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");
      AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");
      AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");
 
      System.out.println("Customers");
      System.out.println(customer1.getName());
      System.out.println(customer2.getName());
      System.out.println(customer3.getName());
      System.out.println(customer4.getName());
   }
}

 运行结果

Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database

 

 策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

将这些算法封装成一个一个的类,任意地替换。

public interface Strategy {
   public int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}
public class Context {
   private Strategy strategy;
 
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}
public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationSubstract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationMultiply());    
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}

 

 

模板模式

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

在抽象类实现,其他步骤在子类实现。

spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。

1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。

缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。

package 模板模式;

public abstract class Game {
	public abstract void start();
	
	public abstract void register();
	
	public abstract void end();
	
	public final void play(){
		register();
		start();
		register();
	}
}
package 模板模式;

public class Basketball extends Game{

	@Override
	public void start() {
		// TODO 自动生成的方法存根
		System.out.println("Basketball_start");
	}

	@Override
	public void register() {
		// TODO 自动生成的方法存根
		System.out.println("Basketball_register");
	}

	@Override
	public void end() {
		// TODO 自动生成的方法存根
		System.out.println("Basketball_end");
	}
	
}
package 模板模式;

public class Football extends Game{

	@Override
	public void start() {
		// TODO 自动生成的方法存根
		System.out.println("Football_start");
	}

	@Override
	public void register() {
		// TODO 自动生成的方法存根
		System.out.println("Football_register");
	}

	@Override
	public void end() {
		// TODO 自动生成的方法存根
		System.out.println("Football_end");
	}
	
}
package 模板模式;

public class Start {
	public static void main(String[] args){
		Game game = new Basketball();
		game.play();
		System.out.println();
		game = new Football();
		game.play();
	}
}

 

访问者模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

主要将数据结构与数据操作分离。稳定的数据结构和易变的操作耦合问题。需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

在被访问的类里面加一个对外提供接待访问者的接口。

相当于多态

 

public Computer(){
      parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};      
   } 
public interface ComputerPartVisitor {
   public void visit(Computer computer);
   public void visit(Mouse mouse);
   public void visit(Keyboard keyboard);
   public void visit(Monitor monitor);
}

 

MVC模式

  • Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  • View(视图) - 视图代表模型包含的数据的可视化。
  • Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

业务代表模式

业务代表模式(Business Delegate Pattern)用于对表示层和业务层解耦。它基本上是用来减少通信或对表示层代码中的业务层代码的远程查询功能。在业务层中我们有以下实体。

  • 客户端(Client) - 表示层代码可以是 JSP、servlet 或 UI java 代码。
  • 业务代表(Business Delegate) - 一个为客户端实体提供的入口类,它提供了对业务服务方法的访问。
  • 查询服务(LookUp Service) - 查找服务对象负责获取相关的业务实现,并提供业务对象对业务代表对象的访问。
  • 业务服务(Business Service) - 业务服务接口。实现了该业务服务的实体类,提供了实际的业务实现逻辑。
  1. 实体类接口
  2. 实体服务类
  3. 业务查询服务类
  4. 业务代表类
  5. 客户端
  6. 演示

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值