一篇文章带你彻底了解Java常用的设计模式

news2024/11/17 18:28:58

文章目录

    • 前言
    • 1. 工厂模式
      • 使用示例代码
      • 优势
    • 2. 单例模式
      • 说明
      • 使用示例代码
      • 优势
    • 3. 原型模式
      • 使用示例代码
      • 优势
    • 4. 适配器模式
      • 使用示例代码
      • 优势
    • 5. 观察者模式
      • 使用示例代码
      • 优势
    • 6. 策略模式
      • 使用示例代码
      • 优势
    • 7. 装饰者模式
      • 使用示例代码
      • 优势
    • 8. 模板方法模式
      • 使用示例代码
      • 优势
    • 总结

前言

        说到Java开发,设计模式肯定是绕不开的,Java常用的设计模式主要包括很多,一种说是有10种设计模式,还有一种说是23种设计模式。我这边重点解释了开发中常用到的8种设计模式,分别是:工厂模式、单例模式、原型模式、适配器模式、观察者模式、策略模式、装饰者模式、模板方法模式。其中每种模式都有其特定的应用场景和优缺点,在实际开发中,根据具体需求选择适合的设计模式可以提高代码的可维护性、可扩展性和重用性。需要根据具体情况来合理选择和组合使用设计模式,最终的目的就是让我们的代码优雅且可读性强,整体逻辑高内聚、低耦合。

🚀工厂模式(Factory):通过工厂类来创建对象,隐藏对象的创建细节,提供对象的接口给客户端使用
🚀单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点
🚀原型模式(Prototype):通过复制现有对象来创建新对象,避免了使用new关键字创建对象
🚀适配器模式(Adapter):将一个类的接口转换成客户端所期望的另一个接口
🚀观察者模式(Observer):定义了一种一对多的依赖关系,当一个对象状态发生改变时,其相关依赖对象都会得到通知和更新
🚀策略模式(Strategy):定义了一系列可互换的算法,并使得算法的变化独立于使用算法的客户端
🚀装饰者模式(Decorator):在不改变原始对象的基础上,动态地给对象添加额外的功能
🚀模板方法模式(Template Method):定义一个算法骨架,将一些步骤延迟到子类中实现

 

1. 工厂模式

Java使用工厂模式是为了实现对象的创建和使用的分离,提供一种灵活的方式来创建对象实例。工厂模式提供一种可扩展、灵活、封装对象创建逻辑的方式,使代码更易于维护、测试和修改。它帮助实现了软件设计中的开闭原则,即对扩展开放、对修改关闭。

使用示例代码

定义产品接口,并定义产品操作的抽象方法

/**
 * 产品接口
 */
public interface Product {
    void operation();
}

产品A实现产品接口,并重写operation()方法

/**
 * 产品A类
 */
public class ProductA implements Product {
    @Override
    public void operation() {
        System.out.println("产品A的操作!");
    }
}

产品B实现产品接口,并重写operation()方法

/**
 * 产品B类
 */
public class ProductB implements Product {
    @Override
    public void operation() {
        System.out.println("产品B的操作!");
    }
}

建立工厂类,用于产品的生产

/**
 * 工厂类
 */
public class Factory {
    public Product createProduct(String type){
        if ("A".equals(type)) {
            return new ProductA();
        } else if ("B".equals(type)) {
            return new ProductB();
        } else {
            throw new IllegalArgumentException("无法创建指定类型的产品");
        }
    }
}

使用工厂对象来创建产品A和产品B,通过传递不同的参数"A"和"B"来指定要创建的产品类型。然后调用产品的operation()方法来执行具体产品的操作,通过工厂类来创建产品对象,客户端代码就不需要直接依赖于具体产品类,而只需要依赖于产品接口

public class Test {

    public static void main(String[] args) {
        Factory factory = new Factory();
        Product productA = factory.createProduct("A");
        productA.operation();
        Product productB = factory.createProduct("B");
        productB.operation();
        Product productC = factory.createProduct("C");
        productC.operation();
    }
}

运行结果
在这里插入图片描述

优势

  1. 隐藏具体实现类
  2. 简化对象的创建过程
  3. 降低系统的耦合度
  4. 支持扩展和灵活性

 

2. 单例模式

Java使用单例模式是为了确保一个类只能创建一个对象实例,并提供全局访问点。可以限制一个类只能创建一个对象实例,提供了一个全局访问点,使得其他对象可以方便地获取到该单例对象并使用它。这样可以简化代码,减少对全局变量的使用,同时也方便对单例对象进行集中管理和控制。由于单例模式只创建一个对象实例,节省了系统资源和内存空间。在需要频繁创建和销毁对象的场景中,使用单例模式可以提高性能和效率。

