java 设计模式学习记录

设计模式目的是: 提高代码的复用性,扩展性, 减少代码的冗余,重构整体的代码。

六大原则:

1: 开闭原则, 易于扩展和升级及维护。 前提是基于接口和抽象类。 正常生产中都是基于接口和抽象类的。   

   对已经正常使用的接口方法禁止修改,因为一旦修改后测试不完全,很容易影响原来正常的流程造成未知的bug.

  对增加开放, 原来的接口方法不动, 需要就增加一个接口, 不会影响原来正常的接口流程。

2: 里氏代换原则,  是对开闭原则的补充。

  父类出现的地方, 子类一定可以出现,当子类可以替换父类而软件功能不受影响时,父类才是真正的被复用。子类可以在父类的基础增加新的方法。

  里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实  现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3:依赖倒转原则

这是开闭原则的基础, 基于接口编程,依赖于抽象,而不依赖与基础。

4:接口隔离原则

不要在一个接口里面放很多的方法,这样会显得这个类很臃肿不堪。接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加轻便灵活。

5:迪米特法则

一个对象尽量少和不相干的对象产生相互作用,使的功能模块相对的独立。

需要和其他对象联系时,最好通过第三者进行关联通信。

6:合成复用原则

在进行复用时, 尽量使用合成或者集合等方式进行, 其次才考虑使用继承。

要使用已有的对象时,最好将其纳入到新的对象中,使他成为新对象的一部分。就可以使用已有对象的功能。

 

设计模式的分类:

 1:创建型:

      工厂方法,抽象工厂,单例, 建造者,原型。

 2:结构型

      适配器,代理,装饰,外观,桥接, 组合, 享元

 3:  行为型

     策略,责任链,模版方法,观察者,迭代,命令, 备忘录, 状态,访问者,终结者,解释器

 

一: 工厂模式: 简单工厂,抽象工厂,静态工厂,工厂方法

   工厂模式的目的: 将创建者和使用者分离开来。 工厂就是创建,生产。

   优点:代码结构简单,满足开闭原则,对扩展开放,对修改关闭。

   缺点:扩展时繁琐。

  springmvc中的 beanFactory, IOC控制反转等都是工厂模式。

 

二: 策略模式 + 工厂 

 对算法的包装,把使用算法和算法分开。

  用于解决多重if 判断。

 

 


三: 责任链模式 + 工厂,

多个对象处理同一个任务。对象使用链式存储结构,每一个对象都知道自己的下一个对象。

 或者工厂中保证顺序

  应用场景: 多条件流程判断, 权限控制,filer过滤器等。

 

 

四: 模版方法 + 工厂,

    将共同的行为抽象到父类中实现, 不同的行为定义为抽象, 交由子类实现, 通过继承实现代码复用,通过父类调用子类实现操作。将共同的行为抽象为框架。

 优点: 将共同行为抽象到父类中,去除子类重复代码, 子类实现自己的细节,有助于扩展,符合开闭原则。

缺点: 每一个不通的实现都需要增加一个子类,会导致类的个数增加,更加抽象。

 模版方法与策略的区别:

  模版是 将共同的行为抽象到父类实现, 子类实现不同的行为。 子类扩展维护性好, 模版关注的是一种算法

  策略是定义公共的抽象接口, 子类各自实现不同的行为。 策略关注的是多种算法

 

 

五: 装饰者模式

在不改变原有对象的功能下,动态扩展或者撤销功能, 按照想要的顺序执行。

分为: 

   1: 父类抽象组件: 定义一个抽象的接口,规范准备扩展的功能的类

   2: 父类抽象组件的具体实现组件: 要被附加扩展功能的类, 实现父类抽象组件的类。

   3: 抽象装饰组件: 持有对具体实现组件的引用并定义父类抽象组件一致的接口

  4: 具体装饰组件: 实现抽象装饰组件,负责对具体实现组件添加扩展额外的功能。

 

与责任链的区别:

装饰者是从子类开始,找到最上层的父类开始执行, 执行完父类在执行子类, 执行顺序与责任链相反。

责任链是先执行第一步,在第二步,第三步。

IO流就是用的装饰者模式 :  FileReader,    Reader.

 

 

