《面试系列篇》——11种常用的设计模式

news2025/7/19 6:21:36

目录

【一】前言

【二】单例模式

2.1概念

2.2 饿汉模式

2.3 懒汉模式

多线程版本:

【三】简单工厂模式

【四】工厂方法模式

【五】抽象工厂模式

【六】策略模式

【七】装饰模式

7.1 定义

7.2 使用示例

【八】代理模式

8.1 定义

8.2 使用的优势

8.3 如何使用

【九】模板方法模式

【十】建造者模式

10.1 定义

10.2 优势

10.3 如何使用

10.4 Builder模式的应用

【十一】观察者模式

【十二】适配器模式

12.1 定义

12.2 角色职责

【十三】总结


【一】前言

有这么一个很形象的比喻,把写代码比作是建房子,代码比作是砖瓦、一个完整的系统就好比是一栋高楼大厦、程序员无疑就好比是建(ban)筑(zhuan)工,这些很表面的东西我们都可以很形象深刻的理解,其实要设计和开发一个系统远远不只这些东西,深挖表象之下隐藏着的很细节往往才是灵魂所在,诸如:算法和数据结构、框架、设计模式等,设计模式是一个虚幻的抽象的概念,好比建造房子时的设计理念方案一样,一个软件系统扩展性、可维护性以及稳定健壮性如何,很大程度上取决于设计模式。

如下,介绍我们在日常开发中常用的11种设计模式,这些设计模式都是非常经典,翻开源代码和一些开源框架经常会发现它们的踪影。

【二】单例模式

2.1概念

单例模式(SingleTon):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类的自身负责保存它的唯一实例,这个类可以保证没有其他任何实例可以被创建。并且它可以提供一个访问该实例的方法。

 单例模式有两种模式,一个是饿汉模式,一个是懒汉模式。

2.2 饿汉模式

在对象被加载时,定义的静态全局变量的就new实例化对象。

public class SingleTon{
	
	private static readonly SingleTon instance = new SingleTon();//静态初始化时就把对象实例化
	private SingleTon(){
	
	}
	private static getInstance(){
	    return instance ;
	}
       
}

2.3 懒汉模式

只有在调用了该对象的时候,才调用构造方法去实例化该对象实例。  多线程场景需要在构造方法里增加Lock,双重锁判断,其中有2个null判断。

public class Singleton {  
    /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
    private static Singleton instance;  
  
    /* 私有构造方法,防止被实例化 */  
    private Singleton() {}  
  
    /* 1:懒汉式,静态工程方法,创建实例 */  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}  

优点:延迟加载(需要的时候才去加载),适合单线程操作
缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。

多线程版本:

public class Singleton {  
    /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
    private static Singleton instance ;
    private static readonly object syncRoot = new object();  
  
    /* 私有构造方法,防止被实例化 */  
    private Singleton() {}  
  
    /* 1:懒汉式,静态工程方法,创建实例 */  
    public static Singleton getInstance() { 
        if(null == instance ){
	        lock(syncRoot){ 
                if (instance == null) {  
                    instance = new Singleton();
                }  
            }  
        }
    return instance;  
    }  
}  

【三】简单工厂模式

定义一个用于创建对象的接口,一个工厂类处于对产品类实例化调用的中心位置上,它决定哪一个产品类应当被实例化。
组成如下:
工厂类角色:含有一定的业务逻辑和判断逻辑,Java里往往是一个具体类来实现。
抽象产品角色:具体产品继承的父类或者实现的接口,Java里由接口或者抽象类来实现。
具体产品角色:工厂类所创建的对象就是此类角色的实例,由一个具体类实现。

示例代码:

public class Factory{ //getClass 产生Sample 一般可使用动态类装载装入类。
    public static Sample creator(int which){ 
        if (which==1)
            return new SampleA();
        else if (which==2)
            return new SampleB();
    }
}

【四】工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,工厂方法把简单工厂的内部逻辑判断
转移到了客户端代码来进行。如果想要加功能,直接在客户端修改即可实现。

//抽象产品角色
public interface Moveable {
    void run();
}
//具体产品角色
public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.println("plane....");
    }
}
//具体产品角色
public class Broom implements Moveable {
    @Override
    public void run() {
        System.out.println("broom.....");
    }
}
 
