-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.search.js
40 lines (40 loc) · 13 KB
/
index.search.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var relearn_search_index=[{content:`23种设计模式.
`,description:"",tags:null,title:"设计模式",uri:"/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/index.html"},{content:"前端 前端知识 React Vue Typescript ",description:"",tags:null,title:"前端",uri:"/%E5%89%8D%E7%AB%AF/index.html"},{content:" arr 转map const arr = [ {metricsKey: 'k-1', metricsValue: 'v-1'}, {metricsKey: 'k-2', metricsValue: 'v-2'}, {metricsKey: 'k-3', metricsValue: 'v-3'}, {metricsKey: 'k-4', metricsValue: 'v-4'}, {metricsKey: 'k-5', metricsValue: 'v-5'}, ] const map = new Map\u003cstring, string\u003e(); arr.forEach(({metricsKey, metricsValue}) =\u003e map.set(metricsKey, metricsValue)) ",description:"",tags:null,title:"TS常用用法",uri:"/%E5%89%8D%E7%AB%AF/typescript/ts%E5%B8%B8%E7%94%A8%E7%94%A8%E6%B3%95/index.html"},{content:"Typescript ",description:"",tags:null,title:"Typescript",uri:"/%E5%89%8D%E7%AB%AF/typescript/index.html"},{content:`六大设计原则 [toc]
单一职责原则 (Single Responsibility Principle: SRP) 定义:应该有,且仅有一个原因引起类的变更 (适用范围,接口,方法,类) “There should never be more than one reason for a class to change.”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
定义:应该有,且仅有一个原因引起类的变更 (适用范围,接口,方法,类)
建议: 对于单一职责原则,我的建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化,一个方法尽可能做一件事情 单一职责的好处: 类的复杂性降低实现什么职责都有清晰明确的定义
可读性提高 (因为降低了类的复杂性)
可维护性提高(因为可读性提高了)
变更引起的风险降低:
接口的单一职责做的好,一个接口的修改只对相应的实现类有影响,对系统的拓展性与可维护性都有很大的帮助
里氏替换原则 (Liskov Substitution Principle: LSP) 定义:所有引用基类的地方必须能透明地使用其子类的对象 定义一:
“If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。)”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
定义二:
“Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象。)
第二使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
里氏替换原则为良好的继承定义了规范 子类必须完全实现父类的方法
“在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则”
“如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承”
子类可以有自己的个性
覆盖或实现父类的方法时输入参数可以被放大: 子类方法的前置条件必须与超类中被复写的方法的前置条件相同或更宽松
如果Father类的输入参数类型宽于子类的输入参数类型,会出现父类存在的地方,子类就未必可以存在,因为一旦把子类作为参数传入,调用者就很可能进入子类的方法范畴。
// 父类 public class Father { public Collection doSomething(HashMap map) { System.out.println("父类被执行..."); return map.values(); } } /** * 子类的输入参数是Map类型,也就是说子类的输入参数类型的范围扩大了 * 子类代替父类传递到调用者中,子类的方法永远都不会被执行 */ public class Son extends Father { //放大输入参数类型, 子类的方法永远不会执行 public Collection doSomething(Map map) { System.out.println("子类被执行..."); return map.values(); } } // 场景类 public class Client { public static void invoker() { //父类存在的地方,子类就应该能够存在 Father f = new Father(); //Son f = new Son(); HashMap map = new HashMap(); f.doSomething(map); } public static void main(String[] args) { invoker(); } } Note:宽于基类,则子类的复写方法实际为方法重载,若如参为父类方法的类型,则子类方法不会被调用到,因其直接调用了其父类的方法
“采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
复写或实现父类的方法时输出结果可以被缩小
父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一个类型,要么S是T的子类
最佳实践: “在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了,把子类当做父类使用,子类的“个性”被抹杀——委屈了点;把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标准。”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
依赖倒置原则 (Dependence Inversion Principle: DIP) 定义 高层模块不应该依赖底层模块,两者都应该依赖其抽象; 抽象不应该依赖细节; 细节应该依赖抽象; “High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
“依赖倒置原则在Java语言中的表现就是:
● 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
● 接口或抽象类不依赖于实现类;
● 实现类依赖接口或抽象类。”
摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.
`,description:"",tags:null,title:"六大设计原则",uri:"/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E5%85%AD%E5%A4%A7%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99/index.html"},{content:`单例模式 定义: “确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例”
通用代码: public class Singleton { /** * 定义的时候初始化对象/在static体重定义/在get方法中定义(此时的get方法加synchronized 修饰) */ public static final Singleton singleton = new Singleton(); /** * 私有化构造类,限制产生多个对象 */ private Singleton() { } /** * 获取实例对象 * * @return */ public static Singleton getSingleton() { return singleton; } /** * 类中其他方法,尽量是static */ public static void doSomething(){ } } 优点 减少内存开销,避免频繁创建销毁时的性能损耗(创建销毁性能无法优化) 避免资源多重占用(例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作) 单例模式可以在系统设置全局的访问点,优化和共享资源访问 缺点 拓展困难,因为一般没有接口(接口对单例模式没有意义) 不利于测试,在单例模式创建之前不能完成测试 与单一职责原则冲突 业务例子 /** * 线程池 * * @author robinson * 2021/9/28 15:19 * **/ @Slf4j public class ExecutorUtil { /** * 核心线程数 */ private static final int THREAD_CORE_POOL_SIZE = 5; /** * 队列容量 */ private static final int THREAD_QUEUE_CAPACITY = 1024; private static ThreadPoolExecutor executor; /** * 私有构造方法,防止初始化 */ private ExecutorUtil() { } /** * 获取线程池 * * @return ThreadPoolExecutor */ public static synchronized ThreadPoolExecutor getExecutor(String threadPoolName) { if (null == executor) { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(threadPoolName + "-%d").build(); executor = new ThreadPoolExecutor(THREAD_CORE_POOL_SIZE, THREAD_CORE_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, // 定义队列大小,防止占用内存过大 new LinkedBlockingQueue\u003c\u003e(THREAD_QUEUE_CAPACITY), threadFactory, // 使用CallerRunsPolicy() 保证所有任务不被丢弃 new ThreadPoolExecutor.CallerRunsPolicy()); } return executor; } } 其他实现 //懒汉式 //实现方式一:线程不安全 public class Singleton(){ //私有化的构造器 private Singleton(){} private static Singleton instance; public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } } //实现方式二:线程安全 public class Singleton(){ //私有化的构造器 private Singleton(){} private static Singleton instance; public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } } //实现方式三:双重检查锁→推荐 /* 多线程下,可能出现空指针问题,原因:JVM的优化和指令重排 解决:volatile */ public class Singleton(){ //私有化的构造器 private Singleton(){} private static volatile Singleton instance; public static Singleton getInstance(){ if(instance != null){//iyci判断,如果instance值不为空,不需要强占锁,直接返回对象 synchronized(Singleton.class){ if(instance == null){//第二次判断 instance = new Singleton(); } } } return instance; } } //实现方式四:静态内部类→推荐 /* JVM加载外部类的过程中,不会加载静态内部类,只有内部类的属性、方法调用时才会被加载→解决指令重排问题 */ public class Singleton(){ //私有化的构造器 private Singleton(){} private static clss SingletonHoler{ //内部类中声明并初始化外部类的对象 private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance(){ return SingletonHolder.INSTANCE; } } // 解决序列化破坏 public class Singleton() implements Serializable { /** * 私有化的构造器 */ private Singleton() {}; private static class SingletonHolder { /** * 内部类中声明并初始化外部类的对象 */ private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } /** * 当进行反序列化时,会自动调用该方法 * @return */ public Object readResolve() { return SingletonHolder.INSTANCE; } } /** * 解决序列化破坏 */ public class Singleton(){ private static boolean flag = false; // 实际开发中会用加密过的一个标志 /** * 私有化的构造器 */ private Singleton() { if(flag) { throw new RuntimeException("不能用反射破坏单例模式"); } flag = true; } private static class SingletonHolder { /** * 内部类中声明并初始化外部类的对象 */ private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } 总结 单例模式是23个模式中比较简单的模式,应用也非常广泛,如在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理这些Bean的生命期,决定什么时候创建出来,什么时候销毁,销毁的时候要如何处理,等等。如果采用非单例模式(Prototype类型),则Bean初始化后的管理交由J2EE容器,Spring容器不再跟踪管理Bean的生命周期
`,description:"",tags:null,title:"单例模式",uri:"/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/index.html"},{content:"个人博客 ",description:"",tags:null,title:"个人博客",uri:"/index.html"},{content:"修饰符.native 修饰什么时候使用 在我们需要监听一个组件的原生事件时,必须给对应的事件加上.native 修饰符,才能进行监 事件总线: Vue.prototype.$bus = new Vue(); this.$bus.$emit() this.$bus.$on() ",description:"",tags:null,title:"Vue知识点",uri:"/%E5%89%8D%E7%AB%AF/vue/vue%E7%9F%A5%E8%AF%86%E7%82%B9/index.html"},{content:"Vue ",description:"",tags:null,title:"Vue",uri:"/%E5%89%8D%E7%AB%AF/vue/index.html"},{content:"",description:"",tags:null,title:"Categories",uri:"/categories/index.html"},{content:"",description:"",tags:null,title:"Tags",uri:"/tags/index.html"}]