说明

  1. 将构造方法设置为私有,以防止外部通过new关键字创建新的实例
  2. 声明一个私有静态变量instance,用于存储单例的唯一实例
  3. 提供一个公共的静态方法getInstance(),用于获取单例实例

使用示例代码

懒汉式单例模式,存在线程安全性问题,当多个线程同时调用getInstance()方法时,可能会创建多个实例

/**
 * 懒汉式单例模式
 */
public class Singleton1 {

    //私有静态变量,用于存储单例实例
    private static Singleton1 instance;

    //构造私有方法,默认无参构造器失效,外部无法实例化
    private Singleton1(){

    }

    //获取单例实例的方法(新构造方法),相当于原来的new Singleton1()
    public static Singleton1 getInstance(){
        if (instance == null) {
            instance =  new Singleton1();
        }
        return instance;
    }

    //其他普通方法
    public void doSomething(){
        System.out.println("懒汉式单例...普通方法...");
    }
}

饿汉式单例模式,因为实例在类加载时就被创建,不存在多线程并发访问的问题,是线程安全的。实例在类加载时就创建,可能会占用一定的内存空间

/**
 * 饿汉式单例模式
 * 饿汉式的特点是线程安全,因为实例在类加载时就被创建,不存在多线程并发访问的问题
 * 实例在类加载时就创建,可能会占用一定的内存空间
 */
public class Singleton2 {

    //私有静态变量,类加载时创建对象
    private static Singleton2 instance = new Singleton2();

    //构造私有方法,默认无参构造器失效,外部无法实例化
    private Singleton2(){

    }

    //获取单例实例的方法(新构造方法)
    public static Singleton2 getInstance(){
        return instance;
    }

    //其他普通方法
    public void doSomething(){
        System.out.println("饿汉式单例...普通方法...");
    }
}

懒汉式线程安全的单例模式,通过双重检查锁来保证线程安全性

/**
 * 懒汉式单例模式(线程安全)
 */
public class Singleton3 {

    //私有静态变量,用于存储单例实例
    private static Singleton3 instance;

    //构造私有方法,默认无参构造器失效,外部无法实例化
    private Singleton3(){

    }

    //获取单例实例的方法(新构造方法),相当于原来的new Singleton1()
    public static Singleton3 getInstance(){
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance =  new Singleton3();
                }
            }
        }
        return instance;
    }

    //其他普通方法
    public void doSomething(){
        System.out.println("懒汉式单例...普通(线程安全)方法...");
    }
}

实例化调用

public class Test {

    public static void main(String[] args) {
        //实例化Singleton1对象
        Singleton1 instance1 = Singleton1.getInstance();
        //实例化Singleton2对象
        Singleton2 instance2 = Singleton2.getInstance();
        //实例化Singleton3对象
        Singleton3 instance3 = Singleton3.getInstance();

        instance1.doSomething();
        instance2.doSomething();
        instance3.doSomething();
    }
}

运行结果
在这里插入图片描述

优势

  1. 可以确保所有对象都访问唯一实例
  2. 类可以灵活更改实例化过程
  3. 减少内存开支和系统的性能开销

 

3. 原型模式

Java使用原型模式是为了通过复制现有对象来创建新的对象实例,以减少对象的创建开销和提高性能。它提供了一种便捷、高效、灵活的方式来创建对象的变体,并隐藏了对象创建细节,使代码更加简洁和易于维护。可以通过调用原型对象的clone()方法来创建新的对象,而无需显式地使用new关键字进行实例化。

使用示例代码

定义一个原型接口,并定义clone()的抽象方法

/**
 * 定义一个原型接口
 */
public interface Prototype {
    Prototype clone();
}

原型类A实现原型接口,并重写clone()方法

/**
 * 原型实现类
 */
public class PrototypeA implements Prototype {

    private String name;
    private Integer age;

    public PrototypeA(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "PrototypeA{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public Prototype clone() {
        return new PrototypeA(name, age);
    }
}

原型模式可以方便地创建和复制对象,避免了重复的对象实例化过程,并且可以动态地添加或修改对象的属性

public class Test {

