5、设计模式之工厂模式

news2024/9/23 12:22:07

工厂模式

    • 5.1 案例引入
    • 5.2简单工厂模式
      • 5.2.1 简单工厂模式结构
      • 5.2.2 实现
      • 5.2.3 优缺点分析
    • 5.3 工厂方法模式
      • 5.3.1 工厂方法模式结构
      • 5.3.2 新需求
      • 5.3.3 思路
      • 5.3.4 实现
      • 5.3.5 优缺点分析
    • 5.4 抽象工厂
      • 5.4.1 介绍
      • 5.4.2 结构
      • 5.4.3 实现
      • 5.4.4 使用场景
    • 5.5 工厂+配置文件实现解耦
    • 相关文章索引
    • 后记

5.1 案例引入

 需求:设计一个披萨订购系统。
 设计一个抽象披萨类(Coffee),并定义其两个子类(奶酪披萨【CheessPizza】和水果披萨【FruitPizza】);再设计一个披萨店类(PizzaStore),披萨店具有点披萨的功能。
 类图如下:
在这里插入图片描述
 代码如下:
Pizza类:

package d3_factory.t1_simple.before;
/**
 * 披萨类 - 抽象
 * @author luxianghai
 *
 */
public abstract class Pizza {
	// 咖啡名
	protected String name;
	
	// 准备工作
	protected abstract void prepare();
	
	// 烘烤
	protected void bake() {
		System.out.println(name + " - 烘烤");
	}
	
	protected void cut() {
		System.out.println(name + " - 切割");
	}
	protected void box() {
		System.out.println(name + " - 打包");
	}
}

CheesePizza类

package d3_factory.t1_simple.before;
/**
 * 奶酪披萨
 * @author luxianghai
 *
 */
public class CheesePizza extends Pizza {
	
	public CheesePizza() {
		super.name = "奶酪披萨";
	}
	
	@Override
	protected void prepare() {
		System.out.println(super.name);		
		System.out.println("准备奶酪中...");		
	}
}

FruitPizza类

package d3_factory.t1_simple.before;
/**
 * 水果披萨
 * @author luxianghai
 *
 */
public class FruitPizza extends Pizza {

	public FruitPizza() {
		super.name = "水果披萨";
	}
	
	@Override
	protected void prepare() {
		System.out.println(super.name);
		System.out.println("准备水果中...");
	}

}

PizzaSotre类

package d3_factory.t1_simple.before;

import java.util.Scanner;

/**
 * 披萨店
 * @author luxianghai
 *
 */
public class PizzaStore {
	
	public PizzaStore() {
		orderPizza();
	}
	
	/**
	 * 点披萨
	 */
	private void orderPizza() {
		Pizza pizza = null;
		String type = ""; // 披萨类型
		do {
			type = getType();
			if ( "奶酪披萨".equals(type) ) {
				pizza = new CheesePizza();
			} else if ( "水果披萨".equals(type) ) {
				pizza = new FruitPizza();
			} else {
				System.out.println("退出!!!");
				break;
			}
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		} while(true);
	}
	/**
	 * 获取披萨类型
	 * @return
	 */
	private String getType() {
		System.out.println("输入披萨名:");
		Scanner scan = new Scanner(System.in);
		return scan.next();
	}
}

测试

package d3_factory.t1_simple.before;

public class Client {

	public static void main(String[] args) {
		new PizzaStore();
	}
}

 优缺点分析

  1. 优点是比较好理解,简单易操作。
  2. 缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
  3. 比如我们这时要新增加一个Pizza的种类(ChickenPizza鸡肉披萨),我们需要在 PizzaStore的orderPizza方法中添加else if来进行判断

 改进思路分析:

  • 分析:修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizza的代码,往往有多处。
  • 思路:把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可,其它有创建到Pizza对象的代码就不需要修改了 --> 简单工厂模式

5.2简单工厂模式

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

5.2.1 简单工厂模式结构

 简单工厂模式的结构:

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

5.2.2 实现

 使用简单工厂对 5.1小节 中的案例进行改进,我们只需对PizzaStore做修改(把创建对象的语句提取到工厂中),并创建一个简单工厂SimpleFactory类即可,代码如下:
SimpleFactory.java

package d3_factory.t1_simple.after1;
/**
 * 简单工厂类
 * @author luxianghai
 *
 */