//抽象工厂
public abstract class VehicleFactory {
    abstract Moveable create();
}
//具体工厂
public class PlaneFactory extends VehicleFactory{
    public Moveable create() {
        return new Plane();
    }
}
//具体工厂
public class BroomFactory extends VehicleFactory{
    public Moveable create() {
        return new Broom();
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        VehicleFactory factory = new BroomFactory();
        Moveable m = factory.create();
        m.run();
    }
}

组成:

  • 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
  • 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象
  • 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
  • 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的。

【五】抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。
一个系统有多于一个的产品族,而系统只消费其中某一产品族时。
一个系统不依赖于产品类实例如何被创建、组合和表达的细节时。
工厂模式是为一类对象提供创建接口,抽象工厂模式是为创建一组(多类)相关或互相依赖的对象提供创建接口。

示例代码:

//抽象工厂类
public abstract class AbstractFactory {
    public abstract Vehicle createVehicle();
    public abstract Weapon createWeapon();
    public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
    @Override
    public Food createFood() {
        return new Apple();
    }
    @Override
    public Vehicle createVehicle() {
        return new Car();
    }
    @Override
    public Weapon createWeapon() {
        return new AK47();
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        AbstractFactory f = new DefaultFactory();
        Vehicle v = f.createVehicle();
        v.run();
        Weapon w = f.createWeapon();
        w.shoot();
        Food a = f.createFood();
        a.printName();
    }
}

在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。

【六】策略模式

策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合。策略模式模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为,继承有助于析取这些算法中的公共功能。策略模式的优点是简化了单元测试。

【七】装饰模式

7.1 定义

装饰模式是动态地给一个对象添加一些额外额职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式是为已有功能动态地添加更多功能的一种方式。当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有的类的核心职责或主要行为。
新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。装饰模式提供了一个非常好的解决方案,把每个要装饰的功能放在单独的类中,让这个类包装它所要装饰的对象。当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地按顺序地使用装饰功能包装对象了。
优点
把类中的装饰功能从类中搬移去除,这样可以简化原有的类。
有效地把类的核心职责和装饰功能区分开,去除相关类中重复的装饰逻辑。

装饰模式

上图是Decorator 模式的结构图,让我们可以进行更方便的描述:

Component是定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。

Decorator是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

7.2 使用示例

假设情景:某人装扮自己形象,穿衣服,裤子,鞋子,戴帽子等来把自己给包装起来,需要把所需的功能按正确的顺序串联起来进行控制,我们应该如何设计才能做到呢?如下,先看下代码结构图:

先创建一个接口类:Component.java

public interface Component {    
    void show();
}

创建一个具体的 ConcreteComponent 来实现 Component 接口:Person.java

public class Person implements Component{
    private String name;
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Person(String name){
        this.name = name;
    }
 
    @Override
    public void show() {
        System.out.println("装扮的" + name);
    }
}

创建装饰类 Decorator 实现 Component 接口

public class Decorator implements Component{
    private Component mComponent;
    public void decoratorObj(Component component){
        mComponent = component;
    }
 
    @Override
    public void show() {
        if(mComponent != null){
            mComponent.show();
        }
    }
}

分别创建具体的装饰类:Jeans.java , Pelisse.java, Sandal.java ...等等,分别继承 Decorator.java 类

/** 牛仔裤 */
public class Jeans extends Decorator {
    @Override
    public void show(){
        System.out.println("穿牛仔裤");
        super.show();
    }
    
}

【八】代理模式

8.1 定义

基本概念:为其他对象提供一种代理以控制对这个对象的访问。也可以说,在出发点到目的地之间有一道中间层,意为代理。

8.2 使用的优势


授权机制不同级别的用户对同一对象拥有不同的访问权利,如在论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),论坛就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限。

某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动。

举例两个具体情况:

如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片。
如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象。
总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存。所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系。

8.3 如何使用


以论坛系统为例,访问论坛系统的用户有多种类型:注册普通用户、论坛管理者、系统管理者、游客。注册普通用户才能发言,论坛管理者可以管理他被授权的论坛,系统管理者可以管理所有事务等,这些权限划分和管理是使用Proxy完成的。
在Forum中陈列了有关论坛操作的主要行为,如论坛名称,论坛描述的获取和修改,帖子发表删除编辑等,在ForumPermissions中定义了各种级别权限的用户:

public class ForumPermissions implements Cacheable {
    /**
    * Permission to read object.
    */
    public static final int READ = 0;
 
    /**
    * Permission to administer the entire sytem.
    */
    public static final int SYSTEM_ADMIN = 1;
 
