创建型设计模式-2.工厂设计模式

创建型设计模式-2.工厂设计模式

一、示例代码

下面是一个没有使用工厂设计模式的例子,ResourceLoader 类负责根据 URL 的前缀来加载资源。根据不同的前缀,它执行不同的操作来创建 Resource 对象。这导致了以下问题:

  1. 代码冗余:在每个分支中,都有相似的复杂操作用于创建 Resource 对象,这造成了代码的重复。
  2. 可扩展性差:当需要添加新的资源类型时,需要修改 ResourceLoader 类的代码,并增加对应的分支。这违反了开闭原则,使代码难以扩展和维护。
  3. 低内聚性:ResourceLoader 类的职责既包括根据前缀选择创建资源对象的逻辑,又包括资源对象的创建过程,导致职责不够单一。

没有使用工厂设计模式的代码实现不够灵活,代码复用性较低,并且随着业务需求的变化,代码的维护和扩展会变得困难。相比之下,使用工厂设计模式可以将对象的创建逻辑封装到工厂类中,提高了代码的可扩展性和可维护性,同时使得代码更加清晰和易于理解。

public class Resource {private String url;public Resource(String url) {this.url = url;}
}public class ResourceLoader {private Resource load(String url) {// 根据前缀匹配String prefix = getPrefix(url);if (prefix.equals("http")) {// 很复杂的操作,可能此处会执行很久return new Resource(url);} else if (prefix.equals("file")) {// 很复杂的操作,可能此处会执行很久return new Resource(url);} else if (prefix.equals("classpath")) {// 很复杂的操作,可能此处会执行很久return new Resource(url);} else {return new Resource("default");}}private String getPrefix(String url) {if (url == null || "".equals(url) || url.contains(":")) {throw new ResourceLoadException("url不合法");}String[] split = url.split(":");return split[0];}
}

上述代码包含两个类:ResourceResourceLoader

  • Resource 类表示资源对象,具有一个私有的 url 字段和一个公共的构造函数。它通过构造函数接收一个 url 参数,并将其赋值给 url 字段。
  • ResourceLoader 类是一个资源加载器,它有一个私有的 load 方法用于加载资源。该方法接收一个 url 参数,根据其前缀进行匹配。根据前缀的不同,它执行不同的操作来创建并返回一个 Resource 对象。
    • load 方法中,它通过调用私有的 getPrefix 方法来获取 url 的前缀。然后,使用条件语句判断前缀是什么,并在每个分支中执行复杂的操作(可能需要执行很久)来创建一个对应的 Resource 对象。如果前缀不匹配任何条件,则创建一个默认的 Resource 对象。
    • getPrefix 方法用于从 url 中提取前缀。它首先检查 url 是否为空、空字符串或包含冒号。如果是,则抛出一个 ResourceLoadException 异常,表示 url 不合法。否则,它通过将 url 使用冒号进行分割,并返回分割后的第一个元素作为前缀。

总结:以上代码展示了一个简单的资源加载器,根据给定的 url 和其前缀,创建并返回对应的 Resource 对象。它通过条件语句进行判断和创建,没有使用工厂设计模式。然而,这种实现方式存在代码冗余和可扩展性差的问题。工厂设计模式可以用来改善这些问题。


二、简单工厂

🔺总结就是:一个工厂负责生产多个产品

1.简介

简单工厂设计模式(Simple Factory Pattern)是一种创建型设计模式,旨在通过一个工厂类来封装对象的创建过程。它属于最基本的工厂模式,虽然并不是一种正式的设计模式,但在实际开发中被广泛应用。

  • 在简单工厂模式中,存在一个具体的工厂类,负责根据客户端的需求创建不同类型的产品对象。客户端只需要提供一个参数或条件给工厂类,工厂类根据参数或条件的不同,返回相应类型的产品对象。这样,客户端与具体产品类之间解耦,不需要直接依赖具体产品的创建过程。

2.案例

public class ResourceLoadFactory {public static Resource create(String type, String url) {if (type.equals("http")) {//很复杂的操作,可能此处会执行很久return new Resource(url);} else if (type.equals("file")) {//很复杂的操作,可能此处会执行很久return new Resource(url);} else if (type.equals("classpath")) {//很复杂的操作,可能此处会执行很久return new Resource(url);} else {return new Resource("default");}}
}

其中ResourceLoadFactory充当了工厂类的角色,create方法充当了工厂方法。根据传入的type参数,create方法决定实例化并返回不同类型的Resource对象。

简单工厂模式的优点之一是将对象的创建过程集中在一个工厂类中,使得客户端代码与具体的对象创建逻辑解耦。客户端只需要调用工厂方法,并传入相应的参数即可获得所需的对象实例,而无需了解对象的具体创建细节。

3.总结

简单工厂设计模式的优点:

  1. 封装对象的创建过程:简单工厂模式将对象的创建逻辑封装在工厂类中,客户端只需调用工厂方法,而无需了解对象的具体创建过程。

  2. 解耦客户端和具体对象:客户端代码只与工厂类打交道,无需直接与具体对象类交互,从而实现了客户端代码与具体对象的解耦。

  3. 简化客户端代码:客户端只需调用工厂方法并传入相应参数,即可获得所需对象的实例,无需自行创建对象,从而简化了客户端代码。

简单工厂设计模式的缺点:

  1. 不符合开闭原则:当需要添加新的产品类型时,需要修改工厂类的代码,违反了开闭原则。这可能导致工厂类的代码过于复杂,且对于每个新的产品类型的添加都需要修改工厂类,增加了代码的维护成本。

  2. 可能过于臃肿:随着产品类型的增加,工厂类可能变得庞大而臃肿,对于复杂的产品类型结构,简单工厂模式可能无法很好地管理和创建对象。

  3. 不支持扩展性:由于工厂类集中了所有对象的创建逻辑,如果需要对不同类型的对象采取不同的创建逻辑,则无法通过简单工厂模式实现。

总结:简单工厂模式适用于创建对象的过程相对简单且不频繁变化的情况。它提供了一种简单的对象创建方式,使得客户端代码与具体对象的创建逻辑解耦。然而,它的缺点是不符合开闭原则,难以扩展和维护。在面对复杂的对象结构和频繁变化的创建逻辑时,可以考虑使用其他更灵活的创建型设计模式。

三、工厂方法

🔺总结就是:一个工厂生产一个产品

1.简介

工厂方法设计模式(Factory Method Pattern)是一种创建型设计模式,用于解决对象的创建问题。它将对象的创建延迟到子类中,通过定义一个创建对象的接口,让子类决定实例化哪个具体类。

  • **核心思想:是将对象的实例化交给子类来完成,而不是在父类中直接创建对象。**这样可以将对象的创建与使用分离,提高代码的灵活性和可扩展性。

工厂方法模式通常包含以下角色:

  1. 抽象产品(Abstract Product):定义产品的共同接口或抽象类,具体产品需要实现这个接口或继承这个抽象类。

  2. 具体产品(Concrete Product):实现抽象产品接口或继承抽象产品类,是工厂方法所创建的对象实例。

  3. 抽象工厂(Abstract Factory):定义创建产品的接口,包含创建产品的抽象方法。

  4. 具体工厂(Concrete Factory):实现抽象工厂接口,实现创建具体产品的方法。

工厂方法模式通过引入抽象工厂和具体工厂来解决直接实例化具体产品的问题。客户端代码只需要与抽象工厂进行交互,而不需要直接与具体产品类打交道。具体的产品对象由具体工厂类来创建,具体工厂类的选择由客户端来决定。

2.案例

抽象产品和具体产品:

@Data
public abstract class AbstractResource {private String url;public AbstractResource() {}public AbstractResource(String url) {this.url = url;}//子类都要实现的方法public abstract InputStream getInputStream();
}
public class FileResource extends AbstractResource {public FileResource() {super();}public FileResource(String url) {super(url);}@Overridepublic InputStream getInputStream() {return null;}
}

抽象工厂和具体工厂:

public interface IResourceFactory {public AbstractResource create(String url);
}
public class FileResourceFactory implements IResourceFactory {@Overridepublic AbstractResource create(String url) {//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......return new FileResource(url);}
}

测试:

@Slf4j
public class ResourceLoaderMethod {private IResourceFactory resourceFactory;private static Map<String, IResourceFactory> resourceFactoryCache = new HashMap<>(8);static {//在类加载的时候/起一个定时器,定时读取配置文件InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("resourceFactory.properties");Properties properties = null;try {properties = new Properties();properties.load(inputStream);} catch (IOException e) {throw new RuntimeException(e);}Set<Map.Entry<Object, Object>> entries = properties.entrySet();Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<Object, Object> next = iterator.next();String prefixKey = next.getKey().toString();String className = next.getValue().toString();Class<?> clazz = null;try {clazz = Class.forName(className);IResourceFactory instance = (IResourceFactory) clazz.getConstructor().newInstance();resourceFactoryCache.put(prefixKey, instance);} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |InvocationTargetException e) {throw new RuntimeException(e);}}}private AbstractResource load(String url) {String prefix = getPrefix(url);return resourceFactoryCache.get(prefix).create(url);}private String getPrefix(String url) {if (url == null || "".equals(url) || url.contains(":")) {return "default";}String[] split = url.split(":");return split[0];}public static void main(String[] args) {ResourceLoaderMethod rlm = new ResourceLoaderMethod();AbstractResource load = rlm.load("file:user/inter");System.out.println("load.getUrl() = " + load.getUrl());}
}

这段代码展示了使用抽象工厂设计模式的资源加载器实现。

抽象产品和具体产品部分:

  • AbstractResource 是抽象产品类,它包含了一个 url 字段,并定义了一个抽象方法 getInputStream()
  • FileResource 是具体产品类,它继承自 AbstractResource,实现了抽象方法 getInputStream()

抽象工厂和具体工厂部分:

  • IResourceFactory 是抽象工厂接口,它定义了一个方法 create(),用于创建抽象产品 AbstractResource 对象。
  • FileResourceFactory 是具体工厂类,实现了 IResourceFactory 接口。在 create() 方法中,它通过复杂的逻辑创建一个 FileResource 对象,并将其返回。

测试部分:

  • ResourceLoaderMethod 类中包含了一个静态的 resourceFactoryCache 缓存,用于存储不同前缀对应的具体工厂对象。
  • 在静态代码块中,通过读取配置文件 resourceFactory.properties,获取了具体工厂类的映射关系,并将其实例化放入缓存中。
  • load() 方法根据传入的 URL 获取前缀,并从 resourceFactoryCache 缓存中获取对应的具体工厂对象,然后调用其 create() 方法创建抽象产品对象。
  • getPrefix() 方法用于从 URL 中提取前缀,如果 URL 为空、空字符串或包含冒号,则返回默认前缀。
  • main() 方法中,创建 ResourceLoaderMethod 对象,并通过调用 load() 方法加载资源。最后打印出加载的资源的 URL。

通过这段代码,资源加载器实现了抽象工厂设计模式。客户端只需与抽象工厂接口 IResourceFactory 进行交互,通过调用其 create() 方法,由具体工厂类根据传入的 URL 创建相应的具体产品对象。这样可以实现客户端与具体产品类的解耦,提高了代码的灵活性和可维护性。

3.总结

工厂方法模式(Factory Method Design Pattern)的优点:

  1. 符合开闭原则:工厂方法模式通过将对象的创建委托给子类,实现了对扩展开放、对修改关闭。通过添加新的具体工厂子类,可以轻松地新增产品类型,而无需修改现有的代码。

  2. 提供了灵活性:工厂方法模式将对象的创建委托给子类,使得客户端可以通过选择不同的具体工厂子类来获取不同类型的对象实例。这提供了灵活性,使得系统能够根据需求动态地创建所需的对象。

  3. 封装了对象的创建逻辑:工厂方法模式将对象的创建逻辑封装在具体工厂子类中,使得客户端代码与具体对象的创建过程解耦。客户端只需关心使用工厂方法获得对象,无需关心对象的具体创建细节。

  4. 可以应对复杂的对象创建逻辑:工厂方法模式适用于需要根据不同的条件或参数来创建对象的情况。每个具体工厂子类可以实现自己特定的对象创建逻辑,使得系统能够处理复杂的对象创建需求。

工厂方法模式的缺点:

  1. 类的数量增加:引入工厂方法模式会增加系统中类的数量,每个具体产品对应一个具体工厂类,这可能会增加代码的复杂性和理解的难度。

  2. 客户端需要知道具体工厂类:客户端需要知道具体工厂类才能创建相应的对象,这增加了客户端代码的依赖性。如果客户端不知道具体工厂类,需要进一步结合其他模式(如抽象工厂模式)来解决这个问题。

总结:工厂方法模式提供了一种灵活的对象创建机制,能够根据具体需求选择不同的具体工厂子类来创建对象。它符合开闭原则,可以应对复杂的对象创建逻辑。然而,它可能会增加系统中的类数量,并要求客户端知道具体工厂类。根据具体情况,可以考虑使用工厂方法模式来实现灵活、可扩展的对象创建。

四、抽象工厂

🔺总结就是:一个工厂生产一组产品线

1.简介

抽象工厂设计模式(Abstract Factory Pattern)是一种创建型设计模式,用于创建一系列相关或相互依赖的对象。它提供了一个抽象工厂接口,允许客户端使用抽象接口创建一组相关的产品对象,而无需关心具体的产品类。

  • 核心思想:是将对象的创建委托给一个抽象工厂接口,具体的工厂类实现这个接口并负责创建一族相关的产品。每个具体工厂类负责创建特定的产品,这些产品在接口层面上有相关性。

抽象工厂模式通常包含以下角色:

  1. 抽象工厂(Abstract Factory):定义创建一族产品的抽象接口。它通常包含多个用于创建不同产品的抽象方法。

  2. 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建一族具体产品对象。

  3. 抽象产品(Abstract Product):定义产品的共同接口或抽象类。具体产品类需要实现这个接口或继承这个抽象类。

  4. 具体产品(Concrete Product):实现抽象产品接口或继承抽象产品类,是具体工厂所创建的对象实例。

抽象工厂模式通过引入抽象工厂和具体工厂来解决直接实例化具体产品的问题。客户端代码只需要与抽象工厂进行交互,而不需要直接与具体产品类打交道。具体的产品对象由具体工厂类来创建,具体工厂类的选择由客户端来决定。

2.案例

抽象产品和具体产品:

public interface IResource {//子类都要实现的方法InputStream getInputStream();
}
@Data
public abstract class AbstractVideoResource implements IResource {private String url;public AbstractVideoResource() {}public AbstractVideoResource(String url) {this.url = url;}public void transformMp4() {System.out.println("视频资源组共有方法-transformMp4()");}
}
@Data
public abstract class AbstractTextResource implements IResource {private String url;public AbstractTextResource() {}public AbstractTextResource(String url) {this.url = url;}public void transformUtf8() {System.out.println("文本资源组共有方法-transformUtf8()");}
}
@Data
public abstract class AbstractPictureResource implements IResource {private String url;public AbstractPictureResource() {}public AbstractPictureResource(String url) {this.url = url;}public void transformJpg() {System.out.println("图片资源组共有方法-transformJpg()");}
}
public class FileTextResource extends AbstractTextResource {@Overridepublic InputStream getInputStream() {return null;}
}
public class FileVideResource extends AbstractVideoResource {@Overridepublic InputStream getInputStream() {return null;}
}
public class FilePictureResource extends AbstractPictureResource {public FilePictureResource() {super();}public FilePictureResource(String url) {super(url);}@Overridepublic InputStream getInputStream() {return null;}
}
public class HttpPictureResource extends AbstractPictureResource {public HttpPictureResource() {super();}public HttpPictureResource(String url) {super(url);}@Overridepublic InputStream getInputStream() {return null;}
}
public class HttpTextResource extends AbstractPictureResource {public HttpTextResource() {super();}public HttpTextResource(String url) {super(url);}@Overridepublic InputStream getInputStream() {return null;}
}
public class HttpVideoResource extends AbstractPictureResource {public HttpVideoResource() {super();}public HttpVideoResource(String url) {super(url);}@Overridepublic InputStream getInputStream() {return null;}
}

抽象工厂和具体工厂:

public interface IResourceFactory {public AbstractPictureResource create(String url);/*** 加载图片资源的工厂方法** @param url 给的的资源url* @return 图片资源*/public AbstractPictureResource loadPicture(String url);/*** 加载视频资源的工厂方法** @param url 给的的资源url* @return 视频资源*/public AbstractVideoResource loadVideo(String url);/*** 加载文本资源的工厂方法** @param url 给的的资源url* @return 文本资源*/public AbstractTextResource loadText(String url);
}public abstract class AbstractResourceFactory implements IResourceFactory {//可提供共享的模板方法、资源等
}public class FileResourceFactory extends AbstractResourceFactory {@Overridepublic AbstractPictureResource create(String url) {//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......return new FilePictureResource(url);}@Overridepublic AbstractPictureResource loadPicture(String url) {return null;}@Overridepublic AbstractVideoResource loadVideo(String url) {return null;}@Overridepublic AbstractTextResource loadText(String url) {return null;}
}
public class HttpResourceFactory extends AbstractResourceFactory {@Overridepublic AbstractPictureResource create(String url) {//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......//很复杂的逻辑......return new HttpPictureResource(url);}@Overridepublic AbstractPictureResource loadPicture(String url) {return null;}@Overridepublic AbstractVideoResource loadVideo(String url) {return null;}@Overridepublic AbstractTextResource loadText(String url) {return null;}
}

测试:

@Slf4j
public class ResourceLoaderMethod {private IResourceFactory resourceFactory;private static Map<String, IResourceFactory> resourceFactoryCache = new HashMap<>(8);static {//在类加载的时候/起一个定时器,定时读取配置文件InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("resourceFactory.properties");Properties properties = null;try {properties = new Properties();properties.load(inputStream);} catch (IOException e) {throw new RuntimeException(e);}Set<Map.Entry<Object, Object>> entries = properties.entrySet();Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<Object, Object> next = iterator.next();String prefixKey = next.getKey().toString();String className = next.getValue().toString();Class<?> clazz = null;try {clazz = Class.forName(className);IResourceFactory instance = (IResourceFactory) clazz.getConstructor().newInstance();resourceFactoryCache.put(prefixKey, instance);} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |InvocationTargetException e) {throw new RuntimeException(e);}}}private AbstractPictureResource load(String url) {String prefix = getPrefix(url);return resourceFactoryCache.get(prefix).create(url);}private String getPrefix(String url) {if (url == null || "".equals(url) || url.contains(":")) {return "default";}String[] split = url.split(":");return split[0];}public static void main(String[] args) {ResourceLoaderMethod rlm = new ResourceLoaderMethod();AbstractPictureResource load = rlm.load("file:user/inter");System.out.println("load.getUrl() = " + load.getUrl());}
}

这段代码展示了抽象工厂设计模式的实现。

抽象产品和具体产品部分:

  • IResource 是抽象产品接口,定义了一个 getInputStream() 方法。
  • AbstractVideoResourceAbstractTextResourceAbstractPictureResource 是抽象产品的具体实现,它们分别继承了 IResource 接口,并包含了一些额外的共有方法。
  • FileTextResourceFileVideoResourceFilePictureResourceHttpPictureResourceHttpTextResourceHttpVideoResource 是具体产品类,分别继承了抽象产品的具体实现类,并实现了 getInputStream() 方法。

抽象工厂和具体工厂部分:

  • IResourceFactory 是抽象工厂接口,它定义了创建产品的抽象方法以及加载具体产品的工厂方法。
  • AbstractResourceFactory 是抽象工厂的具体实现,它继承了 IResourceFactory 接口,可以提供共享的模板方法和资源等。
  • FileResourceFactoryHttpResourceFactory 是具体工厂类,分别继承了抽象工厂的具体实现类,实现了创建具体产品和加载具体产品的方法。

测试部分:

  • ResourceLoaderMethod 类中的 resourceFactoryCache 是一个静态缓存,用于存储不同前缀对应的具体工厂对象。在类加载时,通过读取配置文件,动态创建具体工厂对象,并将其放入缓存中。
  • load() 方法根据传入的 URL 获取前缀,并从 resourceFactoryCache 缓存中获取对应的具体工厂对象。然后,通过具体工厂对象调用 create() 方法创建抽象产品对象。
  • getPrefix() 方法用于从 URL 中提取前缀,如果 URL 为空、空字符串或包含冒号,则返回默认前缀。

main() 方法中,创建了 ResourceLoaderMethod 对象,并通过调用 load() 方法加载资源。最后打印出加载的资源的 URL。

这段代码实现了抽象工厂设计模式,通过抽象产品、具体产品、抽象工厂和具体工厂的定义,将产品的创建过程从客户端代码中解耦出来。客户端只需要与抽象工厂进行交互,而不需要直接依赖具体产品类。这提高了代码的灵活性、可扩展性和可维护性。

3.总结

抽象工厂模式(Abstract Factory Design Pattern)是一种创建型设计模式,它提供一个接口或抽象类作为工厂,允许客户端使用该接口或抽象类来创建一系列相关或依赖的对象。抽象工厂模式旨在提供一种创建对象族的方式,而无需指定具体的类。

抽象工厂模式的优点:

  1. 提供了一种统一的接口:抽象工厂模式定义了一组相关对象的创建接口或抽象类,使得客户端可以通过统一的接口来创建一系列相关的产品对象,而无需关心具体的实现类。

  2. 实现了产品族的概念:抽象工厂模式支持一次性创建一整个产品族。产品族是指由相互关联或依赖的一组相关对象组成的集合。通过抽象工厂模式,可以一次性创建一整个产品族,确保这些产品对象之间相互匹配、协同工作。

  3. 符合开闭原则:抽象工厂模式使得新增产品族变得相对容易。通过添加新的具体工厂类和产品类,可以扩展抽象工厂模式,而无需修改现有的代码,符合开闭原则。

  4. 封装了对象的创建细节:抽象工厂模式将对象的创建过程封装在具体工厂类中,使得客户端无需关心对象的具体创建细节,从而提高了代码的封装性和可维护性。

抽象工厂模式的缺点:

  1. 难以支持新种类的产品:当需要添加新种类的产品时,需要修改抽象工厂接口或抽象类,以及所有的具体工厂类,这可能对现有的代码和实现造成一定的影响。

  2. 增加了系统的复杂性:引入抽象工厂模式会增加系统中的类和对象的数量,这增加了系统的复杂性和理解的难度。

总结:抽象工厂模式提供了一种创建一系列相关或依赖对象的方式,通过一组接口或抽象类定义了对象的创建过程,实现了产品族的概念。它提供了一种统一的接口,封装了对象的创建细节,并符合开闭原则。然而,抽象工厂模式难以支持新种类的产品,并增加了系统的复杂性。根据具体需求,可以考虑使用抽象工厂模式来创建一系列相关的对象。

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

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

相关文章

【计算机视觉 | 图像分类】arxiv 计算机视觉关于图像分类的学术速递(7 月 17 日论文合集)

文章目录 一、分类|识别相关(11篇)1.1 Multimodal Distillation for Egocentric Action Recognition1.2 Dual-Query Multiple Instance Learning for Dynamic Meta-Embedding based Tumor Classification1.3 Interactive Spatiotemporal Token Attention Network for Skeleton-…

【面试官】说说你对闭包的理解

说说你对闭包的理解 闭包是什么闭包的三个特性优缺点应用场景javascript的垃圾回收原理:通常情况下有两种实现方式垃圾回收原理的缺陷GC优化策略 闭包是什么 闭包就是能够读取其他函数内部变量的函数闭包是指有权访问另一个函数作用域中变量的函数&#xff0c;创建闭包的最常见…

基于ClickHouse解决活动海量数据问题 | 京东云技术团队

1、背景 魔笛活动平台要记录每个活动的用户行为数据&#xff0c;帮助客服、运营、产品、研发等快速处理客诉、解决线上问题并进行相关数据分析和报警。可以预见到需要存储和分析海量数据&#xff0c;预估至少几十亿甚至上百亿的数据量&#xff0c;所以需要选择一款能存储海量数…

会议音响系统麦克风阵列波束形成算法C语言实现

一 应用麦克风阵列波束成形算法做的项目产品 二 麦克风波束形成技术应用领域? 麦克风波束形成技术是一种利用多个麦克风阵列来实现声音定向捕捉和增强的技术。通过对多个麦克风信号进行处理和合成,可以使麦克风系统在特定方向上具有更高的灵敏度和抑制非期望方向上的噪…

机器学习(13)--支持向量机

目录 一、支持向量机概述 二、Sklearn中的SVM概述 三、线性SVM损失函数 四、sklearn中进行可视化 1、导入模块 2、实例化数据集&#xff0c;可视化 3、网格点制作 4、建立模型并绘制决策边 目录 一、支持向量机概述 二、Sklearn中的SVM概述 三、线性SVM损失函数 四…

机器学习技术(三)——机器学习实践案例总体流程

机器学习实践案例总体流程 文章目录 机器学习实践案例总体流程一、引言二、案例1、决策树对鸢尾花分类1.数据来源2.数据导入及描述3.数据划分与特征处理4.建模预测 2、各类回归波士顿房价预测1.案例数据2.导入所需的包和数据集3.载入数据集&#xff0c;查看数据属性&#xff0c…

四个按键控制led的四种变化(按键控制led)(附源码)

文章目录 一、实验任务二、系统框图三、代码实现四、引脚分配五、总结 一、实验任务 使用开发板上的四个按键控制四个LED灯。按下不同的按键时&#xff0c;四个LED灯显示不同效果。本实验是在EP4CE6F17C8开发板上实现&#xff0c;仿真请用modelsim Altera 二、系统框图 三、代…

揭秘GPT-4;Adobe Firefly AI 扩大测试规模

&#x1f989; AI新闻 &#x1f680; Adobe Firefly AI 扩大测试规模&#xff0c;支持100多种语言的输入 摘要&#xff1a;Adobe宣布扩大测试规模&#xff0c;Adobe Firefly AI现在支持100多种语言的 prompts 输入。网页测试版Firefly已经扩充了罗马尼亚语等多种语言&#xf…

MacOS使用USB接口与IPhone进行Socket通信

演示效果如下: 开源地址: GitHub - rsms/peertalk: iOS and Mac Cocoa library for communicating over USB 克隆源码: git clone https://github.com/rsms/peertalk.git 克隆后打开peertalk然后启动xcode工程 先启动MacOS服务端工程,再启动iOS客户端工程 客户端 服务端

微信小程序安装和使用 Vant Weapp 组件库

微信小程序安装和使用 Vant Weapp 组件库 1. Vant Weapp 介绍2. Vant Weapp 的 安装2.1. 通过npm安装2.2. 构建npm2.3. 修改 app.json2.4. 修改 project.congfig.json2.5. 测试一下&#xff0c;使用Vant Weapp提供的组件 1. Vant Weapp 介绍 Vant 是一个轻量、可靠的移动端组件…

极智开发 | ubuntu交叉编译aarch64 boost

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍一下 ubuntu交叉编译aarch64 boost。 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xf…

opencv -10 基础运算之 图像加权和(图像融合图像修复视频合成)

什么是图像加权和&#xff1f; 所谓图像加权和&#xff0c;就是在计算两幅图像的像素值之和时&#xff0c;将每幅图像的权重考虑进来&#xff0c;可以用公式表示为&#xff1a; dst saturate(src1 &#x1d6fc; src2 &#x1d6fd; &#x1d6fe;)式中&#xff0c;satu…

C# Linq 详解二

目录 概述 七、OrderBy 八、OrderByDescending 九、Skip 十、Take 十一、Any 十二、All C# Linq 详解一 1.Where 2.Select 3.GroupBy 4.First / FirstOrDefault 5.Last / LastOrDefault C# Linq 详解二 1.OrderBy 2.OrderByDescending 3.Skip 4.Take 5.Any 6.All C#…

arm day2

汇编实现1到100的累加 .text .global _start_start:mov r0,#0loop:add r0,#1add r1,r0cmp r0,#100blne loopstop:b stop结果为0x13ba等于5050

python的魔法函数

一、介绍 在Python中&#xff0c;魔法函数是以双下划线__开头和结尾的特殊函数。它们在类定义中用于实现特定的行为&#xff0c;例如运算符重载、属性访问、迭代等。 以下是一些常见的Python魔法函数&#xff1a; __init__: 这是一个特殊的构造函数&#xff0c;在创建类的实例…

Web_php_include

代码审计 进入环境&#xff0c;根据题目的提示&#xff0c;本题考察文件包含漏洞 <?php show_source(__FILE__); echo $_GET[hello]; $page$_GET[page]; while (strstr($page, "php://")) {$pagestr_replace("php://", "", $page); } incl…

解决Ruoyi单体版本集成Echarts多图表时在Tab模式下不展示问题

目录 背景 一、Tab拆分后无法展示 1、环境简介 2、原始报表功能说明 3、tab切分遇到的问题 二、问题分析及解决 1、问题分析 2、问题解决 3、初始化时图表渲染 4、Tab切换时重渲 总结 背景 最近在使用ruoyi的单体化版本进行Echarts多图表展示时遇到一个问题&#xff0c;r…

苍穹外卖day03——菜品管理业务代码开发

目录 公共字段自动填充——问题分析和实现思路 公共字段自动填充——代码实现(1) 公共字段自动填充——代码实现完善(2) 新增菜品——需求分析与设计 产品原型 ​编辑 接口设计 ​编辑 数据库设计 新增菜品——代码开发1(文件上传接口) 配置文件 Controller层代码 前后…

Net HTTP 概述

Net HTTP 概述 状态码字段Get/Post HTTP (HyperText Transfer Protocol) : 超文本传输协议 超文本 : 比文本更丰富传输 : 双方通信协议 : 双方的约定 状态码 200 : OK , 一切成功302 : 临时重定向 , 访问另一个 URL404 : 服务器不存在该 URL502 : 网关 , 代理错误503 : 当前…

Java经典面试解析:服务器卡顿、CPU飙升、接口负载剧增

01 线上服务器CPU飙升&#xff0c;如何定位到Java代码 解决这个问题的关键是要找到Java代码的位置。下面分享一下排查思路&#xff0c;以CentOS为例&#xff0c;总结为4步。 第1步&#xff0c;使用top命令找到占用CPU高的进程。 第2步&#xff0c;使用ps –mp命令找到进程下…