    public static void main(String[] args) {
        PrototypeA prototype1 = new PrototypeA("张三", 18);
        System.out.println("原型对象:"+prototype1);

        //克隆原型对象
        PrototypeA prototype2 = (PrototypeA)prototype1.clone();
        System.out.println("克隆对象:"+prototype2);

        prototype2.setName("李四");
        System.out.println("修改后克隆对象:"+prototype2);
    }
}

运行结果
在这里插入图片描述

优势

  1. 减少对象的创建开销
  2. 提高性能
  3. 对象创建的隐藏

 

4. 适配器模式

Java使用适配器模式可以将一个类的接口转换成客户端所期望的另一个接口,解决由于接口不兼容而导致不能正常工作的问题。提供了一种灵活、可扩展的方式来复用现有功能、解耦合并提高系统的兼容性,可以帮助我们在不改变已有代码结构的前提下,实现不同类之间的协同工作。

使用示例代码

定义一个目标接口,在接口中定义一个抽象方法request()

/**
 * 目标接口
 */
public interface Target {
    void request();
}

定义一个需要适配的类Adaptee,定义一个测试的适配方法specificRequest()

/**
 * 需要适配的类
 */
public class Adaptee {
    public void specificRequest(){
        System.out.println("需要适配的方法!");
    }
}

定义适配器类Adapter实现目标接口Target,并重写request()方法。在适配器类中定义需要适配类Adaptee的成员变量,并在构造方法中赋值

/**
 * 适配器类
 */
public class Adapter implements Target {

    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

适配器调用目标接口的方法,实际上会调用需要适配类Adaptee的特定方法

public class Test {

    public static void main(String[] args) {
        //创建需要适配的对象
        Adaptee adaptee = new Adaptee();
        //创建适配器类对象,传入需要适配的对象
        Target adapter = new Adapter(adaptee);

        //调用目标接口的方法,实际上会调用需要适配类中的特定方法
        adapter.request();
    }
}

运行结果
在这里插入图片描述

优势

  1. 可以解决两个接口不兼容的问题
  2. 功能复用,让已经存在的类在新的环境中复用
  3. 提高系统的扩展性和灵活性

 

5. 观察者模式

Java使用观察者模式是为了实现对象之间的松耦合和事件驱动的通信机制,以便在一个对象的状态变化时通知其他相关对象。提供了一种灵活、可扩展和解耦合的方式来实现发布者和订阅者之间的通信,使得对象能够根据需要进行状态观察和响应,从而实现更灵活、可维护和可扩展的代码设计。

使用示例代码

定义一个观察者接口Observer,在接口中定义一个抽象方法update()

/**
 * 定义一个观察者接口
 */
public interface Observer {
    void update();
}

定义一个主题接口,并定义注册、注销、通知变化

/**
 * 定义一个主题接口
 */
public interface Subject {
    //注册观察者
    void registerObserver(Observer observer);
    //注销观察者
    void unregisterObserver(Observer observer);
    //通知观察者(状态变化)
    void notifyObservers();
}

主题具体实现类,重写三个抽象方法,并且在成员变量中引入Observer和state值

/**
 * 主题具体实现类
 */
public class SubjectA implements Subject {

    private List<Observer> observers = new ArrayList<>();
    private int state;

    public int getState() {
        return state;
    }

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

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void unregisterObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

观察者具体实现类,重写update()方法,并在构造方法中初始化主题类

/**
 * 观察者接口具体实现类
 */
public class ObserverA implements Observer {

    private SubjectA subject;

    public ObserverA(SubjectA subject) {
        this.subject = subject;
        this.subject.registerObserver(this);
    }

    public void cancelObserver() {
        this.subject.unregisterObserver(this);
    }

    @Override
    public void update() {
        int state = this.subject.getState();
        //执行相应操作
        System.out.println(this+" 此时状态为:"+state);
    }
}

当主题的状态发生变化时,会通知所有的观察者进行相应的更新操作,通过观察者模式可以有效实现对象之间的解耦和消息传递

public class Test {

    public static void main(String[] args) {
        SubjectA subject = new SubjectA();
        ObserverA observer1 = new ObserverA(subject);
        ObserverA observer2 = new ObserverA(subject);
        ObserverA observer3 = new ObserverA(subject);

        System.out.println("1号观察者:"+observer1);
        System.out.println("2号观察者:"+observer2);
        System.out.println("3号观察者:"+observer3);
        subject.setState(12);
        System.out.println("主题状态发生变化!!!");
        subject.setState(24);
        observer2.cancelObserver();
        System.out.println("2号观察者退出!!!");
        System.out.println("主题状态发生变化!!!");
        subject.setState(36);
    }
}

运行结果
在这里插入图片描述

优势