public class SimpleFactory {
	
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new CheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new FruitPizza();
		}
		return pizza;
	}
}

PizzaStore

package d3_factory.t1_simple.after2;

import java.util.Scanner;

/**
 * 披萨店
 * @author luxianghai
 *
 */
public class PizzaStore {
	
	public PizzaStore() {
		orderPizza();
	}
	
	/**
	 * 点披萨
	 */
	private void orderPizza() {
		String type = ""; // 披萨类型
		do {
			type = getType();
			Pizza pizza = SimpleFactory.createPizza(type);
			if(null != pizza) {
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				System.out.println("退出!!!");
				break;
			}
		} while(true);
	}
	/**
	 * 获取披萨类型
	 * @return
	 */
	private String getType() {
		String type = "";
		Scanner scan = null;
		try {
			System.out.println("输入披萨名:");
			scan = new Scanner(System.in);
			type = scan.next();
		} finally {
			if ( null != scan ) {
				scan.close();
			}
		}
		return type;
	}
	
}

 此时如果我们新增一个鸡肉披萨,只需创建新类ChickenPizza,然后在SimpleFactory添加一个判断即可,就不需要修改客户端了,更容易扩展了:
ChickenPizza

package d3_factory.t1_simple.after2;
/**
 * 鸡肉披萨
 * @author luxianghai
 *
 */
public class ChickenPizza extends Pizza {
	
	public ChickenPizza() {
		super.name = "鸡肉披萨";
	}
	@Override
	protected void prepare() {
		System.out.println("鸡肉披萨");
		System.out.println("准备鸡肉中...");
	}
}

SimpleFactory

package d3_factory.t1_simple.after2;
/**
 * 简单工厂类
 * @author luxianghai
 *
 */
public class SimpleFactory {
	
	public static Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new CheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new FruitPizza();
		} else if ( "鸡肉披萨".equals(type) ) {
			pizza = new FruitPizza();
		}
		return pizza;
	}
}

 如此边添加了一个新的披萨种类

5.2.3 优缺点分析

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

5.3 工厂方法模式

定义一个用于创建对象的接口或抽象类,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

5.3.1 工厂方法模式结构

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

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

5.3.2 新需求

披萨项目新的需求:客户在点披萨时,可以根据所在地点不同的披萨,比如 北京的水果pizza、北京的奶酪pizza 或者是伦敦的奶酪pizza、伦敦的水果pizza。

5.3.3 思路

 思路1:使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory 等等.从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
 思路2:使用工厂方法模式

5.3.4 实现

 类图如下:
在这里插入图片描述
 代码如下:
抽象产品

/**
 * 披萨类 - 抽象产品
 * @author luxianghai
 *
 */
public abstract class Pizza {
	// 咖啡名
	protected String name;
	
	// 准备工作
	public abstract void prepare();
	
	// 烘烤
	public void bake() {	
		System.out.println(name + " - 烘烤");
	}
	
	public void cut() {
		System.out.println(name + " - 切割");
	}
	public void box() {
		System.out.println(name + " - 打包");
	}
}

具体产品

/**
 * 奶酪披萨 – 具体产品
 * @author luxianghai
 *
 */
public class BJCheesePizza extends Pizza {
	
	public BJCheesePizza() {
		super.name = "北京奶酪披萨";
	}
	
	@Override
	public void prepare() {
		System.out.println(super.name);		
		System.out.println("准备奶酪中...");		
	}
}

/**
 * 水果披萨 – 具体产品
 * @author luxianghai
 *
 */
public class BJFruitPizza extends Pizza {

	public BJFruitPizza() {
		super.name = "北京水果披萨";
	}
	
	@Override
	public void prepare() {
		System.out.println(super.name);
		System.out.println("准备水果中...");
	}

}

/**
 * 奶酪披萨 – 具体产品
 * @author luxianghai
 *
 */
public class LDCheesePizza extends Pizza {
	
	public LDCheesePizza() {
		super.name = "伦敦奶酪披萨";
	}
	
	@Override
	public void prepare() {
		System.out.println(super.name);		
		System.out.println("准备奶酪中...");		
	}
}

/**
 * 水果披萨  – 具体产品
 * @author luxianghai
 *
 */
public class LDFruitPizza extends Pizza {

	public LDFruitPizza() {
		super.name = "伦敦水果披萨";
	}
	
