首页
统计
关于
Search
1
Sealos3.0离线部署K8s集群
1,093 阅读
2
类的加载
745 阅读
3
Spring Cloud OAuth2.0
727 阅读
4
SpringBoot自动装配原理
693 阅读
5
集合不安全问题
590 阅读
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
FastApi
登录
Search
标签搜索
Java
CSS
mysql
RabbitMQ
JavaScript
Redis
JVM
Mybatis-Plus
Camunda
多线程
CSS3
Python
Spring Cloud
注解和反射
Activiti
工作流
SpringBoot
Mybatis
Spring
html5
蘇阿細
累计撰写
391
篇文章
累计收到
4
条评论
首页
栏目
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
FastApi
页面
统计
关于
搜索到
391
篇与
的结果
2022-08-27
创建者模式-单例模式
特点:将对象的创建与使用分离,可以降低系统的耦合度,使用者不需要关注对象的创建细节分为:单例模式、工厂模式、抽象工厂模式、原型模式、建造者模式1. 单例模式单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象单例模式的实现:饿汉式:类一加载就创建该实例对象懒汉式:需要使用时才创建该实例对象(1)饿汉式(静态变量方式)该方式在成员位置声明 Singleton 类型的静态变量,并创建 Singleton 类的对象 instance,instance 对象随着类的加载被创建,如果该类足够大且一直没有被使用的情况下会造成内存的浪费Singletonpublic class Singleton { //1.私有构造方法 private Singleton() { } //2.在本类中创建本类对象 private static Singleton instance = new Singleton(); //3.提供一个公共的访问方式,让外界获取该对象 public static Singleton getInstance() { return instance; } }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //true System.out.println(instance == instance1); } }(2)饿汉式(静态代码块方式)该方式在成员位置声明 Singleton 类型的静态变量,而对象的创建是在静态代码块中,也是随着类的加载而被创建,与静态变量方式类似Singletonpublic class Singleton { private Singleton() { } private static Singleton instance; static { instance = new Singleton(); } public static Singleton getInstance() { return instance; } }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //true System.out.println(instance == instance1); } }(3)懒汉式(线程不安全)当调用 getInstance() 方法获取 Singleton 类的对象的时候才创建 Singleton 类的对象,这样就实现了懒加载,但在多线程操作时存在线程不安全的问题Singletonpublic class Singleton { private Singleton() { } private static Singleton instance; public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //多线程操作时,存在线程不安全的问题 System.out.println(instance == instance1); } }(4)懒汉式(双重检测锁)使用 volatile 关键字保证可见性和防止指令重排(JVM在实例化对象时会进行优化和指令重排序操作,可能产生空指针)Singletonpublic class Singleton { private Singleton() { } //volatile保证可见性和防止指令重排 private static volatile Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1); } }(5)懒汉式(静态内部类)实例由内部类创建,由于JVM在加载外部类的过程中不会加载静态内部类,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性,其中静态属性由于被 static 修饰,保证只被实例化一次,并且严格保证实例化顺序说明:第一次加载 Singleton 类时不会去初始化 INSTANCE,只有第一次调用 getInstance() 时,虚拟机加载 SingletonHolder 并初始化 INSTANCE ,这样既保证了现成安全,也保证了 Singleton 的唯一性,在没有加任何锁的情况下保证了线程的安全且不造成性能和内存的浪费(双重检测锁方式 和 静态内部类方式可以任选其一)Singlepublic class Singleton { private Singleton() { } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance == instance1); } }(6)枚举方式枚举是线程安全的,且只会被加载一次,注意枚举方式属于饿汉式Singletonpublic enum Singleton { INSTANCE; }Clientpublic class Client { public static void main(String[] args) { Singleton instance = Singleton.INSTANCE; Singleton instance1 = Singleton.INSTANCE; //true System.out.println(instance == instance1); } }(7)存在的问题破坏单例模式的方式:序列化和反序列化反射解决方法:序列化和反序列化 - 在单例类中添加 readResolve() 方法,在反序列化时,如果类中定义了这个方法,就返回这个方法的值,反之则创建新的对象反射 - 在单例类的构造方法中通过标志位来判断是否是第一次访问,且在该构造方法中需要加 synchronized 锁,锁该类 synchronized(Singleton.class)
2022年08月27日
46 阅读
0 评论
0 点赞
2022-08-27
合成复用原则
定义:尽量先使用组合或聚合等关联关系来实现,其次才考虑使用继承关系来实现类的复用通常分为:继承复用、合成复用继承复用破坏了类的封装性,将父类的实现细节暴露给了子类,父类对子类是透明的,这种复用又称为“白箱”复用耦合度高,父类的实现的任何变化都会导致子类的实现发生变化,不利于类的维护和扩展灵活性低,从父类继承而来的实现是静态的,在编译时已定义,所以在运行时不可能发生变化合成复用(可将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能)维持了类的封装性,因为成员对象的内部细节是新对象看不见的,所以又称为“黑箱”复用耦合度低,可以在类的成员位置声明抽象灵活性高,这种复用可以在运行时动态进行,新对象可以动态的引用与成员对象类型相同的对象以汽车分类管理为例:汽车按动力源可分为汽油车、新能源车;按颜色可分为白色、红色;如果同时考虑这两种成分,会产生多种组合可以看出使用继承复用会产生很多子类,如果要添加新的能源类型的车,就需要再定义新的类
2022年08月27日
48 阅读
0 评论
0 点赞
2022-08-27
迪米特法则
定义:如果两个软件实体无需直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用,其目的是降低耦合,提高模块的相对独立性以明星和经纪人为例:Agentpublic class Agent { private Star star; private Fans fans; private Company company; public Star getStar() { return star; } public void setStar(Star star) { this.star = star; } public Fans getFans() { return fans; } public void setFans(Fans fans) { this.fans = fans; } public Company getCompany() { return company; } public void setCompany(Company company) { this.company = company; } public void meeting() { System.out.println(star.getName() + "和粉丝:" + fans.getName() + "见面"); } public void business() { System.out.println(star.getName() + "和" + company.getName() + "进行洽谈"); } }Starpublic class Star { private String name; public Star(String name) { this.name = name; } public String getName() { return name; } }Fanspublic class Fans { private String name; public Fans(String name) { this.name = name; } public String getName() { return name; } }Companypublic class Company { private String name; public Company(String name) { this.name = name; } public String getName() { return name; } }Clientpublic class Client { public static void main(String[] args) { //经纪人 Agent agent = new Agent(); //明星 Star star = new Star("孙笑川"); agent.setStar(star); //粉丝 Fans fans = new Fans("药水哥"); agent.setFans(fans); //媒体公司 Company company = new Company("xxxTV"); agent.setCompany(company); //粉丝见面会 agent.meeting(); //商务洽谈 agent.business(); } }
2022年08月27日
34 阅读
0 评论
0 点赞
2022-08-22
接口隔离原则
定义:客户端不应该被迫依赖于它不使用的方法,即:一个类对另一个类的依赖应该建立在最小的接口上以安全门为例:存在的问题:如果要增加新的品牌的安全门,则违背了开闭原则SafetyDoorpublic interface SafetyDoor { /** * 防盗 */ void antiTheft(); /** * 防火 */ void fireproof(); /** * 防水 */ void waterproof(); }TestSafetyDoorpublic class TestSafetyDoor implements SafetyDoor { @Override public void antiTheft() { System.out.println("防盗"); } @Override public void fireproof() { System.out.println("防火"); } @Override public void waterproof() { System.out.println("防水"); } }Clientpublic class Client { public static void main(String[] args) { //存在的问题:如果要增加新的品牌的安全门,则违背了开闭原则 TestSafetyDoor testSafetyDoor = new TestSafetyDoor(); testSafetyDoor.antiTheft(); testSafetyDoor.fireproof(); testSafetyDoor.waterproof(); } }改进:抽象出安全门各个功能的接口,新增其他品牌的安全门时只需实现对应功能的接口AntiTheftpublic interface AntiTheft { /** * 防盗 */ void antiTheft(); }Fireproofpublic interface Fireproof { /** * 防火 */ void fireproof(); }Waterproofpublic interface Waterproof { /** * 防水 */ void waterproof(); }TestSafetyDoorpublic class TestSafetyDoor implements AntiTheft, Fireproof, Waterproof { @Override public void antiTheft() { System.out.println("防盗"); } @Override public void fireproof() { System.out.println("防火"); } @Override public void waterproof() { System.out.println("防水"); } }Test01SafetyDoorpublic class Test01SafetyDoor implements AntiTheft, Fireproof { @Override public void antiTheft() { System.out.println("防盗"); } @Override public void fireproof() { System.out.println("防火"); } }Clientpublic class Client { public static void main(String[] args) { //Test品牌安全门 TestSafetyDoor testSafetyDoor = new TestSafetyDoor(); testSafetyDoor.antiTheft(); testSafetyDoor.fireproof(); testSafetyDoor.waterproof(); System.out.println("================="); //Test品牌安全门 Test01SafetyDoor test01SafetyDoor = new Test01SafetyDoor(); test01SafetyDoor.antiTheft(); test01SafetyDoor.fireproof(); } }
2022年08月22日
41 阅读
0 评论
0 点赞
2022-08-22
依赖倒置原则
定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象以组装电脑为例:存在的问题:现在的电脑只能使用给定的组件,如果要使用其他的,则违背了开闭原则XiJiepublic class XiJie { public void save(String data) { System.out.println("使用希捷硬盘存储数据:" + data); } public String get() { System.out.println("使用希捷硬盘读取数据"); return "数据"; } }Intelpublic class Intel { public void run() { System.out.println("使用Intel cpu"); } }Kingstonpublic class Kingston { public void save() { System.out.println("使用金士顿内存条"); } }Computerpublic class Computer { private XiJie hardDisk; private Intel cpu; private Kingston memory; public XiJie getHardDisk() { return hardDisk; } public void setHardDisk(XiJie hardDisk) { this.hardDisk = hardDisk; } public Intel getCpu() { return cpu; } public void setCpu(Intel cpu) { this.cpu = cpu; } public Kingston getMemory() { return memory; } public void setMemory(Kingston memory) { this.memory = memory; } public void run() { System.out.println("电脑运行了"); String data = hardDisk.get(); System.out.println("从硬盘上获取的数据是:" + data); cpu.run(); memory.save(); } }ComputerDemopublic class ComputerDemo { public static void main(String[] args) { //创建组件对象 XiJie hardDisk = new XiJie(); Intel cpu = new Intel(); Kingston memory = new Kingston(); Computer computer = new Computer(); //组装计算机 computer.setHardDisk(hardDisk); computer.setCpu(cpu); computer.setMemory(memory); //运行 //存在的问题:现在的电脑只能使用给定的组件,如果要使用其他的,则违背了开闭原则 computer.run(); } }改进:抽象出各个配件的接口,让Computer类依赖抽象,而不是依赖于各组件的具体实现类HardDiskpublic interface HardDisk { /** * 存储数据 * * @param data 数据 */ void save(String data); /** * 读取数据 * * @return */ String get(); }Cpupublic interface Cpu { /** * 运行 */ void run(); }Memorypublic interface Memory { /** * 保存 */ void save(); }XiJiepublic class XiJie implements HardDisk { @Override public void save(String data) { System.out.println("使用希捷硬盘存储数据:" + data); } @Override public String get() { System.out.println("使用希捷硬盘读取数据"); return "数据"; } }Intelpublic class Intel implements Cpu { @Override public void run() { System.out.println("使用Intel cpu"); } }AMDpublic class Amd implements Cpu { @Override public void run() { System.out.println("使用AMD cpu"); } }Kingstonpublic class Kingston implements Memory { @Override public void save() { System.out.println("使用金士顿内存条"); } }Computerpublic class Computer { private HardDisk hardDisk; private Cpu cpu; private Memory memory; public HardDisk getHardDisk() { return hardDisk; } public void setHardDisk(HardDisk hardDisk) { this.hardDisk = hardDisk; } public Cpu getCpu() { return cpu; } public void setCpu(Cpu cpu) { this.cpu = cpu; } public Memory getMemory() { return memory; } public void setMemory(Memory memory) { this.memory = memory; } public void run() { System.out.println("电脑运行了"); String data = hardDisk.get(); System.out.println("从硬盘上获取的数据是:" + data); cpu.run(); memory.save(); } }ComputerDemopublic class ComputerDemo { public static void main(String[] args) { //创建组件对象 HardDisk xiJie = new XiJie(); //Cpu intel = new Intel(); Cpu intel = new Amd(); Memory kingston = new Kingston(); //创建计算机对象 Computer computer = new Computer(); //组装计算机 computer.setHardDisk(xiJie); computer.setCpu(intel); computer.setMemory(kingston); //运行 computer.run(); } }
2022年08月22日
36 阅读
0 评论
0 点赞
2022-08-22
里氏替换原则
定义:子类可以扩展父类的功能,但不能改变父类原有的功能(子类继承父类时,除了添加新的方法和功能外,尽量不要重写父类的方法)以正方形不是长方形为例:在resize方法中,Rectangle类型的参数不能被Square类型的参数所代替,如果进行了替换,则不能得到预期的打印结果Rectanglepublic class Rectangle { private double length; private double width; public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } }Squarepublic class Square extends Rectangle { @Override public void setLength(double length) { super.setLength(length); super.setWidth(length); } @Override public void setWidth(double width) { super.setWidth(width); super.setLength(width); } }RectangleDemopublic class RectangleDemo { public static void main(String[] args) { //创建长方形对象 Rectangle rectangle = new Rectangle(); rectangle.setLength(20); rectangle.setWidth(10); //扩宽 resize(rectangle); printLengthAndWidth(rectangle); System.out.println("===================="); //创建正方形 Square square = new Square(); square.setWidth(20); resize(square); //在resize方法中,Rectangle类型的参数不能被Square类型的参数所代替,如果进行了替换,则不能得到预期的打印结果 printLengthAndWidth(square); } public static void resize(Rectangle rectangle) { //如果长 > 宽,进行扩宽操作 while (rectangle.getLength() >= rectangle.getWidth()) { rectangle.setWidth(rectangle.getWidth() + 1); } } public static void printLengthAndWidth(Rectangle rectangle) { System.out.println("长:" + rectangle.getLength()); System.out.println("宽:" + rectangle.getWidth()); } }改进:抽象出四边形接口,长方形、正方形实现四边形接口Quadrilateralpublic interface Quadrilateral { /** * 获取长 * * @return */ double getLength(); /** * 获取宽 * * @return */ double getWidth(); }Rectanglepublic class Rectangle implements Quadrilateral { private double length; private double width; public void setLength(double length) { this.length = length; } public void setWidth(double width) { this.width = width; } @Override public double getLength() { return length; } @Override public double getWidth() { return width; } }Squarepublic class Square implements Quadrilateral { private double side; public double getSide() { return side; } public void setSide(double side) { this.side = side; } @Override public double getLength() { return side; } @Override public double getWidth() { return side; } }RectangleDemopublic class RectangleDemo { public static void main(String[] args) { //创建长方形对象 Rectangle rectangle = new Rectangle(); rectangle.setLength(20); rectangle.setWidth(10); resize(rectangle); printLengthAndWidth(rectangle); System.out.println("===================="); //创建正方形对象(此时正方形和长方形不存在父子关系) Square square = new Square(); square.setSide(10); printLengthAndWidth(square); } public static void resize(Rectangle rectangle) { //如果长 > 宽,进行扩宽操作 while (rectangle.getLength() >= rectangle.getWidth()) { rectangle.setWidth(rectangle.getWidth() + 1); } } public static void printLengthAndWidth(Quadrilateral quadrilateral) { System.out.println("长:" + quadrilateral.getLength()); System.out.println("宽:" + quadrilateral.getWidth()); } }
2022年08月22日
22 阅读
0 评论
0 点赞
2022-08-19
开闭原则
定义:对扩展开放,对修改关闭以输入法更换皮肤为例抽象皮肤类public abstract class AbstractSkin { /** * 显示方法 */ public abstract void display(); } 默认皮肤public class DefaultSkin extends AbstractSkin { @Override public void display() { System.out.println("默认皮肤"); } }自定义皮肤public class TestSkin extends AbstractSkin { @Override public void display() { System.out.println("测试皮肤"); } } 搜狗输入法public class SouGouInput { private AbstractSkin skin; public void setSkin(AbstractSkin skin) { this.skin = skin; } public void display() { skin.display(); } }测试public class Client { public static void main(String[] args) { //1.创建输入法对象 SouGouInput input = new SouGouInput(); //2.创建默认皮肤对象 //DefaultSkin skin = new DefaultSkin(); TestSkin skin = new TestSkin(); //3.将皮肤设置到输入法中 input.setSkin(skin); //4.显示皮肤 input.display(); } }
2022年08月19日
33 阅读
0 评论
0 点赞
2022-07-17
新的组件
1. FragmentVue2:组件必须有一个根标签Vue3:组件可以没有根标签,内部会将多个标签包含在一个 Fragment 虚拟元素中减少标签层间,性能优化2. Teleport概念:将 组件html结构 移动到指定位置<teleport to="body"> <div v-if="isShow" class="mask"> <div class="dialog"> <h3>你好</h3> <h4>孙笑川</h4> <h4>药水哥</h4> <h4>Giao哥</h4> <button @click="isShow = false">关闭弹窗</button> </div> </div> </teleport>3. Suspense等待异步组件时渲染定义的缺省内容,提升用户体验实现:引入异步组件import {defineAsyncComponent} from "vue"; const Child = defineAsyncComponent(() => import('./components/Child'))使用 Suspense 包裹组件,并配置好 default 和 fallback<template> <div class="app"> <h3>App组件</h3> <Suspense> <template v-slot:default> <Child/> </template> <template v-slot:fallback> <h3>加载中...</h3> </template> </Suspense> </div> </template>
2022年07月17日
20 阅读
0 评论
0 点赞
1
...
14
15
16
...
49