design pattern 设计模式

1 设计模式简介

在这里插入图片描述

1.2 设计模式概念

1. 设计模式(Designpattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
2. 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
3. 设计模式使代码编制真正工程化,设计模式是软件工程的基石
4. 项目中合理的运用设计模式可以完美的解决很多问题

模式:在某些场景下,针对某类问题的某种通用的解决方案。
场景:项目所在的环境
问题:约束条件,项目目标等
解决方案:通用、可复用的设计,解决约束达到目标。

1.3 设计模式七大原则

设计模式就是基于以下七大原则的实现

1.3.1 开闭原则(Open Close Principle,OCP)

1. 开闭原则是指一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。
2. 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
3. 为了使程序的扩展性好,易于维护和升级,需要使用接口和抽象类。
4. 开闭原则的核心思想是面向抽象编程。
5. 通过接口和抽象类为软件定义一个相对稳定的抽象层,而将相同的可变因素封装到相同的具体实现类中。软件中稳定的用抽象或接口约束,易变的用实现类扩展

1.3.2 依赖倒置原则(Dependence Inversion Principle,DIP)

1. 依赖倒置原则是开闭原则的基础:针对接口编程,依赖于抽象而不依赖于具体。尽量实现,不实例化,造成依赖太多,代码量增大
2. 是指设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象。
3. 通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并且能降低修改程序所造成的风险。
4. 

1.3.3 里氏替换原则(Liskov Substitution Principle)

(1)概念
1. 里氏替换原则(Liskov Substitution Principle)面向对象设计基本设计原则之一
2. 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。
3. 只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
4. 里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范
5. 里氏替换原则就是继承
(2)里氏原则优缺点
优点:
1. 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性
2. 提高代码的重用性
3. 子类可以形似父类但又异于父类
4. 提高代码的扩展性,实现父类的方法就可以为所欲为了,很多开源框架的扩展接口都是通过继承父类来完成的
5. .提高产品或者项目的开放性

缺点:
1. 继承是侵入性的。只要继承 就必须拥有父类的所有方法和属性
2. 降低了代码的灵活性。子类必须拥有父类的所有方法和属性,让子类自由的世界多了写约束
3. 增强了耦合性,当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果————大段的代码需要重构。
4. 如果子类不能完整的实现父类的方法,或者父类方法在子类已经发生“畸变”,建议断开继承关系,采用依赖、聚集、组合等关系代替继承。
5. .提高产品或者项目的开放性

(3)里氏原则规范
里氏替换原则为继承定义了良好的规范:
1. 子类可以扩展父类的功能,但不能改变父类原有的功能。
2. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
3. 子类可以增加自己特有的方法。
4. 子类重载父类方法时,方法的形参要比父类的宽,宽指的重载时类型可以变大如:父类是HashMap 子类用Map类型,当然也可以是其他类型
5. 重写方法的输出结果也就是返回值可以缩小,就是说子类的方法返回值 必须小于等于父类的返回值范围,,,比如父类的返回值是T ,子类返回值必须满足 ? extends T 或者 T类型或者 ?implements T

1.3.4 接口隔离原则(Interface Segregation Principle,ISP)

1. 接口隔离原则:使用多个隔离的接口,比使用单个接口要好。降低依赖,降低耦合。
2. 一个类对另一个类的依赖应该建立在最小的接口之上
3. 建立单一接口(接口中方法少而专),接口尽量细化,,不要建立臃肿庞大的接口。

1.3.5 迪米特法则(最少知道原则)(Demeter Principle)

1. 一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
2. 一个类应该对自己需要耦合或调用的类知道得最少,仅仅知道依赖类的public属性或者方法就最好

1.3.6 合成复用原则(Composite/Aggregate Reuse Principle,CARP)

1. 尽量使用组合(has-a)/聚合(contanins-a)的方式,而不是继承关系达到软件复用的目的。
2. 可以使用系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成影响相对影响较少。

1.3.7 单一职责原则

1. 单一职责(SimpleResponsibility Principle,SRP)是指不要存在多于一个导致类变更的原因。
2. 单一职责(SimpleResponsibility Principle,SRP)是指不要存在多于一个导致类变更的原因。
3. 可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。总体来说,就是一个类、接口或方法只负责一项职责。
4. 

1.3.8 设计原则总结

学习设计原则是学习设计模式的基础。在实际开发过程中,并不要求所有代码都遵循设计原则,我们要考虑人力、时间、成本、质量,不能刻意追求完美,但要在适当的场景遵循设计原则这体现的是一种平衡取舍,可以帮助我们设计出更加优雅的代码结构。

1.4 设计模式的三个分类

1. 创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
2. 结构型模式:把类或对象结合在一起形成一个更大的结构。
3. 行为型模式:类和对象如何交互,及划分责任和算法。

在这里插入图片描述

2 创建型模式

2.1 单例模式

1. 单例模式:某个类中只能有一个实例,提供一个全局的访问点

2.1.1 单例模式应用场景

1. 单例模式:(Singleton Pattern)指确保一个类在任何情况下都绝对只有一个实例(堆内存中只存在一个该类对象),提供一个全局访问点
2. 单例模式是创建型模式

2.1.2 饿汉式(立即加载)单例模式

(1)概念
1. 饿汉式单例模式在类加载时就立即初始化,并且创建单例对象
2. 饿汉式单例模式绝对线程安全,在线程还没有出现以前就实例化了,不会存在线程访问安全问题
3. 饿汉式单例模式适用于单例对象较少的情况
4. 优点::没有任何锁,执行效率高,用户体验比懒汉式单例模式好
5. 缺点:不管使用不使用该实例,类加载的时候就初始化,占空间,浪费内存
(2)声明时创建对象实现饿汉式单例模式
package com.zx;

/**
 * 声明时创建对象实现饿汉式单例模式
 */
public class HungrySingleton {
    //定义本类型静态常量对象
    private static final HungrySingleton hungrySingleton = new HungrySingleton();
    
    //私有化无参构造方法:只有自己可以创建自己的实例
    private HungrySingleton(){
        
    }

    /**
     * 对外提供初始化获取实例对象方法
     * @return 返回上诉属性对象
     */
    public static HungrySingleton getInstance(){
        return hungrySingleton;
    }
            
            
            
}


测试

package com.zx;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class HungrySingletonTest {

    @Test
    @DisplayName("声明时创建对象实现饿汉式单例模式")
    void getInstance() {
        HungrySingleton singleton1 = HungrySingleton.getInstance();
        HungrySingleton singleton2 = HungrySingleton.getInstance();
        HungrySingleton singleton3 = HungrySingleton.getInstance();
        HungrySingleton singleton4 = HungrySingleton.getInstance();
        HungrySingleton singleton5 = HungrySingleton.getInstance();
        System.out.println(singleton1);
        System.out.println(singleton2);
        System.out.println(singleton3);
        System.out.println(singleton4);
        System.out.println(singleton5);
    }
}

在这里插入图片描述

(3)使用静态代码块实现饿汉式单例模式

单例;类

package com.zx;

/**
 * 静态代码块实现饿汉式单例模式
 */
public class HungrySingleton {
    //1. 声明本类型静态常量对象
    public static final HungrySingleton hungrySingleton;

    //使用静态代码块初始化属性对象
    static{
        hungrySingleton = new HungrySingleton();
    }

    //3. 私有化无参构造方法:只有自己可以创建自己的实例
    private HungrySingleton(){

    }

    /**
     * 对外提供初始化获取实例对象方法
     * @return 返回上诉属性对象
     */
    public static HungrySingleton getInstance(){
        return hungrySingleton;
    }
}

测试线程

package com.zx;

public class HungryThread implements  Runnable {
    @Override
    public void run() {
        //获取单例类对象
        HungrySingleton singleton = HungrySingleton.getInstance();
        //打印出当前线程
        System.out.println("property"+Thread.currentThread().getName()+":"+singleton);
    }
}

测试类

package com.zx;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class HungrySingletonTest {

    @Test
    @DisplayName("静态代码块实现饿汉式单例模式")
    void getInstance() {
        //1. 定义线程数组
        Thread[] threads = new Thread[100];
        //2. 循环打印
        for (int i = 0; i <100 ; i++) {
            //新建线程对象,将线程对象放入数组
            threads[i] = new Thread(new HungryThread());
        }

        for (int i = 0; i < 100 ; i++) {
            //循环启动线程
            threads[i].start();
        }
        System.out.println("main end");
    }
}

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值