	@Override
	public void prepare() {
		System.out.println(super.name);
		System.out.println("准备水果中...");
	}

}

抽象工厂

import java.util.Scanner;

import d3_factory.t2_factorymethod.pizza.*;

/**
 * 抽象工厂
 * @author luxianghai
 *
 */
public abstract class PizzaStore {
	// 工厂子类需要实现的方法 - 常用创建具体产品
	public abstract Pizza createPizza(String type);
	
	public PizzaStore() {
		orderPizza();
	}
	
	/**
	 * 点披萨
	 */
	private void orderPizza() {
		Pizza pizza = null;
		String type = ""; // 披萨类型
		do {
			type = getType();
			pizza = createPizza(type);
			if ( null != pizza ) {
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				break;
			}
		} while(true);
	}
	/**
	 * 获取披萨类型
	 * @return
	 */
	private String getType() {
		System.out.println("输入披萨名:");
		Scanner scan = new Scanner(System.in);
		return scan.next();
	}
	
}

具体工厂

/**
 * 伦敦披萨 - 具体工厂
 * @author luxianghai
 *
 */
public class LDPizzaStore extends PizzaStore {

	@Override
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new LDCheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new LDFruitPizza();
		}
		return pizza;
	}

}

/**
 * BJ披萨 - 具体工厂
 * @author luxianghai
 *
 */
public class BJPizzaStore extends PizzaStore {

	@Override
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new BJCheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new BJFruitPizza();
		}
		return pizza;
	}
}

测试

public class Client {

	public static void main(String[] args) {
		
		//new BJPizzaStore();
		new LDPizzaStore();
	}
}

5.3.5 优缺点分析

 工厂方法就是对简单工厂在进行一次封装而已,由于多态性使得工厂方法仍然保持了简单工厂的优点。
 缺点:仍然违反开闭原则

5.4 抽象工厂

5.4.1 介绍

 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
 抽象工厂模式就是将工厂方法改进了一下,使其能够管理多个抽象产品。
 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

5.4.2 结构

 抽象工厂模式的主要角色如下:

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

5.4.3 实现

我们只需要保留下工厂方法代码中的抽象产品和具体产品即可,其他的代码均删除,添加以下代码:
抽象工厂

/**
 * 抽象工厂
 * @author luxianghai
 *
 */
public interface AbsFactory {
	
	Pizza createPizza(String type);
	
}

具体工厂

/**
 * BJ披萨 - 具体工厂
 * @author luxianghai
 *
 */
public class BJPizzaStore implements AbsFactory {

	@Override
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new BJCheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new BJFruitPizza();
		}
		return pizza;
	}
}

/**
 * 伦敦披萨 - 具体工厂
 * @author luxianghai
 *
 */
public class LDPizzaStore implements AbsFactory {

	@Override
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if ( "奶酪披萨".equals(type) ) {
			pizza = new LDCheesePizza();
		} else if ( "水果披萨".equals(type) ) {
			pizza = new LDFruitPizza();
		}
		return pizza;
	}
}

业务类

/**
 * 业务类
 * @author luxianghai
 *
 */
public class PizzaStore {

	private AbsFactory factory;
	
	public PizzaStore() {
		
	}
	
	public void setFactory(AbsFactory factory) {
		this.factory = factory;
		orderPizza();
	}
	
	/**
	 * 点披萨
	 */
	private void orderPizza() {
		Pizza pizza = null;
		String type = ""; // 披萨类型
		do {
			type = getType();
			pizza = factory.createPizza(type);
			if ( null != pizza ) {
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				break;
			}
		} while(true);
	}
	/**
	 * 获取披萨类型
	 * @return
	 */
	private String getType() {
		System.out.println("输入披萨名:");
		Scanner scan = new Scanner(System.in);
		return scan.next();
	}
}

测试

public class Client {

	public static void main(String[] args) {
		
		PizzaStore store = new PizzaStore();
//		store.setFactory(new LDPizzaStore());
		store.setFactory(new LDPizzaStore());
	}
}

 此时的类图如下:在这里插入图片描述

5.4.4 使用场景

  1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
  4. 如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

5.5 工厂+配置文件实现解耦

 简单工厂+配置文件解除耦合
可以通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件中的全类名,并创建对象进行存储,客户端如果需要对象,直接进行获取即可。
第一步:创建配置文件
resources/bean.properties 文件内容

