框架进阶(2)

建模语言

Unified Modeling Language,简称UML。 类图

以可视化图形方式来表述类与类之间的关系,方便理解.

类图的基本元素:

类;接口;属性 ;方法

类之间的关系:

依赖(Dependency)关系

在A类中的某个方法中把B类作为参数使用,具有临时性.

关联(Association)关系

在一个类中,把另一个类当做属性;

聚合(Aggregation)关系

表示一种强关联关系 学校和老师 学校不存在,老师依然存在

组合(Composition)关系

更强烈的关联关系 头和嘴 头不存在了 嘴也就没有存在的意义

泛化(Generalization)关系

类继承类, 接口继承接口

实现(Realization)关系

类实现接口

面向对象设计原则

继承 多态 提高程序代码复用性和可扩展性

![在这里插入图片描述](https://img-blog.csdnimg.cn/7315019218c04d5e91bda842091a69de.在这里插入图片描述
png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Z2i5ZCRY3bnvJY=,size_20,color_FFFFFF,t_70,g_se,x_16)

单一职责

一个类负责做一件事. 低耦合,高内聚

开闭原则

​ 对扩展开发,对修改关闭

​ 抽象功能,具体的实现可以扩展子类.
里氏替换原则

在任何父类出现的地方都可以用它的子类来替换,且不影响功能(多态)

Animal a = new Dog();

依赖倒置原则

高层模块不应该依赖底层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

在顶层不适合定义太多的功能,底层实现有的可能用不到的.

在中间设计接口,抽象类去扩展功能,底层按照自己的需要去实现即可.

迪米特原则

一个对象应当对其他对象尽可能少的了解,降低耦合

使用代理的思想,不直接对其他类进行访问

组合/聚合复用原则

总结
七大原则虽说是原则,但它们并不是强制性的,更多的是建议。遵照这些原则固然能帮助我们更好的规范我们的系统设计和代码习惯,但并不是所有的场景都适用,就例如接口隔离原则,在现实系统开发中,我们很难完全遵守一个模块 一个接口的设计,否则业务多了就会出现代码设计过度的情况,让整个系统变得
过于庞大,增加了系统的复杂度,甚至影响自己的项目进度。

Java 设计模式(java design patterns)

设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计 经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问 题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设 计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可 重用性、代码的可读性和代码的可靠性。

创建型模式结构型模式行为型模式 3 种

创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使 用分离”。提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。

结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,提供了代理、 适配器、桥接、装饰、外观、享元、组合 7 种结构型模式。

行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独 完成的任务,以及怎样分配职责。提供了模板方法、策略、命令、职责链、状态、 观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式。

常用设计模式:

一.单例(Singleton)模式:

在整个程序中只允许有一个对象.

创建对象 使用构造方法. 将构造方法私有化, 只能在本类中创建,这样我们就可以控制数量.向外界提供一个公共的访问方法.

Singleton 模式通常有两种实现形式。

第 1 种:懒汉式单例

该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例 。

/*
 * 懒汉式单例
 * 在类加载时,不会创建单例对象,在第一次访问时才会被创建
 *
 * 懒汉式单例会有线程安全问题,必须要加锁处理
 */
public class Singleton {

    //定义静态的
    private static Singleton instance;

    //让构造函数为 private,这样该类就不会被实例化
    private Singleton() {
    }

    //向外界提供获取实例的方法  加锁 synchronized 才能保证单例
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

第 2 种:饿汉式单例

该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之 前单例已经存在了。

/*
 * 饿汉式单例
 *一般又称为急切式单例
 *在类加载时,就会创建此单例对象,这种写法不会出现线程安全问题
 */
public class Singleton {

    //创建 Singleton 的一个对象
    private static Singleton instance = new Singleton();

    //让构造函数为 private
    private Singleton() {
    }

    //获取唯一可用的对象
    public static Singleton getInstance() {
        return instance;
    }
}
//懒汉式单例
public class Hungrysingleton {

    private static Hungrysingleton hungrysingleton;

    Hungrysingleton() {

    }
    
    public static Hungrysingleton getInstance() {
        if (hungrysingleton == null) {
            synchronized (Hungrysingleton.class) {
                if (hungrysingleton == null) {
                    hungrysingleton = new Hungrysingleton();
                }
            }
        }
        return hungrysingleton;
    }
}

二.工厂模式(Factory Pattern)

批量创建对象, 将创建对象与使用对象分离

按实际业务场景划分,工厂模式有 2 种不同的实现方式,分别是简单工厂模式、 抽象工厂模式。

简单工厂:

我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创 建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。 在简单工厂模式中创建实例的方法通常为静态(static)方法,因此简单工厂模 式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。

简单工厂模式的主要角色如下:

​ 工厂;负责生产对象的

​ 抽象产品;接口/抽象类 定义

​ 具体产品;实现了抽象的接口/抽象类的具体实现类 ,以抽象来表示具体.

三.代理模式

在有些情况下,一个客户不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。例如,购买火车票不一定要去火车站买,可以通过12306 网站或者去火车票代售点买。又如找保姆、找工作,买东西等都可以通过找中介完成。

代理模式优点:

1.保护目标对象

2.对目标的功能进行扩展

3.将用户和目标进行分类,降低了耦合度

模式的结构 :

1.抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现 的业务方法。

2.真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。

3。代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

代理实现可以分为静态代理和动态代理。
静态代理

静态代理一般适用于关系是固定的,代理某类事务必须实现接口,
如果需要代理多个目标对象,那么就需要实现更多的接口,后期维护比较麻烦.

动态代理

动态代理实现方式分为 jdk 动态代理cglib 动态代理

jdk动态代理:

其步骤如下:

1.编写一个委托类的接口,即静态代理的

2.实现一个真正的委托类,即静态代理的

3.创建一个动态代理类,实现 InvocationHandler 接口,并重写该invoke方法

4.在测试类中,生成动态代理的对象。

jdk代理实现原理使用的是java反射机制,可以动态获取目标类中代理的方法,

​ 不需要代理类指定的去实现某些抽象接口, 代理的扩展性好.

​ 动态生成代理对象, 要求目标类必需有实现接口.

cglib动态代理:

JDK 实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何 实现动态代理呢,这就需要 CGLib 了。CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦 截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对 final 修饰的类进行代理。JDK 动态代理与 CGLib 动态代理均是实现 Spring AOP 的基础。

Cglib 子类代理实现方法:

1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所 以直接引入 spring-core-xxx.jar 即可.

2.引入功能包后,就可以在内存中动态构建子类

3.代理的类不能为 final,否则报错

4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额 外的业务方法.

动态字节码技术

可以在运行中为目标类动态生成一个子类, 进行方法拦截,从而添加增强功能.

不能代理final所修饰的类, 目标类可以不实现任何接口.

spring中两种实现都支持 可以根据目标类是否实现接口,自动选择动态方式.