6:代理模式

代理:  相等于中介一样的, 客户端访问 》 代理 》 目标

  代理和目标都实现相同的接口, 可以在代理中扩展, 而不需要改动目标类。

 满足开闭原则,扩展开放, 修改关闭

 

代理模式分为两种:

  1: 静态代理, 手动创建 代理类, 效率低

        两种实现方式:   继承, 接口实现

               

  2: 动态代理

      两种实现方式:

        2.1:   jdk动态代理 

                  通过实现  InvocationHandler 接口, 反射 方式实现代理

        2.2: cglib动态代理 

                 通过  asm字节码框架,转换字节码并生成子类实现代理。

                 asm 是一个强大的, 高性能的,高质量的字节码技术框架。

      jdk与cglib的区别:

       jdk通过实现接口,反射方式实现代理, 必须是接口, 不是接口的类无法代理

      cglib 通过封装asm字节码框架,生成子类继承目标类的方式实现代理。 无法重写代理final修饰的方法。 

 

 

7: 观察者模式

相当于 发布订阅,   一个发布者, 一个订阅者, 一个主题。 

 

 

8: 门面模式也称外观模式

提供统一的访问接口, 隐藏内部实现

 

9:状态模式

一个对象根据内部的状态而执行其行为,内部的状态改变后,其行为也会对应的改变,在不同的状态间切换

一个对象的行为取决于它的状态,并且它在运行时根据它的状态而改变它的行为

状态模式与策略模式是类似的,区别是:

状态模式 : 在不通的状态间切换,封装的是对象的状态, 对象针对的是不同的行为

策略模式:根据具体的情况选择策略, 封装的是算法或策略, 对象针对的是相同的行为

 

 

10 适配器

相当于转换器,  一个不能直接使用的接口, 通过转换变为可以直接使用的接口。 这个转换类就是适配器

类适配器同过继承两种方式

对象适配器则是组合模式

组合优于继承

 

 

11 单例模式

在jvm中保证只有一个实例存在。

单例分为:

懒汉式, 恶汉式, 静态内部类单例,静态块,枚举等。

懒汉式用的时候加载, 初始化的时候比较慢, 需要加双重检验锁。

恶汉式, 一开始就创建, 天生线程安全。

静态内部类,继承了懒汉式的优点,不需要加锁。

枚举,天生线程安全,可以有效防止反射破解。

推荐使用枚举单例

反射破解用的是权限参数设置为true, 暴力破解 构造函数.setAccessible(true),反射就可以访问无参或有参的构造方法破解单例 

反射: 动态的获取所有的类信息, 如方法,属性。

如果是单例模式, 推荐使用枚举, 无法使用反射破解, 天生线程安全。在反射创建对象时,jdk源码中判断如果是反射创建枚举,则会直接抛出异常。

enum 单例是最优秀的实现方式,  

enum单例源码分析

/**
 * @ClassName: EnumDecompose
 * @Description:  enum源码分析
 * @Author: tangjiandong
 * @Time: 2020/8/8 18:03
 * @Viersion 1.0
 */
public enum EnumDecompose {
    SINGLE;


    public void test()
    {
        System.out.println("-----enum单例源码分析");
    }
}

下图是反编译出来的, 将定义的枚举类转换为普通类继承枚举类, 定义的枚举就是类对象。 

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   EnumDecompose.java

package com.tang.single;

import java.io.PrintStream;

public final class EnumDecompose extends Enum
{

    public static EnumDecompose[] values()
    {
        return (EnumDecompose[])$VALUES.clone();
    }

    public static EnumDecompose valueOf(String name)
    {
        return (EnumDecompose)Enum.valueOf(com/tang/single/EnumDecompose, name);
    }

    private EnumDecompose(String s, int i)
    {
        super(s, i);
    }

    public void test()
    {
        System.out.println("-----enum\u5355\u4F8B\u6E90\u7801\u5206\u6790");
    }

    public static final EnumDecompose SINGLE;
    private static final EnumDecompose $VALUES[];

    static 
    {
        SINGLE = new EnumDecompose("SINGLE", 0);
        $VALUES = (new EnumDecompose[] {
            SINGLE
        });
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值