    /**
    * Permission to administer a particular forum.
    */
    public static final int FORUM_ADMIN = 2;
 
    /**
    * Permission to administer a particular user.
    */
    public static final int USER_ADMIN = 3;
 
    /**
    * Permission to administer a particular group.
    */
    public static final int GROUP_ADMIN = 4;
 
    /**
    * Permission to moderate threads.
    */
    public static final int MODERATE_THREADS = 5;
 
    /**
    * Permission to create a new thread.
    */
    public static final int CREATE_THREAD = 6;
 
    /**
    * Permission to create a new message.
    */
    public static final int CREATE_MESSAGE = 7;
 
    /**
    * Permission to moderate messages.
    */
    public static final int MODERATE_MESSAGES = 8;
  
    public boolean isSystemOrForumAdmin() {
        return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
    }
 
//相关操作代码
}

因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来。比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:

public class ForumProxy implements Forum {
    private ForumPermissions permissions;
    private Forum forum;
    this.authorization = authorization;
 
    public ForumProxy(Forum forum, Authorization authorization,ForumPermissions permissions){
        this.forum = forum;
        this.authorization = authorization;
        this.permissions = permissions;
    }
    .....
    public void setName(String name) throws UnauthorizedException,
        ForumAlreadyExistsException{
        //只有是系统或论坛管理者才可以修改名称
      if (permissions.isSystemOrForumAdmin()) {
        forum.setName(name);
      }
    else {
    throw new UnauthorizedException();
    }
    }
    ...
 
} 

而DbForum才是接口Forum的真正实现,以修改论坛名称为例:

public class DbForum implements Forum, Cacheable {
    ...
    public void setName(String name) throws ForumAlreadyExistsException {
  ....
        this.name = name;
       //这里真正将新名称保存到数据库中
       saveToDb();
  ....
    }
    ...
}

凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的"网关","安全代理系统"。
在平时应用中,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用Proxy,实际你已经在使用Proxy了。
示意流程图

代理模式

【九】模板方法模式

概念:定义一个操作中的算法的骨架,将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。
模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。
模板方法模式提供了一个代码复用的平台。

模板方法模式在很多组件和框架中经常看到,如:Spring中的各种Template,有JdbcTemplate、RedisTemplate、RestTemplate等。

【十】建造者模式

10.1 定义

基本概念:是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们。用户不知道内部的具体构建细节。Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到。

UML结构图:
Builder模式

上图是Strategy 模式的结构图,让我们可以进行更方便的描述:

Builder:为创建一个Product对象的各个部件指定抽象接口。

ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,提供一个检索产品的接口

Director:构造一个使用Builder接口的对象。

Product:表示被构造的复杂对象。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。

10.2 优势


是为了将构建复杂对象的过程和它的部件解耦。注意:是解耦过程和部件。
因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮、方向盘、发动机,还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开。

10.3 如何使用


首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示。

首先,需要一个接口,它定义如何创建复杂对象的各个部件:
 

public interface Builder {
   //创建部件A  比如创建汽车车轮void buildPartA();
   //创建部件B 比如创建汽车方向盘void buildPartB();
   //创建部件C 比如创建汽车发动机void buildPartC();
   //返回最后组装成品结果 (返回最后装配好的汽车)
   //成品的组装过程不在这里进行,而是转移到下面的Director类中进行.
   //从而实现了解耦过程和部件
    Product getResult();
}

 用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品:

public class Director {
    private Builder builder;
    public Director( Builder builder ) {
        this.builder = builder;
   }
   // 将部件partA partB partC最后组成复杂对象
   //这里是将车轮 方向盘和发动机组装成汽车的过程
    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

Builder的具体实现ConcreteBuilder:

  • 通过具体完成接口Builder来构建或装配产品的部件;
  • 定义并明确它所要创建的是什么具体东西;
  • 提供一个可以重新获取产品的接口。
public class ConcreteBuilder implements Builder {
 Part partA, partB, partC;
 public void buildPartA() {
  //这里是具体如何构建
 }
 public void buildPartB() {
  //这里是具体如何构建
 }
 public void buildPartC() {
  //这里是具体如何构建
 }
 public Product getResult() {
  //返回最后组装成品结果
 }
}

复杂对象:产品Product

public interface Product { }

复杂对象的部件:

public interface Part { }

调用Builder模式:

ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director( builder );
director.construct();
Product product = builder.getResult();

10.4 Builder模式的应用


在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池。"池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能。修改Builder模式中Director类使之能诊断"断肢"断在哪个部件上,再修复这个部件。
 

【十一】观察者模式

基本概念:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。将一个系统分割成一系列相互协作的类有一个很不好的副作用,需要维护相关对象间的一致性。否则为了维持一致性使各类紧密耦合,给维护、扩展和重用都带来不便。
使用场景:

  • 当一个对象的改变需要同时改变其他对象的时候
  • 不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。

【十二】适配器模式

12.1 定义

基本概念:系统的数据和行为都正确,但接口不符时,应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
 

12.2 角色职责

  • 目标角色(Target):该角色定义把其他类转换为何种接口,也就是我们期望的接口。
  • 源角色(Adaptee):希望转换的源角色,已经存在的,运行良好的只是需要适配的角色。
  • 适配器角色(Adaptor):适配器模式的核心角色,其他两个角色都是已经存在的角色,适配器角色是需要新建立的,职责简单:通过继承或是类关联的方式把源角色转换成目标角色。
     

 当遇到两个类所做的事情相同或相似,但是具有不同的接口时要使用它。

【十三】总结

以上介绍的11种设计模式在日常的开发工作中会经常使用到,也在很多开源框架如:Spring中就会看到很多的案例,灵活运用这些设计模式可以使我们的系统做到:易扩展、可维护性高、更稳健等。


面试系列连载

《面试系列篇》——面试官最喜欢问的Redis知识

《面试系列篇》——ShardingJdbc分库分表浅谈

《面试系列篇》——MySQL慢查询及解决方案

《面试系列篇》——听说面试官喜欢问这些MySQL知识

《面试系列篇》——Paxos与Zookeeper分布式一致性面试必备

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

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

相关文章

【机器学习】岭回归和LASSO回归详解以及相关计算实例-加利福尼亚的房价数据集、红酒数据集

文章目录一,岭回归和LASSO回归1.1 多重共线性1.2 岭回归接手1.3 线性回归的漏洞(线性系数的矛盾解释)1.4 Ridge Regression1.5 岭回归实例(加利福尼亚的房价数据集)1.6 MSE1.7 LASSO1.8 Ridge岭回归和Lasso套索回归的比较1.9 Lass…

H5基本开发2——(HTML常见标签)

常见标签说明 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <meta http-equiv"X-UA-Compatible&q…

Elasticsearch安装

1.Linux下使用Elasticsearch 本教程所有操作均在CentOS 7.x环境下进行。 elasticsearch基于java进行开发&#xff0c;所以在运行elasticsearch之前需要安装jdk yum -y install java-1.8.0-openjdk 1.1.安装和配置 即将开始在centos 7 下安装Elasticsearch 1.1.1.新建一个用…

(四)QCustomPlot柱形图动态显示实例开发

系列文章目录 提示&#xff1a;这里是该系列文章的所有文章的目录 第一章&#xff1a; &#xff08;一&#xff09;QCustomPlot常见属性设置、多曲线绘制、动态曲线绘制、生成游标、矩形放大等功能实现 第二章&#xff1a; &#xff08;二&#xff09;QCustomPlot生成热力图/矩…

【数据结构与算法】递归全流程详细剖析 | 详解图的深度优先遍历

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680;文章简介&#xff1a;本篇文章属于数据结构与算法系列文章&#xff0c;这篇文章会对算法中的递归进行一个详细的介绍&#xff0c;不仅是概念&#xff0c;而是从运行过程中的每一步进行详细分析。并使用递归的方式来…

Vue3 - 使用 mitt.js 进行组件通信(兄弟关系)

前言 在 Vue2 中&#xff0c;两个同级&#xff08;兄弟关系&#xff09;的组件传递数据&#xff0c;都是利用一个叫 EventBus 事件总线&#xff0c;利用这根总线&#xff0c;可以让两个毫无关系的组件进行通信。 其实这个问题的本质核心解决方案&#xff0c;就一句话。通过第三…

开传奇需要什么技术要什么条件

开传奇需要什么技术要什么条件 对于这个问题&#xff0c;近期问的人比较多。这也是热爱传奇这个游戏的朋友会问到的一个问题&#xff0c;因为喜欢玩这个游戏&#xff0c;也想要自己去开一个经营一个 不管是电脑端还是手机端。但是对于一些新手确实不知道该如何开始操作从哪些方…

基于PHP+MySQL的校园二手旧书回收捐赠系统

校园内因为所教授的课程比较多,人数基数也比较大,所以每年都会产生大量的二手废旧图书,很多时候这些图书还可以进行二次利用,如果直接当废品进行回收很暴殄天物的,所以为了能够让这些校园内的二手图书得到更多的利用,我们开发了PHP校园二手旧书回收捐赠系统 本系统分为前台和后…

「Redis数据结构」压缩列表(ZipList)

「Redis数据结构」压缩列表&#xff08;ZipList&#xff09; 文章目录「Redis数据结构」压缩列表&#xff08;ZipList&#xff09;一、概述二、结构三、连锁更新问题四、压缩列表的缺陷五、小结参考ZipList 是一种特殊的“双端链表” &#xff0c;由一系列特殊编码的连续内存块…

基于协同过滤进行金融产品个性化推荐 代码+数据

1.案例简介 (1)方法概述: 本教程包含如下内容: 从原始的数据文件中加载数据,进行训练集和测试集的切分。 对数据分batch, 利用用户侧信息,和商品侧信息,进行双塔模型的训练 结果展示 (2)宏观流程图 (3)案例知识点 pytorch 视频CTR预估指标 博客point wise 以及 pair wise …

从0到1图文教你如何将spring boot项目部署到minikube中去

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 源码 本项目博文的源码已上传github&#xff0c;有需要自取 github: https://github.com/weihubeats/weihubeats_demos/tree/master/spring-boot-demos/spring-…

C#界面里Control.Enabled 属性的使用

C#界面里Control.Enabled 属性的使用 在开发中即使一个细节也可以决定成败。 前段时间刚好是毕业季,公司招聘了很多应界毕业生, 由于项目非常多,许多老手都已经分配到各个项目上去,还有一些小项目不得不让这些新生力军来接手。 这些初生牛犊不怕虎,天天加班,夜夜苦战…

idea打开之前的项目不能正常编译/idea中项目Compile output丢失问题

报错笔记 文章目录错误一&#xff1a;Cannot resolve class or package java错误二&#xff1a;Compile output丢失问题下面的报错发生情况都是打开之前写的JavaWeb文件时&#xff0c;各个文件中的代码爆红错误一&#xff1a;Cannot resolve class or package ‘java’ 在idea…

【安卓应用渗透】第一篇:安卓逆向回顾和梳理-2211

文章目录安卓开发课程回顾第一课&#xff1a;安卓项目文件结构&#xff08;逻辑视图&#xff09;第五课&#xff1a;文件读取和数据库存取文件存取SQLite数据库存取安卓开发&#xff1a;案前资料库安卓逆向课程回顾第一课&#xff1a;基础逆向工具&#xff08;Apktool, Keytool…

【分享】订阅金蝶云进销存集简云连接器同步销货数据至金蝶云进销存系统

方案场景 在企业规模不断壮大的过程中&#xff0c;企业都是在钉钉内提交OA审批&#xff0c;并通过人工的方式统计多种审批数据&#xff0c;然后手动导入到某系统内&#xff0c;如果中间有调整又需要从头再进行核对&#xff0c;繁琐的流程严重影响了业务拓展。基于该方式企业希…

[附源码]SSM计算机毕业设计重庆工程学院教师宿舍管理系统论文JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Eolink征文活动--推荐国产神器Eolink!API优先,Eolink领先!

前言&#xff1a; 在我们后端开发者做项目的时候&#xff0c;避免不了与前端界面的交互&#xff0c;对于我来讲&#xff0c;在做项目的时候用到过postman&#xff0c;swagger做接口测试工作&#xff0c;在公司的时候公司主要用YApi可视化接口平台&#xff0c;最近使用了一个爆款…

负担过重何以轻装前行

随波逐流并不一定过得容易。 猜测负担过重原因&#xff1a; 所作的事情和预期差异大自己并不擅长目前所从事的专业恐惧失败试错成本过高基础薄弱无法持续成长简单问题复杂化复杂问题简单化…… 如何改变这种情况&#xff1f; 自我认知和外部感知都存在分析错位和信息不对称的…

解决ggplot绘制散点图形状超过6个的警告

正常画图&#xff1a; library(ggplot2) ggplot(mpg,aes(displ,hwy))geom_point(aes(shapeclass,colorclass))可以看出形状少了一个&#xff0c;SUV没有形状 并且还会弹出这样的警告&#xff1a; Warning message: “The shape palette can deal with a maximum of 6 discrete…

【附源码】Python计算机毕业设计网络求职招聘系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…