设计模式相关的知识点

**

设计模式相关的知识点

一、什么是设计模式
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
二、为什么要学习设计模式
1.看懂源代码:如果你不懂设计模式去看Jdk、Spring、SpringMVC、IO等等等等的源码,你会很迷茫,你会寸步难行
2.看看前辈的代码:你去个公司难道都是新项目让你接手?很有可能是接盘的,前辈的开发难道不用设计模式?
3.编写自己的理想中的好代码:我个人反正是这样的,对于我自己开发的项目我会很认真,我对他比对我女朋友还好,把项目当成自己的儿子一样
三、设计模式分类

  • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    四、设计模式的六大原则
    1.开放封闭原则
    2.里氏代换原则
    3.依赖倒转原则
    4.接口隔离原则
    5.迪米特法则(最少知道原则)
    6.单一职责原则
    五、单例模式
    创建方式:
    (主要使用懒汉和懒汉式)
    1.饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。
public class Demo1 {
   
    // 类初始化时,会立即加载该对象,线程安全,调用效率高
    private static Demo1 demo1 = new Demo1();
    //构造器
    private Demo1(){
        System.out.println("私有Demo1构造参数初始化");
    }
    public Demo1 getInstance(){
      return demo1;
    }
    public static void main(String[] args) {
        Demo1 s1 = Demo1.getInstance();
        Demo1 s2 = Demo1.getInstance();
        System.out.println(s1 == s2);
    }
}

懒汉式: 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。

public class Demo1 {
   
    // 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象
    private static Demo1 demo1;
    //构造器
    private Demo1(){
        System.out.println("私有Demo1构造参数初始化");
    }
    public synchronized static Demo1 getInstance(){
      if(demo1==null){
         demo1 = new Demo1();
      }
      return demo1;
    }
    public static void main(String[] args) {
        Demo1 s1 = Demo1.getInstance();
        Demo1 s2 = Demo1.getInstance();
        System.out.println(s1 == s2);
    }
}

静态内部方式:结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。

// 静态内部类方式
public class Demo3 {
    private Demo3() {
        System.out.println("私有Demo3构造参数初始化");
    }

    public static class SingletonClassInstance {
        private static final Demo3 DEMO_3 = new Demo3();
    }

    // 方法没有同步
    public static Demo3 getInstance() {
        return SingletonClassInstance.DEMO_3;
    }

    public static void main(String[] args) {
        Demo3 s1 = Demo3.getInstance();
        Demo3 s2 = Demo3.getInstance();
        System.out.println(s1 == s2);
    }
}

枚举单例: 使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。
//使用枚举实现单例模式 优点:实现简单、枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞 缺点没有延迟加载

public class Demo4 {

    public static Demo4 getInstance() {
        return Demo.INSTANCE.getInstance();
    }

    public static void main(String[] args) {
        Demo4 s1 = Demo4.getInstance();
        Demo4 s2 = Demo4.getInstance();
        System.out.println(s1 == s2);
    }

    //定义枚举
	private static enum Demo {
		INSTANCE;
		// 枚举元素为单例
		private Demo4 demo4;

		private Demo() {
			System.out.println("枚举Demo私有构造参数");
			demo4 = new Demo4();
		}

		public Demo4 getInstance() {
			return demo4;
		}
	}
}

双重检测锁方式 (因为JVM本质重排序的原因,可能会初始化多次,不推荐使用)
六、工厂模式
1.工厂模式分为简单工厂、工厂方法、抽象工厂模式
简单工厂 :用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
2.Spring开发中的工厂设计模式
1.Spring IOC
看过Spring源码就知道,在Spring IOC容器创建bean的过程是使用了工厂设计模式
Spring中无论是通过xml配置还是通过配置类还是注解进行创建bean,大部分都是通过简单工厂来进行创建的。
当容器拿到了beanName和class类型后,动态的通过反射创建具体的某个对象,最后将创建的对象放到Map中。
2.为什么Spring IOC要使用工厂设计模式创建Bean呢
在实际开发中,如果我们A对象调用B,B调用C,C调用D的话我们程序的耦合性就会变高。(耦合大致分为类与类之间的依赖,方法与方法之间的依赖。)
在很久以前的三层架构编程时,都是控制层调用业务层,业务层调用数据访问层时,都是是直接new对象,耦合性大大提升,代码重复量很高,对象满天飞
为了避免这种情况,Spring使用工厂模式编程,写一个工厂,由工厂创建Bean,以后我们如果要对象就直接管工厂要就可以,剩下的事情不归我们管了。Spring IOC容器的工厂中有个静态的Map集合,是为了让工厂符合单例设计模式,即每个对象只生产一次,生产出对象后就存入到Map集合中,保证了实例不会重复影响程序效率。
七、代理模式
.1.什么是代理模式