  1. 提高代码的可维护性和可扩展性
  2. 提升扩展性和降低耦合度
  3. 事件驱动的机制能够及时地响应状态变化,实现对象之间的即时通信和协作

&nbap;

6. 策略模式

Java的策略模式可以在运行时根据不同的情况选择不同的算法或策略,以实现灵活、可扩展和可替换的行为。策略模式将算法封装在独立的策略类中,避免了大量的条件语句,提高了代码的可读性和可维护性。它能够灵活地应对需求的变化,并支持动态切换算法,从而使系统更加灵活、可扩展和易于修改。

使用示例代码

定义策略接口,在接口中定义一个抽象方法execute()

/**
 * 抽象策略接口
 */
public interface Strategy {
    void execute();
}

具体策略类A,重写抽象方法

/**
 * 具体策略类A
 */
public class StrategyA implements Strategy{
    @Override
    public void execute() {
        System.out.println("执行策略A...");
    }
}

具体策略类B,重写抽象方法

/**
 * 具体策略类B
 */
public class StrategyB implements Strategy{
    @Override
    public void execute() {
        System.out.println("执行策略B...");
    }
}

上下文类

/**
 * 上下文类
 */
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy() {
        strategy.execute();
    }
}

创建策略对象,创建上下文对象,并将具体策略对象传入,执行、切换不同的策略

public class Test {

    public static void main(String[] args) {
        //创建策略对象
        Strategy strategyA = new StrategyA();
        Strategy strategyB = new StrategyB();

        //创建上下文对象,并将具体策略对象传入
        Context context = new Context(strategyA);
        System.out.println("初始化策略A!!!");
        //执行策略A
        context.executeStrategy();

        //切换策略为B
        context = new Context(strategyB);
        System.out.println("切换为策略B!!!");
        //执行策略B
        context.executeStrategy();
    }
}

运行结果
在这里插入图片描述

优势

  1. 可以避免大量的条件语句,将各种不同的算法或行为封装在独立的策略类中
  2. 提升可扩展性与灵活性
  3. 算法或行为可以被独立地演化和替换
  4. 单一职责原则,代码结构更加清晰和可维护

 

7. 装饰者模式

Java使用装饰者模式可以在不修改原始对象的情况下,动态地扩展其功能或添加新的功能。具有很好的灵活性和可扩展性,可以有效避免类层次结构的膨胀和代码的修改,符合设计模式中的开放封闭原则和单一职责原则。

使用示例代码

定义组件接口,在接口中定义一个抽象方法operation()

/**
 * 定义抽象组件接口
 */
public interface Component {
    void operation();
}

具体组件类,实现组件接口,并重写operation()方法

/**
 * 具体组件类
 */
public class MyComponent implements Component{
    @Override
    public void operation() {
        System.out.println("执行具体组件操作!");
    }
}

抽象装饰者方法,实现组件接口

/**
 * 抽象装饰者方法
 */
public abstract class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation(){
        component.operation();
    }
}

具体装饰者类A

/**
 * 具体装饰者类A
 */
public class MyDecoratorA extends Decorator {
    public MyDecoratorA(Component component) {
        super(component);
    }

    public void operation(){
        super.operation();
        addBehavior();
    }

    public void addBehavior(){
        System.out.println("装饰者A新增的行为...");
    }
}

具体装饰者类B

/**
 * 具体装饰者类B
 */
public class MyDecoratorB extends Decorator {
    public MyDecoratorB(Component component) {
        super(component);
    }

    public void operation(){
        super.operation();
        addBehavior();
    }

    public void addBehavior(){
        System.out.println("装饰者B新增的行为...");
    }
}

先创建装饰者A对象,参数传入组件对象。然后创建装饰者B对象,参数传入装饰者A对象,装饰者B执行的时候还会执行到执行者A的行为

public class Test {

    public static void main(String[] args) {
        //创建具体组件对象
        Component component = new MyComponent();
        //创建装饰者A对象,参数传入组件对象
        Decorator decoratorA = new MyDecoratorA(component);
        //创建装饰者B对象,参数传入装饰者A对象
        Decorator decoratorB = new MyDecoratorB(decoratorA);
        //装饰者B调用装饰后的操作
        decoratorB.operation();
    }
}

运行结果
在这里插入图片描述

优势

  1. 对象功能的灵活扩展,而无需修改原始对象的结构
  2. 单一职责原则,将功能划分为独立的装饰器,每个装饰器只关注特定的功能
  3. 系统更加容易维护和扩展

 