ChickenPizza=d3_factory.t4_config_factory.ChickenPizza
FruitPizza=d3_factory.t4_config_factory.FruitPizza

第二步:创建简单工厂

package d3_factory.t4_config_factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import java.util.Set;

public class SimpleFactory {
	
	// 加载配置文件 - 获取配置文件中配置的全类名,通过反射技术来创建对象
	// 1.定义容器来存储Pizza对象
	private static HashMap<String, Pizza> map ;
	
	static {
		map = new HashMap<String, Pizza>();
		// 1.创建Properties对象
		Properties properties = new Properties();
		// 2.读取配置文件
		InputStream is = SimpleFactory.class.getClassLoader().getResourceAsStream("bean.properties");
		try {
			// 3.加载配置文件
			properties.load(is);
			// 获取 properties 中所有的键的 Set 集合
			Set<Object> keys =  properties.keySet();
			for ( Object key: keys ) {
				// 获取键对应的值
				String className = properties.getProperty((String)key);
				// 通过反射技术根据全类名创建对象
				Class clazz = Class.forName(className);
				Pizza pizza = (Pizza)clazz.newInstance();
				map.put((String)key, pizza);
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 根据名称获取对象
	 * @param name
	 * @return
	 */
	public static Pizza createPizza(String name) {
		return map.get(name);
	}
}

相关文章索引

设计模式概述
UML类图
软件设计原则
单例设计模式


后记

我水平有限,错误难免,还望各位加以指正。

本文内容到此结束,感谢您的阅读!!!如果内容对你有帮助的话,记得给我三连丫(点赞、收藏、关注)

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

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

相关文章

【Vue】pc和移动端网页样式适配

在下面环节会讲解怎么做pc和移动端网页样式适配。 在当下有两种实现样式适配的&#xff1a;JS 适配方案和CSS 媒体查询适配。下面会具体讲解一下代码该怎么写。 &#x1f64f; 希望该文章能帮助到你。 1. JS 适配方案 比如在src/router/index.vue文件中有一个统一的Layout组件包…

《机器学习实战》9.树回归

目录 树回归 1 复杂数据的局部性建模 2 连续和离散型特征的树的构建 3 将CART算法用于回归 3.1 构建树 3.2 运行代码 4 树剪枝 4.1 预剪枝 4.2 后剪枝 5 模型树 6 示例&#xff1a;树回归与标准回归的比较 7 使用python的Tkinter库创建GUI 7.1 用Tkinter创建GUI …

UG旋钮盖模具设计与加工

文章目录三维造型设计创建草图旋转拉伸拉伸求差圆周阵列倒圆抽壳二板模模具设计分型面初始化项目定义模具坐标定义成形镶件定义一模四腔的布局创建型芯和型腔检测区域创建区域和分型线创建分型面创建型芯和型腔加载模架创建模架添加标准件添加定位圈添加浇口套添加旋钮盖顶杆修…

【JavaScript】浏览器调试控制台console的功能有了解多少

在我们学会JavaScript编程以后&#xff0c;编程调试通常使用console.log() &#xff0c;那有没有想过&#xff0c;console除了log&#xff0c;还有很多是没有用到的&#xff0c;久而久之&#xff0c;就忘记了怎么用&#xff0c;接下来熟悉一下&#xff0c;温故而知新&#xff0…

网页大作业代码自取

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

Red Eye Camera开发日记之API 移植I2C 和关键接口函数

API 说明文件里面有官方的移植指导&#xff0c;但我觉得可以把重点放在与 MLX90640 具体操作有关的几个函数上&#xff0c;而与标准 I2C 相关的函数和文件结构还是按照自己习惯的套路实现。这样更符合我们开发人员的可控性的习惯。步骤如下&#xff1a; 建立标准 I2C 文件 IIC…

第P9周:YOLOv5-Backbone模块实现

● &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 ● &#x1f366; 参考文章&#xff1a;Pytorch实战 | 第P9周&#xff1a;YOLOv5-Backbone模块实现(训练营内部成员可读) ● &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 说明&…

电脑技巧:推荐4个冷门且功能非常强大的效率工具

目录 1、Seafile 企业云盘神器 2、PPSSPP PSP模拟器神器 3、按键精灵 键盘鼠标模拟神器 4、BenVista PhotoZoom Pro 图片无损放大神器 今天给大家推荐4个冷门且功能非常强大的效率工具&#xff0c;一起来看看吧&#xff01; 1、Seafile 企业云盘神器 Seafile 是一个开源的网…

middlebury立体匹配评估使用方法总结(二)——python版离线教程

系列文章目录 middlebury立体匹配评估使用方法总结&#xff08;一&#xff09;——网站说明 middlebury立体匹配评估使用方法总结&#xff08;二&#xff09;——python版离线教程 文章目录系列文章目录前言1.下载内容2.配置环境3.elas编译4. 运行评估总结前言 最近想使用midd…

vim配置systemverilog环境

参考文章: vim中systemverilog的高亮显示 - 乔_木 - 博客园vim中systemverilog的高亮显示https://www.cnblogs.com/OneFri/p/6087847.html 一、.vimrc配置文件中添加 filetype on "打开文件类型检测 二、创建运行目录 mkdir -p ~/.vim/ftdetect mkdir -p ~/.vim/synta…

Python基础知识入门(一)

Python基础知识入门&#xff08;二&#xff09; 一、发展历程 Python的创始人为荷兰人吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;。1989年圣诞节期间&#xff0c;在阿姆斯特丹&#xff0c;Guido为了打发圣诞节的无趣&#xff0c;决心开发一个新的脚本解释程序&…

第五章《类的继承》第2节:子类对象的构建过程

5.1小节讲解了类的继承机制。通过学习5.1小节的内容可知:子类能够继承父类的属性和方法,在此基础上,子类常常会扩展出属于自身特有的属性和方法,因此子类对象中的属性和方法可以分为两部分:从父类中继承而来的部分和自身所定义的部分。图5-3展示了Person和Student父子两个…

C++中的继承(上)

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、继承概述二、继承方式与访问限定符三、继承中的作用域四、基类和派生类对象赋值兼容转换五、继承当中默认成员函数的问题1.构造函数2.拷…

我做整车疲劳耐久分析9年积累的22条建模经验

作者&#xff1a;孙老师 对于承受交变应力的设备&#xff0c;疲劳分析在有限元分析占有重要地位。在进行疲劳分析时&#xff0c;有限元模型的正确搭建又至关重要。我们都知道&#xff0c;模型的质量直接影响分析的精度&#xff0c;所以好的建模方式是疲劳分析的第一步&#xf…

OpenGL原理与实践——核心模式(一):VBO、VAO等原理解析及项目初始设置

目录 序言——OpenGL在是什么&#xff1f;为什么&#xff1f;做什么? OpenGL实现了什么 OpenGL内模型数据的本质——顶点数据 我们需要研究什么——三角形&#xff0c;一个图形基元 MVP变换 OpenGL渲染流程的关键——摄像机变换 OpenGL渲染管线概览 准备——项目配置…

dpdk结合sriov测试vpp ipsec性能

目的 测试vpp ipsec转发性能&#xff0c;想当作openstack VPNaas的一种driver&#xff0c;提高ipsec网关的转发能力。 环境 测试资源很有限&#xff0c;没有测试仪&#xff0c;物理机之外的交换机不受控制。 只有两台物理机&#xff0c;各有一张测试网卡&#xff0c;网卡有…

分布式存储之 etcd 的集群管理

在分布式文件存储中&#xff0c;我们通常会面临集群选主&#xff0c;配置共享和节点状态监控的问题。通过 etcd&#xff08;基于 Raft 协议)&#xff09;可以实现超大规模集群的管理&#xff0c;以及多节点的服务可靠性。今天&#xff0c;我们就聊聊 etcd 在分布式存储中的具体…

作业-11.24

1、多线程并发服务器 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <string.h> #include <pthread.h> #include <stdlib.h> #include <…

MCE | 间歇性禁食增强抗癌疗效

越来越多的研究表明&#xff0c;“禁食”不仅与免疫系统调控 、血糖调节有关&#xff0c;还对多种疾病的治疗有改善效果&#xff0c;如心血管疾病和癌症等。这里的“禁食”与节食不同&#xff0c;一般指的是间歇性禁食&#xff0c;包括多种方案&#xff0c;例如 FMD (Fasting-m…

LeetCode135. 分发糖果(贪心算法)

1 题目描述 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回…