设计模式
2021-05-18 23:57:59 16 举报
AI智能生成
设计模式是一种在软件开发中被反复使用、具有普遍适用性的解决方案,它可以帮助开发人员解决在软件设计和开发中遇到的特定问题。设计模式通常以四人组合方式命名,包括模式类型、问题描述、解决方案和效果描述。设计模式的目的是提高代码的可重用性、可扩展性和可维护性,使软件更加灵活、易于修改和扩展。常见的设计模式包括单例模式、工厂模式、观察者模式等。通过使用设计模式,开发人员可以更加高效地完成软件开发任务,并提高软件质量和可靠性。
作者其他创作
大纲/内容
设计模式
简介
设计模式不是代码,而是解决某一类问题提出的通用方法,是模板
设计模式不涉及具体语言,它是站在了软件结构的角度去看待软件,而非软件实现的角度
设计模式不局限于四人组提出的23种,但是这23种已经囊括了我们所需要面对的绝大部分场景了
设计模式需要遵循七大设计原则
设计模式的本质
提高软件的可维护性、通用性和扩展性
并且降低软件的复杂度
七大设计原则
单一职责原则
一个类只负责一个单一的职责,将对象解耦,提高内聚
接口隔离原则
类不该实现不需要的接口方法,即各个类都有自己专属的接口
依赖倒转原则
中心思想
面向接口编程
依赖倒转的三种方式
基于实现接口
基于构造函数注入
基于setter方法注入
里氏替换原则
所有引用基类的地方必须能透明的使用其子类的对象
开闭原则(Open Closed Principle)
对提供方的扩展开放,而对使用方的关闭修改
比如pom依赖,提供方后期的扩展应该完全兼容之前的版本
迪米特法则
一个对象应该对其他对象保持最少的了解===》低耦合
合成复用原则
优先使用合成、聚合等关联关系实现,其次再考虑继承实现
三种类型(共23种)
创造性模式
单例模式
核心思想
把需要多次使用到的类,特别是大对象,读取资源的类的实例唯一化,减少系统资源消耗
实现方式
饿汉式(静态变量)
实现思路
构造方法私有(防止new出来对象)
类内部创建对象
向外暴露静态方法(getInstance)返回对象
代码实现
Singleton类
pre style=\
Test测试类
存在的问题
类一加载就会存在静态变量,占用资源(其实并不要紧)
饿汉式(静态代码块)
通过静态代码块创建静态对象
懒汉式(线程不安全)
声明静态变量,赋值为null
向外暴露静态方法(getInstance),如果静态变量为null,就new Singleton,否则直接返回静态变量
多线程并发执行时,线程不安全
懒汉式(线程安全、同步方法)
getInstance方法用synchronizied修饰,达到线程安全
效率太低了,开发当中不推荐使用
每次调用到getInstance方法都会加锁,其实只有第一次使用new对象时才需要加锁
懒汉式(线程安全、同步代码块)--- 这是个错误的方法
getInstance方法中需要new实例的地方用synchronizied修饰,实际上并不能达到进程安全的效果
这种方法其实并不能达到线程安全的目的,其实是错误的一种解决方法
⭐双重检查锁定(DCL)
声明静态变量,用volatile修饰,赋值为null
向外暴露静态方法(getInstance),如果静态变量为null,就进入同步代码块,内部再次判断instance是否为空,如果instance为空就new Singleton,否则直接返回静态变量
DCL单例为什么要用volatile修饰静态变量
这是因为new一个对象并不是一个原子操作,共有三步:1、开辟内存空间 2、执行构造方法,初始化对象 3、把这个对象指向开辟的内存空间在多线程并发操作下,可能存在指令重排序,导致执行了A线程执行了13,时间片切换给B线程判断对象为空,执行了123,这样就存在了两个对象
⭐静态内部类
声明静态内部类,静态内部类内部声明Singleton类型的静态变量
向外暴露静态方法(getInstance),然后静态内部类的静态对象
静态内部类如何实现懒加载和线程安全?
类加载时是不加载它的静态内部类的,那么我们就可以通过把静态变量的声明和赋值写在静态内部类中,当调用getInstance返回静态内部类的静态变量时才会加载静态内部类,从而实现懒加载,而类加载是线程安全的
类的加载的线程安全是因为ClassLoader.loadClass()这个方法调用全程都是在synchronized代码块中的,所以不必担心线程安全问题
枚举
枚举的优点
可以防止反射破坏单例
哪里用到了单例模式?
jdk的Runtime类,用的是饿汉式的单例
spring的bean也用到了单例模式
工厂模式
实现创建者和调用者的分离,创建对象不用new,而是用工厂方法代替
简单工厂模式(静态工厂模式)(只有一个工厂类,生产同一等级结构(同一种类)中的任意产品(新增产品需要覆盖已有代码))
定义一个产品接口,所有产品都实现此接口
定义多个产品类,实现产品接口
定义工厂类,声明静态方法
产品接口
具体产品类
工厂类
客户端
图解
优点
简单,很多地方都用了简单工厂模式,比如jdk的calendar类
缺点
必须修改工厂类,违反了开闭原则
工厂方法模式(每个工厂类都实现工厂接口,工厂类用来生产同一等级结构(同一种类)中的固定产品)
定义一个工厂接口,所有工厂都实现此接口,内部定义单个产品
每类产品定义一个工厂类,实现工厂接口
工厂接口
具体工厂类
抽象工厂模式(每个工厂类都实现工厂接口,工厂接口就是一个产品族,围绕一个工厂接口,创建其他工厂类)
定义一个工厂接口,所有工厂都实现此接口,内部定义多个产品
定义产品工厂类,实现工厂接口
原型模式
简化对象的创建过程,提高效率,并且动态获得对象运行状态
浅拷贝
重写Object基类的clone方法
深拷贝
⭐通过对象序列化实现
需要为每个类配备克隆方法,如果原来的类没有就需要自己添加,从而会违背ocp原则
哪里用到了原型模式?
spring框架中的bean的scope=\"prototype\"
建造者模式
客户端不需要关注产品的创建过程,将使用和创建解耦
四个角色
House(产品类)
Builder(抽象构造者)
XXXHouseBuilder(具体构造者)
HouseDirector(指挥者)
Consumer(消费者)
产品类
抽象构造者
具体构造者
指挥者
消费者
结构性模式
适配器模式
桥接模式
装饰模式
组合模式
外观模式
享元模式
代理模式
静态代理
一个被代理对象需要一个代理对象,代码量翻倍
被代理方法接口
被代理类
代理类
动态代理
通过Proxy的静态方法newProxyInstance获得动态代理对象
通过实现InvocationHandler接口的invoke方法实现代理对象的方法调用,这里是因为Proxy.newProxyInstance的参数传入了一个invocationhandler,我们传入的是this,就会调用这个动态代理生成类的invoke方法来调用方法
动态生成代理工具类
行为型模式
模板方法模式
命令模式
访问者模式
迭代器模式
观察者模式
中介者模式
备忘录模式
解释器模式
状态模式
策略模式
策略模式的思想就是同一个对象,但是我们可以使用不同的想法(策略)进行操作
组成(3部分)
策略接口(这是为了后面操作类的类方法调用的时候传递的接口参数)
策略接口
策略实现类(这个就是我们的具体策略实现了)
骑车旅游
坐火车旅游
坐飞机旅游
实际调用策略类
测试
控制台输出
这里建议大家实现一个比较器,看看自己是否真的掌握了(先自己写再看代码哦)
比较排序代码
首先定义动物类,继承动物类的猫和狗,使用泛型
动物基类
猫
狗
定义策略模式接口和具体的策略实现类
策略模式接口
策略模式实现类
按照年龄排序
按照身高排序
排序工具类
测试类
责任链模式
0 条评论
回复 删除
下一页