8. 模板方法模式

Java的模板方法模式会定义一个算法的骨架结构,并允许子类在不改变该算法结构的情况下,重新实现某些步骤以提供特定的行为。通过将可变和具体实现的步骤留给子类来实现,模板方法模式让子类可以根据自己的需要来重写父类中的某些步骤,减少重复的代码,并提高代码的可维护性和可读性。

使用示例代码

定义抽象基类,抽象类定义一个模板方法,用于执行各类方法

/**
 * 定义抽象基类
 */
public abstract class MyAbstract {
    public void templateMethod(){
        concreteMethod1();
        abstractMethod();
        concreteMethod2();
        hookMethod();
    }

    //具体方法1
    public void concreteMethod1() {
        System.out.println("执行具体方法1");
    }

    //具体方法2
    public void concreteMethod2() {
        System.out.println("执行具体方法2");
    }

    //抽象方法
    public abstract void abstractMethod();

    //钩子方法
    public void hookMethod() {
        System.out.println("我应该不会被执行到,因为在子类中重写了!");
    }
}

定义具体子类,重写抽象方法和钩子方法

/**
 * 具体子类
 */
public class MyConcrete extends MyAbstract{
    @Override
    public void abstractMethod() {
        System.out.println("抽象方法执行具体方法的子类实现");
    }

    @Override
    public void hookMethod() {
        System.out.println("执行钩子方法");
    }
}

MyAbstract根据实际需求实现了抽象方法,并可以选择性地重写钩子方法,最终会按照顺序调用具体方法、抽象方法和钩子方法

public class Test {

    public static void main(String[] args) {
        MyAbstract myAbstract = new MyConcrete();
        myAbstract.templateMethod();
    }
}

运行结果
在这里插入图片描述

优势

  1. 减少代码冗余,复用率高
  2. 提供一致的算法结构,保持算法的一致性和稳定性
  3. 可扩展性和灵活性强
  4. 减少重复的代码,并提高代码的可维护性和可读性

 

总结

本文重点介绍了八种设计模式的原理及使用方法,当然实际业务开发中不止这8种模式,大家可以按照自己业务架构的实际需求运用合适的设计模式。设计模式的必要性在于它们能够提供可复用、可维护、可扩展和高质量的代码解决方案。设计模式指导开发人员采用良好的设计原则和实践,使代码更具可读性和可维护性。通过合理地应用设计模式,可以降低软件开发风险,提高开发效率,创建高质量的软件系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/933137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python-数据可视化-下载数据-CSV文件格式

数据以两种常见格式存储&#xff1a;CSV和JSON CSV文件格式 comma-separated values import csv filename sitka_weather_07-2018_simple.csv with open(filename) as f:reader csv.reader(f)header_row next(reader)print(header_row) # [USW00025333, SITKA AIRPORT, A…

YOLO目标检测——皮肤检测数据集下载分享

数据集点击下载&#xff1a;YOLO皮肤检测数据集Face-Dataset.rar

springboot源码方法

利用LinkedHashSet移除List重复的数据protected final <T> List<T> removeDuplicates(List<T> list) {return new ArrayList<>(new LinkedHashSet<>(list));} SpringFactoriesLoader#loadFactoryNames 加载配置文件

常见的移动端布局

流式布局&#xff08;百分比布局&#xff09; 使用百分比、相对单位&#xff08;如 em、rem&#xff09;等来设置元素的宽度&#xff0c;使页面元素根据视口大小的变化进行调整。这种方法可以实现基本的自适应效果&#xff0c;但可能在不同设备上显示不一致。 <!DOCTYPE ht…

ctfshow-web14

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 首先看到这个&#xff0c;swith&#xff0c;那么直接输入4&#xff0c;则会打印$url的值 然后访问一下 查看一下&#xff0c;发现完整的请求是http://c7ff9ed6-dccd-4d01-907a-f1c61c016c15.challenge.ctf.sho…

python网络爬虫指南二:多线程网络爬虫、动态内容爬取(待续)

文章目录 一、多线程网络爬虫1.1 线程的基础内容、GIL1.2 创建线程的两种方式1.3 threading.Thread类1.4 线程常用方法和锁机制1.5 生产者-消费者模式1.5.1 生产者-消费者模式简介1.5.2 Condition 类协调线程 1.6 线程中的安全队列1.6 多线程爬取王者荣耀壁纸1.6.1 网页分析1.6…

2023-8-26 模拟散列表

