设计模式学习笔记--单例、建造者、适配器、装饰、外观、组合
以下内容根据以下网址及相关视频整理:Android设计模式之单例模式_谬谬清不给我取名字的博客-CSDN博客_android 单例模式
Android设计模式--单例模式的六种实现和单例模式讲解Volatile与Synchronized相关的并发_龙腾腾的博客-CSDN博客_android 单例 volatile
java 设计模式实战,装饰者模式之不用改变也能变强 - 掘金
目录
一、单例模式:
1、饿汉式单例模式:
2、懒汉式单例模式:
3、双重检索(Double Check Lock,DCL)
4、静态内部类实现单例
5、使用 枚举实现单例
二、builder模式---将复杂的对象构建分离
三、adapter设计模式
1.类适配器:把适配的类的API转换成目标类的API。
2.对象适配器模式:
四、装饰模式
五、外观模式
六、组合模式
一、单例模式:
(1)构造方法使用private修饰,避免外部通过new创建对象;
(2)通过一个静态方法或者枚举返回单例类对象;
(3)考虑对象创建时的线程安全问题,确保单例类的对象有且仅有一个,尤其是在多线程环境下;
(4)确保单例类对象在反序列化时不会重新构建对象;
1、饿汉式单例模式:
(1)类加载时就初始化,浪费内存,不能延迟加载;
(2)基于 classloader 机制避免了多线程的同步问题,线程安全;
(3)没有加锁,调用效率高;
public class Singleton {private static Singleton sInstance = new Singleton();private Singleton() {}public static Singleton getInstance() {return sInstance;}
}
2、懒汉式单例模式:
(1)可以延迟加载;
(2)加synchronized是线程安全的,不加就是线程不安全的;
(3)加synchronized会导致调用效率很低;
不足之处:在多线程并发下这样的实现是无法保证实例是唯一的。
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
优化:懒汉线程安全模式
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}//方法一:添加 synchronized 关键字public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}//方法二:同步代码块实现public static LazySingleton getInstance2() {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();}}return instance;}
}
缺点:性能方面不足
3、双重检索(Double Check Lock,DCL)
(1)可以延迟加载;
(2)线程安全的;
(3)对JDK的版本有要求(1.5及以上)(需要使用volatile关键字来禁止指令重排的操作,这个在JDK1.5之后才出现)
public class Singleton {private volatile static Singleton instance; //volatile具备 “有序性” 和 “可见性” 的特性。 第一层锁:保证变量可见性private Singleton() {}public static Singleton getInstance() {if (instance == null) {//第一次判空:无需每次都加锁,提高性能synchronized (Singleton.class) {//第二层锁:保证线程同步if (instance == null) {//第二次判空:避免多线程同时执行getInstance()产生多个single对象instance = new Singleton();}}}return instance;}
}
1)、构造函数得私有,禁止其他对象直接创建实例;
2)、对外提供一个静态方法,可以获取唯一的实例;
3)、即然是双重检查模式,就意味着创建实例过程会有两层检查。第一层就是最外层的判空语句:第一处if (singleton == null),该判断没有加锁处理,避免第一次检查singleton对象非null时,多线程加锁和初始化操作;当前对象未创建时,通过synchronized关键字同步代码块,持有当前Singleton.class的锁,保证线程安全,然后进行第二次检查。
4)、Singleton类持有的singleton实例引用需要volatile关键字修饰,因为在最后一步singleton = new Singleton(); 创建实例的时候可能会重排序,导致singleton对象逸出,导致其他线程获取到一个未初始化完毕的对象。
4、静态内部类实现单例
(1)可以延迟加载;
(2)基于 classloader 机制避免了多线程的同步问题,线程安全;没有性能缺陷;
public class Singleton{private Singleton(){}public static Singleton newInstance(){return SingletonHelper.instance;}//静态内部类 唯一性 私有的private static class SingletonHelper{private final static Singleton instance = new Singleton();}
}
5、使用 枚举实现单例
优点:
(1)不是延迟加载的;
(2)枚举实例的创建是线程安全的,并且在任何情况下都是一个单例;
public enum Singleton {INSTANCE;
}
总结:
饿汉:无法对instance实例进行延迟加载。
懒汉:多线程并发条件下无法保证实例的唯一性。
懒汉线程安全:使用synchronized 关键字导致性能缺陷。
DCL:JVM即编译器指令导致重排序,导致实例可能不唯一。
静态内部类、枚举:延迟加载、线程安全、性能优势。
android中用到的单例模式举例:application、eventBus
public class MyApplication extends Application {private static MyApplication instance;public static MyApplication getInstance() {return instance;}@Overridepublic void onCreate() {super.onCreate();instance = this;} }
通过MyApplication.getInstance()获取MyApplication类;
二、builder模式---将复杂的对象构建分离
builder模式也叫建造者模式,是较为复杂的 创建型模式,它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离。 builder模式的作用将一个复杂对象的构建与他的表示分离,使用者可以一步一步的构建一个比较复杂的对象。
使用场景:当构建一个对象需要很多参数的时候,并且参数的对象和类型不固定的时候。
//Product:被构建的复杂对象,包含多个组成部件
public class Product {private String partA;private String partB;private String partC;public String getPartA() {return partA;}public void setPartA(String partA) {this.partA = partA;}public String getPartB() {return partB;}public void setPartB(String partB) {this.partB = partB;}public String getPartC() {return partC;}public void setPartC(String partC) {this.partC = partC;}
}//Builder:它为创建一个产品Product对象的各个部件指定抽象接口
abstract class Builder {protected Product product = new Product();//创建产品对象public abstract void buildPartA();public abstract void buildPartB();public abstract void buildPartC();//用于返回复杂的产品对象public Product getResult() {return product;}
}//ConcreateBulder:实现了Builder接口,实现各个部件的具体构造和装配方法
public class ConcreateBulder extends Builder {@Overridepublic void buildPartA() {}@Overridepublic void buildPartB() {}@Overridepublic void buildPartC() {}
}//指挥类:作用:隔离程序员创建复杂对象的过程;控制产品创建复杂对象的过程
//Director:指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系。
public class Director {public Builder builder;public Director(Builder builder) {this.builder = builder;}public void setBuilder(Builder builder) {this.builder = builder;}//产品构建和组装的方法public Product construct() {builder.buildPartA();builder.buildPartB();//每一个部分可以灵活选择是否实现builder.buildPartC();return builder.product;}
}//调用类:class BuildClient{public static void main(String[] args){Builder builder = new ConcreateBulder();Director director = new Director(builder);director.construct();}
}
总结:
(1)Product:被构建的复杂对象,包含多个组成部件
(2)Builder:它为创建一个产品Product对象的各个部件指定抽象接口
(3)ConcreateBulder:实现了Builder接口,实现各个部件的具体构造和装配方法
(4)Director:指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系。
优点:
松散耦合:生成器模式可以用同一个构造算法构建出表现上完全不同的产品,实现产品构建和产品表现上的分离。
可以很容易的改变产品的内部展示。
更好的复用性:生成器模式很好的实现构建算法和具体产品实现的分离。
缺点:
会产生多余的builder对象以及director对象,消耗内存。
对象的构建过程会暴露。
builder模式在android中的应用:AlertDialog、
三、adapter设计模式
定义:将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器。
1.类适配器:把适配的类的API转换成目标类的API。
让 Adapter
实现 Target
接口,并且 继承 Adaptee
,这样 Adapter
就具备 Target
和 Adaptee
可以将两者进行转化。
//目标角色:所期待得到的接口,类适配器目标不能为类
public interface Target {void sampleOperation2();
}//源角色:现在需要适配的接口,
public class Adaptee {public void sampleOperation1(){System.out.println("打印1212");}
}
//适配器角色:适配器类是本模式的核心,适配器把源接口转换成目标接口,这一角色必须是类
public class Adapter extends Adaptee implements Target {@Overridepublic void sampleOperation2() {super.sampleOperation1();}
}public class Client {public static void main(String[] args) {Target target = new Adapter();target.sampleOperation2();}
}
总结:
1、类适配器使用对象继承的方式,是静态的定义方式。
2、对于类适配器,适配器可以重定义adapteree的部分行为。
3、对于类适配器,仅仅引用了一个对象,并不需要额外的引用来间接获得adapteree.
4、由于适配器直接继承了adapteree,使得适配器不能和adapteree的子类一起工作。
2.对象适配器模式:
对象适配器的原理就是通过组合来实现适配器功能,是动态组合的方式。具体做法:让Adapter 实现 Target 接口,然后内部持有 Adaptee 实例,然后再 Target 接口规定的方法内转换 Adaptee。 具体代码实现很简单就是将Adapter代码修改一下,原来是继承 Adaptee,现在是持有 Adaptee。
public interface Target {void sampleOperation2();
}public class Adaptee {public void sampleOperation1(){System.out.println("打印1212");}
}public class Adapter implements Target {public Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void sampleOperation2() {adaptee.sampleOperation1();}
}public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Adapter adapter = new Adapter(adaptee);adapter.sampleOperation2();}
}
四、装饰模式
定义:动态地给对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类实现更加灵活,装饰模式是一种对象结构型模式。
使用场景:
1)在不影响其它对象的情况下,以动态、透明的方式给单个对象添加新的行为或特征
2)当不能采用继承的方式对系统进行扩展或采用继承不利于系统的扩展和维护时,采用装饰模式。
代码:
//抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。 人:吃、跑
public interface People {void run();void eat();
}//具体构件(Concrete Component)角色:定义一个将要接收附加责任的类
public class Xiaoming implements People{@Overridepublic void run() {System.out.println("小明正在跑步。。。");}@Overridepublic void eat() {System.out.println("小明正在吃饭。。。");}
}//装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
public abstract class PeopleDetail implements People {private People people;public PeopleDetail(People people) {this.people = people;}@Overridepublic void run() {beforeRun();people.run();afterRun();}@Overridepublic void eat() {beforeEat();people.eat();afterEat();}public abstract void beforeEat();public abstract void afterEat();public abstract void beforeRun();public abstract void afterRun();
}//具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
public class XiaomingRun extends PeopleDetail{public XiaomingRun(People people) {super(people);}@Overridepublic void beforeEat() {}@Overridepublic void afterEat() {}@Overridepublic void beforeRun() {System.out.println("小明先做拉伸训练");}@Overridepublic void afterRun() {System.out.println("小明进入慢走路状态");}
}//具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
public class XiaomingEat extends PeopleDetail{public XiaomingEat(People people) {super(people);}@Overridepublic void beforeEat() {System.out.println("小明喝了一杯水");}@Overridepublic void afterEat() {System.out.println("小明出去走了100步");}@Overridepublic void beforeRun() {}@Overridepublic void afterRun() {}
}//接下来进行测试:public static void main(String[] args){Xiaoming xiaoming = new Xiaoming();System.out.println("小明开始吃饭--");XiaomingEat xiaomingEat = new XiaomingEat(xiaoming);xiaomingEat.eat();System.out.println("小明开始跑步--");XiaomingRun xiaomingRun =new XiaomingRun(xiaoming);xiaomingRun.run();}
优点:对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。降低了系统的耦合度;可以动态扩展一个实现类的功能。
五、外观模式
定义:主要目的在于让外部减少与子系统内部多个模块的交互,从而让外部能够更简单的使用子系统,它负责把客户端的请求转发给子系统内部的各个模块进行处理。
使用场景:
1)当你要为一个复杂子系统提供一个简单接口时。
2)客户程序与抽象类的实现部分之间存在着很大的依赖性。
3)当你需要构建一个有层次结构的子系统时。
//抽象的组件
public interface Module {void work();
}//实例
public class Module1 implements Module{@Overridepublic void work() {System.out.println("Module1");}
}public class Module2 implements Module{@Overridepublic void work() {System.out.println("Module2");}
}public class Module3 implements Module{@Overridepublic void work() {System.out.println("Module3"+"改变了");}
}public class ModuleImpl {private Module1 module1 = null;private Module3 module3= null;private Module2 module2= null;private static ModuleImpl moduleImpl = null;private ModuleImpl(){this.module1 = new Module1();this.module2 = new Module2();this.module3 = new Module3();}public static ModuleImpl getInstance(){if (moduleImpl==null){moduleImpl = new ModuleImpl();}return moduleImpl;}public void testModule(){module1.work();module2.work();module3.work();}
}//测试:ModuleImpl.getInstance().testModule();
优点:
1)由于ModuleImpl 封装了各个模块交互的过程,如果今后内部模块调用发生了变化,只需要修改ModuleImpl 类就可以。
2)ModuleImpl 是单例的,是可以被多个客户端调用的。
六、组合模式
定义:将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端和单个对象和组合对象的使用具有一致性。
树的结构——>组合设计模式
使用场景:
1)需要表示一个对象整体或者部分层次。
2)让客户能够忽略不同对象层次的变化。
public abstract class File {private String name;public File(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public abstract void Watch();//以下三个方法是组合方法public void add(File file) {throw new UnsupportedOperationException();}public void remove(File file) {throw new UnsupportedOperationException();}public File getChild(int positon) {throw new UnsupportedOperationException();}
}public class Folder extends File {public List<File> mFileList;public Folder(String name) {super(name);mFileList = new ArrayList<>();}@Overridepublic void Watch() {StringBuffer fileName = new StringBuffer();for (File file : mFileList) {fileName.append(file.getName() + ":");}System.out.println("组合模式:"+"这是一个叫"+getName()+"文件夹,包含:"+mFileList.size()+"个文件,分别是:"+fileName);}@Overridepublic void add(File file) {mFileList.add(file);}@Overridepublic void remove(File file) {mFileList.remove(file);}@Overridepublic File getChild(int positon) {return mFileList.get(positon);}
}public class TextFile extends File {public TextFile(String name) {super(name);}@Overridepublic void Watch() {System.out.println("这是一个叫"+getName()+"的文件夹");}
}测试:
public static void main(String[] args){TextFile textFileA =new TextFile("a.txt");TextFile textFileB =new TextFile("b.txt");TextFile textFileC =new TextFile("c.txt");textFileA.Watch();Folder folder = new Folder("组合设计模式");folder.add(textFileA);folder.add(textFileB);folder.add(textFileC);folder.Watch();folder.getChild(1).Watch();}
优点:高层模块调用简单;节点自由增加,案例中创建了两个子类,可以创建多个子类;
缺点:违反了依赖倒置原则;
相关文章:
设计模式学习笔记--单例、建造者、适配器、装饰、外观、组合
以下内容根据以下网址及相关视频整理:Android设计模式之单例模式_谬谬清不给我取名字的博客-CSDN博客_android 单例模式 Android设计模式--单例模式的六种实现和单例模式讲解Volatile与Synchronized相关的并发_龙腾腾的博客-CSDN博客_android 单例 volatile java …...
English Learning - Day5 L1考前复习 2023.2.10 周五
English Learning - Day5 L1考前复习 2023.2.10 周五1 单选题:She has the face _________.2 单选题: The goals ________ he fought all his life no longer seemed important to him.3 单选题:Sales director is a position ______ communi…...
C. Prepend and Append
time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Timur initially had a binary string†† s� (possibly of length 00). He performed the following operation several (possibly zero)…...

javassm超市在线配送管理系统
为了解决用户便捷地在网上购物,本文设计和开发了一个超市管理系统。本系统是基于web架构设计,SSM框架 ,使用Mysql数据库管理,综合采用JSP模式来完成系统的相关功能。主要实现了管理员与用户的注册与登陆,个人中心、用户…...
Scratch少儿编程案例-多模式贪吃蛇(无尽和计时)
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

谷歌蜘蛛池怎么搭建?Google蜘蛛池可以帮助谷歌排名吗?
本文主要分享关于谷歌蜘蛛池的搭建疑问,以及Google对谷歌排名的影响到底有多大。 本文由光算创作,有可能会被剽窃和修改,我们佛系对待这种行为吧。 谷歌蜘蛛池怎么搭建? 答案是:需要一个内链外链体系复杂的站群系统…...

Kubernetes集群-部署Java项目
Kubernetes集群-部署Java项目(SSG) k8s部署项目java流程图 第一步 打包制作镜像 打包 java源码: application.properties #在有pom.xml的路径下执行 mvn clean package制作镜像: 将刚才打包后的文件夹传到,装有dock…...
English Learning - Day54 作业打卡 2023.2.8 周三
English Learning - Day54 作业打卡 2023.2.8 周三引言1. 就算你不喜欢喝酒,也请尝一杯吧。2. 便纵有千种风情,更与何人说?——柳永《雨霖铃》 (来,挑战一下古诗词)3. 虽然忙,我也要参加会议。4. 无论发生什么…...
【Unity题】 1.矩阵旋转,欧拉旋转,四元数旋转各自的优缺点。2.StringBuilder和String的区别
1.矩阵旋转,欧拉旋转,四元数旋转各自的优缺点 矩阵旋转,欧拉旋转,四元数旋转是三种不同的旋转表示方法,下面是它们各自的优缺点: 矩阵旋转: 优点: 1.可以方便地实现复合旋转&…...

【C++面试问答】搞清楚深拷贝与浅拷贝的区别
问题 深拷贝和浅拷贝的区别是面试中的常见问题之一,对于不同的编程语言,这个问题的回答可能稍有差别,下面我们就来探索一下它们之间的异同吧。 先来看看在JavaScript对象的深拷贝与浅拷贝的区别: 浅拷贝:只是复制了…...

day10_面向对象基础
今日内容 零、 复习昨日 一、面向对象的概念 二、面向对象编程 三、内存图 零、 复习昨日 见晨考题 每日一数组题 写一个方法 用于合并两个int类型的数组 合并法则如下 {1,2,5,8,9}{1,3,0}---->{1,2,5,8,9,1,3,0} package com.qf.array;import java.util.Arrays;/*** --- 天…...

电影订票网站的设计与开发
技术:Java、JSP等摘要:随着科技的发展,时代的进步,互联网已经成为了人们生活中不可缺少的一部分,网上购物已然是一种时代的象征。纵观市场,电影行业的发展尤为迅速,电影种类和数量的增多导致客流…...

seata【SAGA模式】代码实践(细节未必完全符合saga的配置,仅参考)
seata SAGA模式: 代码仍然是上一篇AT模式的代码:AT模式 不需要undo_log表 下面开始: 首先,saga模式依靠状态机的json文件来执行整个流程,其中的开始节点的服务即TM,然后状态机需要依靠三张表࿰…...

面试题:Java锁机制
java对象包含了三个部分:对象头,实例数据和对齐填充。对象头又存放了:markWord和class point。classpoint :指向方法区,当前对象的类信息数据。markword:存储了很多和当前对象运行时的数据:例如…...

Springboot Web开发
文章目录一. 静态资源访问1. 配置静态资源访问前缀2. 修改默认静态资源存放目录3. Webjars4. 欢迎页支持5. 自定义Favicon二. 请求处理1. 路径变量2. 请求头处理3. 查询字符串处理4. 获取Cookie的值5. 获取请求体的值6. 获取请求域中的数据7. 矩阵变量一. 静态资源访问 只要静…...

分布式事务 | 使用DTM 的Saga 模式
DTM 简介前面章节提及的MassTransit、dotnetcore/CAP都提供了分布式事务的处理能力,但也仅局限于Saga和本地消息表模式的实现。那有没有一个独立的分布式事务解决方案,涵盖多种分布式事务处理模式,如Saga、TCC、XA模式等。有,目前…...

错误代码0xc0000001要怎么解决?如何修复错误
出现错误代码0xc0000001这个要怎么解决?其实这个的蓝屏问题还是非常的简单的,有多种方法可以实现 解决方法一 1、首先使用电脑系统自带的修复功能,首先长按开机键强制电脑关机。 注:如果有重要的资料请先提前备份好,…...
为什么 HTTP PATCH 方法不是幂等的及其延伸
幂等性 首先来看什么是幂等性,根据 rfc2616(Hypertext Transfer Protocol – HTTP/1.1) 文档第 50 页底部对 Idempotent Methods 的定义: Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the…...

13 Day:实现内核线程
前言:我们昨天完成了内核的内存池以及内存管理程序,今天我们要揭开操作系统多任务执行的神秘面纱,来了解并实现一个多任务的操作系统。 一,实现内核线程 在聊线程之间我们先聊聊处理器吧,众所周之现在我们的CPU动不动…...

GPU服务器安装显卡驱动、CUDA和cuDNN
GPU服务器安装cuda和cudnn1. 服务器驱动安装2. cuda安装3. cudNN安装4. 安装docker环境5. 安装nvidia-docker25.1 ubuntu系统安装5.2 centos系统安装6. 测试docker容调用GPU服务1. 服务器驱动安装 显卡驱动下载地址https://www.nvidia.cn/Download/index.aspx?langcn显卡驱动…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...