通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。(也就是AO的P微实现)
代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能,这也和Spring的(面向切面编程)很相似
2.代理模式应用场景
Spring AOP、日志打印、异常处理、事务控制、权限控制等
3.代理的分类
静态代理(静态定义代理类)
动态代理(动态生成代理类,也称为Jdk自带动态代理)
Cglib 、javaassist(字节码操作库)
4.三种代理的区别
静态代理:简单代理模式,是动态代理的理论基础。常见使用在代理模式
jdk动态代理:使用反射完成代理。需要有顶层接口才能使用,常见是mybatis的mapper文件是代理。
cglib动态代理:也是使用反射完成代理,可以直接代理类(jdk动态代理不行),使用字节码技术,不能对 final类进行继承。(需要导入jar包)
八、建造者模式
1.什么是建造者模式

建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的方式进行创建。
工厂类模式是提供的是创建单个类的产品
而建造者模式则是将各种产品集中起来进行管理,用来具有不同的属性的产品
建造者模式通常包括下面几个角色:
uilder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
Product:要创建的复杂对象。
2.建造者模式的使用场景
使用场景:
需要生成的对象具有复杂的内部结构。
需要生成的对象内部属性本身相互依赖。
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
JAVA 中的 StringBuilder就是建造者模式创建的,他把一个单个字符的char数组组合起来
Spring不是建造者模式,它提供的操作应该是对于字符串本身的一些操作,而不是创建或改变一个字符串。
九、模板方法模式
1.什么是模板方法

模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。
模板方法使得子类可以不改变一个算法的结构来重定义该算法的
2.什么时候使用模板方法
实现一些操作时,整体步骤很固定,但是呢。就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
3.实际开发中应用场景哪里用到了模板方法
其实很多框架中都有用到了模板方法模式
例如:数据库访问的封装、Junit单元测试、servlet中关于doGet/doPost方法的调用等等
4.现实生活中的模板方法
例如:
去餐厅吃饭,餐厅给我们提供了一个模板就是:看菜单,点菜,吃饭,付款,走人
(这里 “点菜和付款” 是不确定的由子类来完成的,其他的则是一个模板。)
十、外观模式
外观模式:也叫门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
它向现有的系统添加一个接口,用这一个接口来隐藏实际的系统的复杂性。
使用外观模式,他外部看起来就是一个接口,其实他的内部有很多复杂的接口已经被实现。
十一、策略模式
1.什么是策略模式
定义了一系列的算法 或 逻辑 或 相同意义的操作,并将每一个算法、逻辑、操作封装起来,而且使它们还可以相互替换。(其实策略模式Java中用的非常非常广泛)
我觉得主要是为了 简化 if…else 所带来的复杂和难以维护。
2.策略模式应用场景
策略模式的用意是针对一组算法或逻辑,将每一个算法或逻辑封装到具有共同接口的独立的类中,从而使得它们之间可以相互替换。
例如:我要做一个不同会员打折力度不同的三种策略,初级会员,中级会员,高级会员(三种不同的计算)。
例如:我要一个支付模块,我要有微信支付、支付宝支付、银联支付等
3.策略模式的优点和缺点
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性非常良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
十二、原型模式
1.什么是原型模式
原型设计模式简单来说就是克隆
原型表明了有一个样板实例,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
2.原型模式的应用场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。这时我们就可以通过原型拷贝避免这些消耗。
通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
我们Spring框架中的多例就是使用原型。
3.原型模式的使用方式
实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此Prototype类需要将clone方法的作用域修改为public类型。
3.1原型模式分为浅复制和深复制
(浅复制)只是拷贝了基本类型的数据,而引用类型数据,只是拷贝了一份引用地址。
(深复制)在计算机中开辟了一块新的内存地址用于存放复制的对象。
十三、观察者模式
1.什么是观察者模式

先讲什么是行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作,进一步明确对象的职责。
观察者模式,是一种行为性模型,又叫发布-订阅模式,他定义对象之间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
2.模式的职责
观察者模式主要用于1对N的通知。当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出相应。
实现有两种方式:
推:每次都会把通知以广播的方式发送给所有观察者,所有的观察者只能被动接收。
拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定。
3.观察者模式应用场景
关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。事件多级触发场景。
跨系统的消息交换场景,如消息队列、事件总线的处理机制。

你可能感兴趣的:(java)