万字解析设计模式之工厂方法模式与简单工厂模式

news2024/11/27 12:53:48

一、概述

1.1简介

在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

在本教程中会介绍三种工厂的使用

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

 1.2简单工厂模式

概述

简单工厂不是一种设计模式,反而比较像是一种编程习惯。

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个工厂类,该类专门用于创建其他对象。简单工厂模式属于静态工厂模式,即在工厂类中提供静态方法,根据传入的参数不同返回不同的对象实例。

结构

简单工厂模式包含三个角色:

  1. 工厂类(Creator):提供了创建产品的方法,调用者通过该方法来获取产品。
  2. 抽象产品类(Product):定义了产品的规范,描述了产品的主要特性和功能。
  3. 具体产品类(Concrete Product):定义具体的产品实现类,实现抽象产品类中的抽象方法。

 实现

原先逻辑 

 SimpleCoffeeFactory.java

package com.yanyu.SimpleFactory;

public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {

        Coffee coffee = null;

        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffee;
    }
}

Coffeestore.java

package com.yanyu.SimpleFactory;

public class Coffeestore {
    public Coffee orderCoffee(String type) {
        Coffee coffee = null;
        if ("american".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if ("latte".equals(type)) {
            coffee = new LatteCoffee();
        } else {
            throw new RuntimeException("对不起,您所点的咖啡没有");
        }

        // 加配料
        coffee.addMilk();
        coffee.addSugar();

        return coffee;
    }
}

Coffee.java

package com.yanyu.SimpleFactory;

public abstract class Coffee {

    public abstract String getName();
    // 加糖
    public void addSugar() {
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
        System.out.println("加奶");
    }
}

AmericanoCoffee.java

package com.yanyu.SimpleFactory;

public class AmericanoCoffee extends Coffee{
    public String getName(){
        return"美式咖啡";
    }
}

LatteCoffee.java

package com.yanyu.SimpleFactory;

public class LatteCoffee extends Coffee{
        public String getName(){
            return"拿铁咖啡";
        }
}

test

package com.yanyu.SimpleFactory;

public class Client {
    public static void main(String[] args) {
        // 创建咖啡店类对象
        Coffeestore store = new Coffeestore();
        Coffee coffee = store.orderCoffee("latte");
        System.out.println(coffee.getName());
    }
}

SimpleCoffeeFactory是工厂类,负责生产不同类型的咖啡,Coffeestore是客户端,通过调用工厂类的方法来获取咖啡。简单工厂模式属于创建型模式,通过将对象的创建工作交给工厂类来实现客户端与具体产品类的解耦,可以方便地扩展新的产品类型,同时也便于管理和维护。在这个例子中,Coffeestore只需要调用工厂类的createCoffee方法即可获取不同类型的咖啡,而不需要关心具体如何创建

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。

后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。