题目链接&#xff1a;模拟散列表 拉链法 #include <iostream> #include <cstring>using namespace std;const int N 100010;int h[N], e[N], ne[N], idx;void insert(int x) {int k (x % N N) % N;e[idx] x;ne[idx] h[k];h[k] idx;idx ; }bool query(int …

智慧县城,乍暖还寒风起时

提起中国的区域数字化&#xff0c;我们大概率会关注两个维度。一个是北上广深为代表的超大城市&#xff0c;这里的智慧城市落地是风向标、排头兵&#xff1b;另一个是乡村的数字化、智能化&#xff0c;作为区域智能升级的最小单位&#xff0c;乡村的典型性更强&#xff0c;也符…

nlp大模型课程笔记

自然语言处理基础和应用 &#x1f446;说明之前的大模型其实有很多都是基于迁移学习的方法。 attention机制的总结&#xff0c;解决了信息瓶颈的问题。 处理词组时BPE的过程 &#x1f446;pos表示的是token所在的位置 &#x1f446;技巧是layer normalization。

数据结构(Java实现)-二叉树(上)

树型结构 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结点&#xff0c;称为根结点&…

从爬楼梯到斐波那契数列:解密数学之美

题目描述 我们来看看力扣的一道经典问题70. 爬楼梯 递归 假设n级台阶有climbStairs(n)种方法爬到楼梯顶。如果有n级台阶&#xff0c;如果第一次往上爬1级台阶&#xff0c;就会剩下n-1级台阶&#xff0c;这n-1级台阶就有climbStairs(n-1)种方法爬到楼梯顶&#xff1b;如果第一…

C++通过JNI调用JAVA方法返回ArrayList对象

运行效果: JAVA实现: 获取系统已安装应用列表并返回List<String>对象 //使用系统API获取安装包列表public List<String> getAppList(MainActivity act) {List<String> packages = new ArrayList<String>();try {//取包信息列表List<PackageInf…

Python学习 -- 类的多态

在面向对象编程中&#xff0c;多态性是一项强大的特性&#xff0c;它允许不同的对象对同一方法产生不同的行为。Python作为一门面向对象的编程语言&#xff0c;也支持多态性。本篇博客将深入探讨Python中的类多态性&#xff0c;通过详细的代码案例来展示其灵活性和可扩展性。 …

Leetcode 2235.两整数相加

一、两整数相加 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num1 12, num2 5 输出&#xff1a;17 解释&#xff1a;num1 是 12&#xff0c;num2 是 5 &#xff0c;它们的和是 12 5 17 &#xff0c;因此返回 17 。示例…

2023.8 -java - 继承

继承就是子类继承父类的特征和行为&#xff0c;使得子类对象&#xff08;实例&#xff09;具有父类的实例域和方法&#xff0c;或子类从父类继承方法&#xff0c;使得子类具有父类相同的行为。 继承的特性 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法…

API Gateway介绍

使用微服务架构开发应用后&#xff0c;每个微服务都将拥有自己的API&#xff0c;设计应用外部API的任务因客户端的多样性而变得更具有挑战性。不同客户端通常需要不同的数据。通常基于PC浏览器的用户界面显示的信息要远多于移动设备的用户界面。此外&#xff0c;不同的客户端通…

基于Java+SpringBoot+Vue前后端分离公交线路查询系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Android学习之路(9) Bundle

Bundle的概念理解 Bundle经常出现在以下场合&#xff1a; Activity状态数据的保存与恢复涉及到的两个回调&#xff1a;void onSaveInstanceState (Bundle outState)、void onCreate (Bundle savedInstanceState)Fragment的setArguments方法&#xff1a;void setArguments (Bu…

【网络安全】理解报文加密、数字签名能解决的实际问题

文章目录 前言1. 防止报文泄露 —— 加密体系的出现1.1 理解非对称加密体系的实施难点1.2 加密体系的实际应用 2. 防止报文被篡改 —— 数字签名的出现2.1 数字签名的原理2.2 数字签名的实施难点2.2 数字签名的实际应用 —— 引入摘要算法 3. 实体鉴别 —— CA证书 后记 前言 …

Java8新特性之——Stream API

文章目录 一、简介二、操作分类创建流通过集合通过数组通过Stream的of()方法 中间操作无状态有状态 结束操作非短路操作短路操作 一、简介 JDK 8 引入了 Stream API&#xff0c;它是用于处理集合数据的功能强大的库。Stream API 提供了一种更为简洁、灵活和函数式的方式来进行…