 扩展静态工厂

静态工厂是一种创建对象的方式,它通过一个静态方法来获取对象,有时也被称为静态工厂方法。静态工厂方法通常不需要创建对象,所以可以在不创建对象的情况下直接返回对象。

通过扩展静态工厂,我们可以让工厂方法更加灵活,以便能够生产不同类型的对象。它也不是23种设计模式中的

public class SimpleCoffeeFactory {
​
    public static Coffee createCoffee(String type) {
        Coffee coffee = null;
        if("americano".equals(type)) {
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}

优缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

1.3工厂方法模式

针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则。

概述

工厂方法模式(Factory Method Pattern)又称为工厂模式,是一种创建型设计模式。在工厂方法模式中,定义一个用于创建对象的接口,但让子类决定将哪一个类实例化。工厂方法把类的实例化推迟到子类中进行,从而实现了解耦。

结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

 实现

 抽象工厂:

package com.yanyu.FactoryMethod;


public interface CoffeeFactory {
    Coffee createCoffee();
}

具体工厂:

public class LatteCoffeeFactory implements CoffeeFactory {
​
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}
​
public class AmericanCoffeeFactory implements CoffeeFactory {
​
    public Coffee createCoffee() {
        return new AmericanoCoffee();
    }
}

咖啡店类:

package com.yanyu.FactoryMethod;

public class CoffeeStore {

    private CoffeeFactory factory;

    public void SetFactory(CoffeeFactory factory) {
        this.factory = factory;
    }

    public Coffee orderCoffee() {
        Coffee coffee = factory.createCoffee();
        coffee.addMilk();
        coffee.addSugar();
        return coffee;
    }
}

测试

package com.yanyu.FactoryMethod;

public class client {
    public static void main(String[] args) {
        // 创建咖啡店对象
        CoffeeStore store = new CoffeeStore();
        //创建工厂对象
        CoffeeFactory factory = new AmericanCoffeeFactory();
        store.SetFactory(factory);
        // 点咖啡
        Coffee coffee = store.orderCoffee();
        System.out.println(coffee.getName());
    }
}

这就是实现开闭原则的核心:一旦转换成功,我们拓展功能就只需要增加相应类的or接口即可,不需要再动原来的代码

工厂方法模式是简单工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

 优缺点 

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
  • 工厂方法模式增加了系统抽象性和理解难度,需要对工厂类和具体产品类进行抽象和设计。

 常见应用

常见的使用场景包括:

  1. 数据库连接池的实现。

  2. 日志处理器的实现。

  3. 图形界面控件库的开发。

  4. 任何需要创建对象的场景,特别是对象创建过程复杂或需要隐藏细节的场景。

1.4抽象工厂模式

产品族和同一级别产品

产品族是指一组具有相似特征和用途的产品,它们通常共享相同的品牌名称、市场定位和推广策略。比如,苹果公司的iPhone产品族包括iPhone 12、iPhone 11、iPhone SE 等,它们都是苹果公司的智能手机产品,具有相似的功能和设计。

同一级别产品是指在市场上竞争的,具有相似功能和特点的产品。这些产品可能来自不同的品牌,但是它们都是在同一细分市场上竞争的产品。举例来说,苹果公司的iPhone和三星公司的Galaxy手机都是智能手机,它们在市场上是同一级别的产品。

 概述

在抽象工厂模式中,我们定义一个抽象工厂接口,该接口具有多个工厂方法,每个工厂方法负责创建一个产品族中的一种产品。然后我们创建一个具体的工厂类来实现抽象工厂接口,并在其中实现工厂方法,以便能够创建具体的产品。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

  结构

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

实现

 抽象工厂:

package com.yanyu.AbstractFactory;

public interface DessertFactory {

    Coffee createCoffee();
    Dessert createDessert();
}

抽象类

package com.yanyu.AbstractFactory;

public abstract class Dessert {
    public abstract void show();
}

具体工厂:

//美式甜点工厂
public class AmericanDessertFactory implements DessertFactory {
​
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }
​
    public Dessert createDessert() {
        return new MatchaMousse();
    }
}
//意大利风味甜点工厂
public class ItalyDessertFactory implements DessertFactory {
​
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
​
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

具体类:

package com.yanyu.AbstractFactory;

public class Trimisu extends Dessert {
    public void show() {
        System.out.println("提拉米苏");
    }
}

package com.yanyu.AbstractFactory;

public class MatchaMousse extends Dessert {
    public void show() {
        System.out.println("抹茶慕斯");
    }
}

test

package com.yanyu.AbstractFactory;

public class Client {
    public static void main(String[] args) {
    // 创建的是意大利风味甜品工厂对象
    // ItalyDessertFactory factory = new ItalyDessertFactory();
    AmericanDessertFactory factory = new AmericanDessertFactory();
    // 获取拿铁咖啡和提拉米苏甜品
    Coffee coffee = factory.createCoffee();
    Dessert dessert = factory.createDessert();
    System.out.println(coffee.getName()); dessert.show();
}
}


如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。

优缺点 

优点:

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:

由于抽象工厂只能创建某个产品族中的全部产品,所以加入新产品时需要修改所有的具体工厂类,增加了维护成本

常见应用

 抽象工厂模式常见应用包括以下几个方面:

1. 操作系统的UI界面设计:操作系统常常提供多种不同的UI界面风格,如Windows提供的经典风格、XP风格、Win7风格等,可以使用抽象工厂模式来实现对不同风格的UI界面进行定制和管理。

2. 游戏开发:游戏中的物品、角色、道具等都可以使用抽象工厂模式来进行设计,不同的游戏可以使用不同的抽象工厂来创建不同的游戏元素。

3. 数据库连接:数据库连接器可以使用抽象工厂模式来设计,通过使用不同的工厂来创建不同类型的数据库连接器,从而支持多种不同的数据库类型。

4. 跨平台开发:不同的操作系统和不同的硬件架构需要不同的代码实现,使用抽象工厂模式可以通过实现不同的工厂来创建适配不同平台的代码。

5. GUI开发:GUI框架常常需要支持多种不同的控件和主题,使用抽象工厂模式可以通过不同的工厂来创建不同的控件和主题。

1.5JDK源码解析-Collection.iterator方法


public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("令狐冲");
        list.add("风清扬");
        list.add("任我行");
​
        //获取迭代器对象
        Iterator<String> it = list.iterator();
        //使用迭代器遍历
        while(it.hasNext()) {
            String ele = it.next();
            System.out.println(ele);
        }
    }
}

 Collection接口是抽象工厂类,ArrayList是具体的工厂类;Iterator接口是抽象商品类,ArrayList类中的Iter内部类是具体的商品类。在具体的工厂类中iterator()方法创建具体的商品类的对象。

 二、实验

简单工厂模式

任务描述

本关任务:某电视机厂专为各知名电视机品牌代工生产各类电视机,当需要海尔牌电视机时只需要在调用该工厂的工厂方法时传入参数“Haier”,需要海信电视机时只需要传入参数“Hisense”,工厂可以根据传入的不同参数返回不同品牌的电视机。现使用简单工厂模式来模拟,程序将会自动从配置文件中读取参数,请根据以下类图来补全代码。

,

相关知识

为了完成本关任务,你需要掌握:

  1. 简单工厂模式包含的角色;
  2. 简单工厂模式缺点。
简单工厂模式包含的角色
  • Factory:工厂角色
  • Product:抽象产品角色
  • ConcreteProduct:具体产品角色
简单工厂模式缺点
  1. 工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响;
  2. 增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度;
  3. 系统扩展困难,一旦添加新产品不得不修改工厂逻辑;
  4. 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展。

编程要求

根据提示,给“HaierTV.java,HisenseTV.java,TVFactory.java”三个代码文件内注释需要填空地方补充代码。

Product:抽象产品角色

package step1;

public interface TV {
    void play();
}

ConcreteProduct:具体产品角色

package step1;

public class HaierTV implements TV/**填空——————————**/{
    @Override
    public void play() {
        System.out.println("海尔电视机播放中......");
    }
}
package step1;

public class HisenseTV implements TV/**填空——————————**/{
    @Override
    public void play() {
        System.out.println("海信电视机播放中......");
    }
}

Factory:工厂角色

package step1;

public class TVFactory {
    public static TV produceTV(String brand) throws Exception
    {
        
        if(brand.equalsIgnoreCase("Haier"))
        {
            System.out.println("电视机工厂生产海尔电视机!");
            /******填空******/
            return new HaierTV();
            /************/
        }
        else if(brand.equalsIgnoreCase("Hisense"))
        {
            System.out.println("电视机工厂生产海信电视机!");
             /******填空******/
            return new HisenseTV();
            /************/
        }
        else
        {
            throw new Exception("对不起,暂不能生产该品牌电视机!");
        }
       
    }
}

顾客类

package step1;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class XMLUtilTV {
    public static String getBrandName()
    {
        try
        {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("/data/workspace/myshixun/src/SimpleFactoryconfigTV.xml"));

            //获取包含品牌名称的文本节点
            NodeList nl = doc.getElementsByTagName("brandName");
            Node classNode=nl.item(0).getFirstChild();
            String brandName=classNode.getNodeValue().trim();
            return brandName;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

这段代码实现了从指定的XML配置文件中获取电视品牌名称的方法。具体步骤如下:

1. 导入所需要的Java类库,包括org.w3c.dom、javax.xml.parsers和java.io.File。

2. 创建XMLUtilTV类,并定义静态的getBrandName方法,返回类型为String,用于获取配置文件中的品牌名称。

3. 在getBrandName方法中,使用DocumentBuilderFactory类和DocumentBuilder类来创建文档对象,即读取XML配置文件。

4. 获取文档对象中的品牌名称节点,通过doc.getElementsByTagName("brandName")获取节点列表,然后使用nl.item(0)获取第一个节点,再使用getFirstChild()获取节点的第一个子节点。

5. 最后通过classNode.getNodeValue().trim()获取节点的文本值,并去掉开头结尾的空格。

6. 如果有异常发生,打印堆栈信息,并返回null。

package step1;
public class Client {
    public static void main(String args[])
    {
        try
        {
            TV tv;
            String brandName= XMLUtilTV.getBrandName();
            tv= TVFactory.produceTV(brandName);
            tv.play();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

 工厂方法模式

任务描述

本关任务:将原有的电视机工厂进行分割,为每种品牌的电视机提供一个子工厂,海尔工厂专门负责生产海尔电视机,海信工厂专门负责生产海信电视机,如果需要生产 TCL 电视机或创维电视机,只需要对应增加一个新的 TCL 工厂或创维工厂即可,原有的工厂无须做任何修改,使得整个系统具有更加的灵活性和可扩展性。 现使用工厂方法模式来模拟,程序将会自动从配置文件中读取参数,请根据以下类图来修补代码。

,

相关知识

为了完成本关任务,你需要掌握:

  1. 工厂方法模式包含的角色;
  2. 实现要点;
  3. 工厂方法模式缺点。
工厂方法模式包含的角色
  • Product:抽象产品
  • ConcreteProduct:具体产品
  • Factory:抽象工厂
  • ConcreteFactory:具体工厂
实现要点
  1. 让所有产品都遵循同一接口。 该接口必须声明对所有产品都有意义的方法。
  2. 在创建类中添加一个空的工厂方法。 该方法的返回类型必须遵循通用的产品接口。
  3. 在创建者代码中找到对于产品构造函数的所有引用。 将它们依次替换为对于工厂方法的调用, 同时将创建产品的代码移入工厂方法。你可能需要在工厂方法中添加临时参数来控制返回的产品类型。工厂方法的代码看上去可能非常糟糕。 其中可能会有复杂的 switch 分支运算符, 用于选择各种需要实例化的产品类。 但是不要担心, 我们很快就会修复这个问题。
  4. 为工厂方法中的每种产品编写一个创建者子类, 然后在子类中重写工厂方法, 并将基本方法中的相关创建代码移动到工厂方法中。
  5. 如果应用中的产品类型太多, 那么为每个产品创建子类并无太大必要, 这时你也可以在子类中复用基类中的控制参数。
  6. 如果代码经过上述移动后, 基础工厂方法中已经没有任何代码, 你可以将其转变为抽象类。 如果基础工厂方法中还有其他语句, 你可以将其设置为该方法的默认行为。
工厂方法模式缺点
  • 系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销;
  • 增加了系统的抽象性和理解难度。

编程要求

根据提示,给“HaierTVFactory.java,HisenseTVFactory.java”两个代码文件内注释需要填空地方补充代码。

 Product:抽象产品

package step3;

public interface TV {
    void play();
}

ConcreteProduct:具体产品、

package step3;

public class HaierTV implements TV{
    @Override
    public void play() {
        System.out.println("海尔电视机播放中......");
    }
}
package step3;

public class HisenseTV implements TV{
    @Override
    public void play() {
        System.out.println("海信电视机播放中......");
    }
}

Factory:抽象工厂

package step3;

public interface TVFactory {
    TV produceTV();
}

 ConcreteFactory:具体工厂

package step3;

public class HaierTVFactory implements TVFactory{
    @Override
    public TV produceTV() {
        /*填空*/
        return new HaierTV();
    }
}
package step3;

public class HisenseTVFactory implements TVFactory{
    @Override
    public TV produceTV() {
        /*填空*/
        return new HisenseTV();
    }
}

 顾客

package step3;

public class Client {
    public static void main(String args[])
    {
        try
        {
            TV tv;
            TVFactory factory;
            factory=(TVFactory)XMLUtil.getBean();
            tv=factory.produceTV();
            tv.play();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}
package step3;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class XMLUtil {
    public static Object getBean()
    {
        try
        {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("./src/FactoryMethodconfig.xml"));

            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();

            //通过类名生成实例对象并将其返回
            Class c=Class.forName(cName);
            Object obj=c.newInstance();
            return obj;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

 

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

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

相关文章

麒麟KYLINOS2303版本上使用KDE桌面共享软件

原文链接&#xff1a;麒麟KYLINOS2303版本上使用KDE桌面共享软件 hello&#xff0c;大家好啊&#xff0c;今天给大家推荐一个在麒麟KYLINOS桌面操作系统2303版本上使用KDE桌面共享软件的文章&#xff0c;通过安装KDE桌面共享软件&#xff0c;可以让远程vnc客户端连接访问本机桌…

飞鼠异地组网工具基本使用教程

飞飞鼠异地组网工具基本使用教程 一、飞鼠工具介绍1.1 飞鼠工具简介1.2 飞鼠工具特点1.3 飞鼠工具使用场景1.4 飞鼠工具官网1.5 飞鼠工具版本介绍1.6 飞鼠工具节点类型 二、本次实践介绍2.1 本次实践简介2.2 本次环境规划 三、Docker环境安装工作3.1 master节点安装Docker3.2 子…

2023年【湖南省安全员-C证】新版试题及湖南省安全员-C证证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 湖南省安全员-C证新版试题是安全生产模拟考试一点通总题库中生成的一套湖南省安全员-C证证考试&#xff0c;安全生产模拟考试一点通上湖南省安全员-C证作业手机同步练习。2023年【湖南省安全员-C证】新版试题及湖南省…

简历:了解常见的设计模式

一、请讲一讲设计模式的好处 在Java中应用设计模式有以下好处&#xff1a; 1. 提高代码的可维护性和可读性&#xff1a; 设计模式提供了一种结构化的方式来组织代码&#xff0c;使得代码更易于理解和修改。通过使用设计模式&#xff0c;开发人员可以遵循一致的设计原则和最佳…

BUUCTF rar 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 这个是一个rar文件&#xff0c;里面好像隐藏着什么秘密&#xff0c;但是压缩包被加密了&#xff0c;毫无保留的告诉你&#xff0c;rar的密码是4位纯数字。 密文&#xff1a; 下载附件&#xff0c;解压得到一个rar压…

保护自己免受AI诈骗的方法

前言 在21世纪&#xff0c;人工智能已经成为我们日常生活的一部分。不仅在聊天、写作、绘画和编程领域展现了巨大的潜力&#xff0c;还改变了我们的生活方式&#xff0c;提供了便捷和创新。然而&#xff0c;随着这一技术的迅速发展&#xff0c;我们也不得不面对新的威胁&#…

sql--索引使用

最左前缀法则&#xff08;联合索引&#xff09; 联合索引 位置不影响&#xff0c;但是所有索引必须连续使用&#xff0c;才会走索引 中间跳过则会造成后面索引则会失效 索引失效 规避方法---尽量使用> 或 < Explain需要重点关注的字段 Type key_leng possibl…

让AI成为你的编程助手——DevChat AI插件在VSCode中的应用

文章目录 1. 前言2. DevChat注册3. DevChat安装依赖安装插件安装 4. DevChat体验写代码5. 总结 1. 前言 随着人工智能技术的飞速发展&#xff0c;ChatGPT已经成为了这个领域的一股强大力量。它的出现&#xff0c;让我们看到了人工智能在自然语言处理方面的惊人能力&#xff0c…

业务设计——透明化实现用户敏感数据加解密和历史数据洗数

文章以 敏感数据安全性存储 为背景&#xff0c;讲述 ShardingSphere 完成数据加密上线&#xff0c;以及后续的业务系统加密改造的过程。 以下如无特殊说明&#xff0c;ShardingSphere-JDBC Starter 版本为 4.1.1。 业务背景 事情的起因是集团对于敏感数据安全的重视&#xff…

【LeetCode:274. H 指数 | 二分 】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

《算法通关村—计算器|逆波兰问题解析》

《算法通关村—计算器|逆波兰问题解析》 计算器问题 描述 LeetCode227.给你一个字符串表达式 s &#xff0c;请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。 输入&#xff1a;s "32*2" 输出&#xff1a;7基本思路&#xff1a;理解题目&a…

1.1 计算机安全概念

思维导图&#xff1a; 前言&#xff1a; 第1章: 计算机与网络安全概念笔记 1. 学习目标 了解保密性、完整性和可用性的关键安全需求。了解OSI的X.800安全架构。识别和举例说明不同的安全威胁和攻击。掌握安全设计的基本准则。熟悉攻击面和攻击树的使用。了解与密码标准相关的…

VulnHub DC-1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

Springboot项目Eureka安全加密

一、通过security增加账号密码登录 1、registry服务pom增加security依赖 2、registry 配置文件 指定security账号密码 3、http://账号:密码IP:PORT/eureka/ 4、重启 二、关闭节点 三、防火墙移除eureka端口访问 参考&#xff1a;Linux(Centos7)操作记录

制作电子版宣传画册,抢占线上消费市场

随着互联网和移动设备的普及&#xff0c;企业在如今如此激烈的市场竞争中&#xff0c;怎样才能提高自身的宣传力度&#xff0c;进而让企业在市场中占一席之地呢&#xff1f;现在大多数企业都青睐于借助电子画册的形式来实现。 如何制作电子版宣传画册&#xff0c;抢占市场消费资…

02、SpringCloud -- Redis和Cookie过期时间刷新功能

目录 需求:代码流程过滤器类工具类过滤判断远程调用feign接口gitee 配置接口实现过滤器run方法测试:问题:需求: cookie应该写在网关中,网关中可以自定义filter过滤器,用来实现cookie的刷新和redis中key的刷新,延长用户的操作时间。 就是让用户每操作一次,就可以重新刷…

Springboot前后端分离同一套代码在同一台服务器上搭两个测试环境

一、Nginx监听不同端口 1、两个环境不同Service端口指定&#xff0c;可参考 中间件&#xff1a;Nginx工作使用记录&#xff08;反向代理&#xff09; 2、端口允许访问设置&#xff1a; 云服务需配置开通入方向规则 检查服务器防火墙是否开通&#xff0c;并开通端口&#xff0…

大数据学习(18)-任务并行度优化

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

自制照片书的全过程

​ 如今&#xff0c;我们生活在一个信息爆炸的时代&#xff0c;照片已成为我们记录生活、分享情感的重要方式。而亲手制作照片书&#xff0c;不仅能让你感受到制作过程的乐趣&#xff0c;更能为你的回忆注入独特的情感和感受。 但是你知道如何制作照片书吗?小编给大家推荐一款…

华为机试题:HJ7 取近似值

目录 第一章、算法题1.1&#xff09;题目描述1.2&#xff09;第一种解题思路与答案1.3&#xff09;第二种解题思路与答案1.4&#xff09;牛客链接 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、算法…