Java面试知识点(全)-设计模式二

news2024/11/27 23:39:30

Java面试知识点(全)
导航: https://nanxiang.blog.csdn.net/article/details/130640392
注:随时更新

13.模板模式

定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
  通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。
Spring (FileSystemXmlApplicationContext),类路径加载配置文件(ClassPathXmlApplicationContext),以及根据项目上下文目录(XmlWebApplicationContext)加载配置文件
抽象父类(AbstractClass):实现了模板方法,定义了算法的骨架。
  具体类(ConcreteClass):实现抽象类中的抽象方法,即不同的对象的具体实现细节。
在这里插入图片描述

来举个例子: 比如我们做菜可以分为三个步骤 (1)备料 (2)具体做菜 (3)盛菜端给客人享用,这三部就是算法的骨架 ;然而做不同菜需要的料,做的方法,以及如何盛装给客人享用都是不同的这个就是不同的实现细节。
下来我们就代码实现如下
 a. 先来写一个抽象的做菜父类:

public abstract class DodishTemplate {    
    /**
     * 具体的整个过程
     */
    protected void dodish(){
        this.preparation();
        this.doing();
        this.carriedDishes();
    }
    /**
     * 备料
     */
    public abstract void preparation();
    /**
     * 做菜
     */
    public abstract void doing();
    /**
     * 上菜
     */
    public abstract void carriedDishes ();
}

b. 下来做两个番茄炒蛋(EggsWithTomato)和红烧肉(Bouilli)实现父类中的抽象方法

/**
 * 西红柿炒蛋
 * @author aries
 */
public class EggsWithTomato extends DodishTemplate{
    @Override
    public void preparation() {
        System.out.println("洗并切西红柿,打鸡蛋。");
    }
    @Override
    public void doing() {
        System.out.println("鸡蛋倒入锅里,然后倒入西红柿一起炒。");
    }
    @Override
    public void carriedDishes() {
        System.out.println("将炒好的西红寺鸡蛋装入碟子里,端给客人吃。");
    }
}

/**
 * 红烧肉
 * @author aries
*/
public class Bouilli extends DodishTemplate{
    @Override
    public void preparation() {
        System.out.println("切猪肉和土豆。");
    }
    @Override
    public void doing() {
        System.out.println("将切好的猪肉倒入锅中炒一会然后倒入土豆连炒带炖。");
    }
    @Override
    public void carriedDishes() {
        System.out.println("将做好的红烧肉盛进碗里端给客人吃。");
    }
}

c. 在测试类中我们来做菜

public class App {
   public static void main(String[] args) {
       DodishTemplate eggsWithTomato = new EggsWithTomato();
       eggsWithTomato.dodish();
       System.out.println("-----------------------------");
       DodishTemplate bouilli = new Bouilli();
       bouilli.dodish();
   }
}
(1)具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。
(2)代码复用的基本技术,在数据库设计中尤为重要。
(3)存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。

14、策略模式(strategy)

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下:

在这里插入图片描述

图中ICalculator提供同意的方法,

//AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类:
//首先统一接口:

public interface ICalculator {  
    public int calculate(String exp);  
}  
//辅助类:
public abstract class AbstractCalculator {  
    public int[] split(String exp,String opt){  
        String array[] = exp.split(opt);  
        int arrayInt[] = new int[2];  
        arrayInt[0] = Integer.parseInt(array[0]);  
        arrayInt[1] = Integer.parseInt(array[1]);  
        return arrayInt;  
    }  
}  
//三个实现类:
public class Plus extends AbstractCalculator implements ICalculator {  
    @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"\\+");  
        return arrayInt[0]+arrayInt[1];  
    }  
}  
public class Minus extends AbstractCalculator implements ICalculator {  
    @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"-");  
        return arrayInt[0]-arrayInt[1];  
    }  
  
}  
public class Multiply extends AbstractCalculator implements ICalculator {  
     @Override  
    public int calculate(String exp) {  
        int arrayInt[] = split(exp,"\\*");  
        return arrayInt[0]*arrayInt[1];  
    }  
}  
//简单的测试类:
public class StrategyTest {  
    public static void main(String[] args) {  
        String exp = "2+8";  
        ICalculator cal = new Plus();  
        int result = cal.calculate(exp);  
        System.out.println(result);  
    }  
}  
输出:10

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

15、模板方法模式(Template Method)

解释一下模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1…n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用,先看个关系图:

在这里插入图片描述

就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用,看下面的例子:

public abstract class AbstractCalculator {  
    /*主方法,实现对本类其它方法的调用*/  
    public final int calculate(String exp,String opt){  
        int array[] = split(exp,opt);  
        return calculate(array[0],array[1]);  
    }  
    /*被子类重写的方法*/  
    abstract public int calculate(int num1,int num2);  
    public int[] split(String exp,String opt){  
        String array[] = exp.split(opt);  
        int arrayInt[] = new int[2];  
        arrayInt[0] = Integer.parseInt(array[0]);  
        arrayInt[1] = Integer.parseInt(array[1]);  
        return arrayInt;  
    }  
}  
public class Plus extends AbstractCalculator {  
    @Override  
    public int calculate(int num1,int num2) {  
        return num1 + num2;  
    }  
}  
测试类:
public class StrategyTest {  
    public static void main(String[] args) {  
        String exp = "8+8";  
        AbstractCalculator cal = new Plus();  
        int result = cal.calculate(exp, "\\+");  
        System.out.println(result);  
    }  
}  

我跟踪下这个小程序的执行过程:首先将exp和"\+"做参数,调用AbstractCalculator类里的calculate(String,String)方法,在calculate(String,String)里调用同类的split(),之后再调用calculate(int ,int)方法,从这个方法进入到子类中,执行完return num1 + num2后,将值返回到AbstractCalculator类,赋给result,打印出来。正好验证了我们开头的思路。

16、观察者模式(Observer)

包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图。观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:

在这里插入图片描述

我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码:

//一个Observer接口:
public interface Observer {  
    public void update();  
}  
//两个实现类:
public class Observer1 implements Observer {  
    @Override  
    public void update() {  
        System.out.println("observer1 has received!");  
    }  
}  
public class Observer2 implements Observer {  
    @Override  
    public void update() {  
        System.out.println("observer2 has received!");  
    }  
}  
//Subject接口及实现类:
public interface Subject {  
    /*增加观察者*/  
    public void add(Observer observer);  
    /*删除观察者*/  
    public void del(Observer observer);  
    /*通知所有的观察者*/  
    public void notifyObservers();  
    /*自身的操作*/  
    public void operation();  
}  

public abstract class AbstractSubject implements Subject {  
    private Vector<Observer> vector = new Vector<Observer>();  
    @Override  
    public void add(Observer observer) {  
        vector.add(observer);  
    }  
    @Override  
    public void del(Observer observer) {  
        vector.remove(observer);  
    }  
    @Override  
    public void notifyObservers() {  
        Enumeration<Observer> enumo = vector.elements();  
        while(enumo.hasMoreElements()){  
            enumo.nextElement().update();  
        }  
    }  
} 
public class MySubject extends AbstractSubject {  
    @Override  
    public void operation() {  
        System.out.println("update self!");  
        notifyObservers();  
    }  
  
}  

测试类:
public class ObserverTest {  
    public static void main(String[] args) {  
        Subject sub = new MySubject();  
        sub.add(new Observer1());  
        sub.add(new Observer2());  
        sub.operation();  
    }  
}  
输出:
update self!
observer1 has received!
observer2 has received!

这些东西,其实不难,只是有些抽象,不太容易整体理解,建议读者:根据关系图,新建项目,自己写代码(或者参考我的代码),按照总体思路走一遍,这样才能体会它的思想,理解起来容易!

17、迭代器模式(Iterator)

顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。我们看下关系图:

在这里插入图片描述

这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例,我们来看看实现代码:

//两个接口:
public interface Collection {  
    public Iterator iterator();  
    /*取得集合元素*/  
    public Object get(int i);  
    /*取得集合大小*/  
    public int size();  
}  
public interface Iterator {  
    //前移  
    public Object previous();  
    //后移  
    public Object next();  
    public boolean hasNext();  
    //取得第一个元素  
    public Object first();  
}  
//两个实现:
public class MyCollection implements Collection {  
    public String string[] = {"A","B","C","D","E"};  
    @Override  
    public Iterator iterator() {  
        return new MyIterator(this);  
    }  
    @Override  
    public Object get(int i) {  
        return string[i];  
    }  
    @Override  
    public int size() {  
        return string.length;  
    }  
}  
public class MyIterator implements Iterator {  
    private Collection collection;  
    private int pos = -1;  
    public MyIterator(Collection collection){  
        this.collection = collection;  
    }  
    @Override  
    public Object previous() {  
        if(pos > 0){  
            pos--;  
        }  
        return collection.get(pos);  
    }  
    @Override  
    public Object next() {  
        if(pos<collection.size()-1){  
            pos++;  
        }  
        return collection.get(pos);  
    }  
    @Override  
    public boolean hasNext() {  
        if(pos<collection.size()-1){  
            return true;  
        }else{  
            return false;  
        }  
    }  
    @Override  
    public Object first() {  
        pos = 0;  
        return collection.get(pos);  
    }  
  
}  

//测试类:
public class Test {  
    public static void main(String[] args) {  
        Collection collection = new MyCollection();  
        Iterator it = collection.iterator();  
          
        while(it.hasNext()){  
            System.out.println(it.next());  
        }  
    }  
}  
输出:A B C D E

此处我们貌似模拟了一个集合类的过程,感觉是不是很爽?其实JDK中各个类也都是这些基本的东西,加一些设计模式,再加一些优化放到一起的,只要我们把这些东西学会了,掌握好了,我们也可以写出自己的集合类,甚至框架!

外传

😜 原创不易,如若本文能够帮助到您的同学
🎉 支持我:关注我+点赞👍+收藏⭐️
📝 留言:探讨问题,看到立马回复
💬 格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!🔥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/528861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7. 深入理解MVCC与BufferPool缓存机制

MySQL性能调优 1. MVCC多版本并发控制机制1.1 undo日志版本链与read view机制详解 2. Innodb引擎SQL执行的BufferPool缓存机制 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确的地方&#xff0c;还望大佬多多指点纠正&#xff0c;勿喷。 本节课内容&#xff1a; 1、…

PowerShell install 一键部署VMware_Workstation

VMware Workstation 前言 VMware Workstation Pro 是业界标准的桌面 Hypervisor&#xff0c;用于在 Linux 或 Windows PC 上运行虚拟机 download VMware_Workstation VMware_Workstation WindowsVMware_Workstation linux文档downloaddownload参考 前提条件 开启wmi,配置…

2023接口自动化测试框架9项必备功能(建议收藏)

当你准备使用一个接口测试框架或者自造轮子的时候&#xff0c;或许你需要先了解下一个接口自动化测试框架必须具备什么功能。 一、校验 这个很好了解&#xff0c;如果没有校验&#xff0c;单纯的执行接口的话&#xff0c;那就谈不上测试了。所以支持对返回值校验是一个必须的…

【集合详解】——python基础——如桃花来

目录索引 集合的特点&#xff1a;创建集合&#xff1a;集合常见操作&#xff1a;增加数据&#xff1a;*add():**update():* 删除数据&#xff1a;*remove():**discard():**pop():* 查找数据&#xff1a;*in:**not in:* 集合的特点&#xff1a; 没有重复元素,即使重复&#xff0…

【ONE·C++ || set和map(三):基于红黑树的封装框架】

总言 主要介绍map、set的封装框架。 文章目录 总言1、基本框架说明2、map、set封装Ⅰ&#xff1a;用于比较的仿函数3、map、set封装Ⅱ&#xff1a;迭代器实现3.1、基本说明3.2、begin()、end()、operator*、operator&、operator、operator!3.2.1、begin()、end()3.2.2、op…

( 位运算 ) 693. 交替位二进制数 / 476. 数字的补数 ——【Leetcode每日一题】

❓ 题目一 693. 交替位二进制数 难度&#xff1a;简单 给定一个正整数&#xff0c;检查它的二进制表示是否总是 0、1 交替出现&#xff1a;换句话说&#xff0c;就是二进制表示中相邻两位的数字永不相同。 示例 1&#xff1a; 输入&#xff1a;n 5 输出&#xff1a;true 解…

使用inbuilder完成UBML低代码设计

文章目录 一、活动介绍二、我所认识的低代码平台三、使用inbuilder开发工具拖拉跩实现 低代码产品开发四、环境搭建五、5分钟完成低代码实验六、财务报销报表实验活动成果截图七、总结 一、活动介绍 开放原子训练营开启inBuilder低代码实验室活动。无论您是计算机行业相关从业…

(css)el-select多选以tag展示时,超过显示长度以...省略号显示

(css)el-select多选以tag展示时&#xff0c;超过显示长度以…省略号显示 效果 代码&#xff1a; <span>系统词典维度&#xff1a;</span><el-selectv-model"dNum"placeholder"请选择"multiplecollapse-tags //设置collapse-tags属性将它…

Windows批处理指令

前言 批处理文件&#xff08;batch file&#xff09;包含一系列 DOS 命令&#xff0c;通常用于自动执行重复性任务。用户只需双击批处理文件便可执行任务&#xff0c;而无需重复输入相同指令。编写批处理文件非常简单&#xff0c;但难点在于确保一切按顺序执行。编写严谨的批处…

Java进阶-面向对象入门

1. 面向过程与面向对象 1.1 何谓“面向对象”的编程思想&#xff1f; 首先解释一下“思想”。 先问你个问题&#xff1a;你想做个怎样的人&#xff1f; 可能你会回答&#xff1a;我想做个好人&#xff0c;孝敬父母&#xff0c;尊重长辈&#xff0c;关爱亲朋…… 你看&#…

2023年Android开发者路线-第2部分

2023年Android开发者路线-第1部分 2023年Android开发者路线-第2部分 2023年Android开发者路线-第3部分 2023年Android开发者路线-第4部分 2023Android开发者路线-第2部分 在上一篇文章中&#xff0c;我们讨论了 Android 架构的重要元素&#xff0c;包括主要的 Android 语言…

探索iOS之AVFoundation框架

AVFoundation框架的业务层主要是AVKit和UIKit&#xff0c;内核层包括CoreVideo、CoreAudio、CoreMedia、VideoToolBox等。AVFoundation作为iOS的音视频框架&#xff0c;提供音视频播放、录制、编辑、编解码、音效设置等。接下来&#xff0c;让我们看一下整体的框架图。 一、AVK…

ANR基础篇 - Trace.txt文件分析

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、trace.txt文件示例二、日志分析2.1 CPU 负载2.2 内存信息2.3 堆栈信息schedst…

Mybatis 案例

文章目录 Mybatis 案例一、 准备工作1.1 数据库表1.2 Restfull规范1.3 封装结果类1.4 实体类 二、部门管理2.1 查询全部部门信息2.2 删除部门2.3 新增部门 三、员工管理3.1 分页查询3.2 分页查询 - PageHelper插件3.3 分页查询 - 条件查询3.4 批量删除员工3.5 新增员工3.6 修改…

蓝桥杯模块学习3——蜂鸣器与继电器

第一章 硬件部分 1.1 电路的组成部分 1.1.1 译码器和锁存器 具体可回顾之前LED灯的文章&#xff1a; https://blog.csdn.net/weixin_63568691/article/details/130660096 1.1.2 ULN2003达林顿管 原理图&#xff1a; 功能&#xff1a; &#xff08;1&#xff09;改变电路特性…

使用Spring初始化器创建Spring Boot项目

注&#xff1a;初始化向导需要联网创建Spring Boot项目 new project 项目创建完成 resources 文件夹中目录结构&#xff1a; static &#xff1a;保存所有的静态资文件&#xff0c; js css images templates &#xff1a;保存所有的模板页面&#xff08;Spring Boot默认j…

python3 爬虫相关学习1:安装requests模块

目录 1 安装前&#xff1a;避免python2 python3 引起的问题 2 如何安装python3 2.1 直接上python3 官网下载 2.2 或者windows的话&#xff0c;microsoft store 里也可以下载 2.3 查看python版本 3 安装requests模块 3.1 很可能安装requests模块之前会遇到报错&#xff…

linux0.12-8-11-vsprintf.c

[383页] 1、 这一小节可以不看代码如何实现&#xff0c;因为标准的C库函数&#xff1b; 2、 等自己看完的这本书&#xff0c;有兴趣过来研究研究也是可以的。 8-11 vsprintf.c程序 8-11-1 功能描述 该程序主要包括vsprintf(),用于对参数产生格式化的输出。由于该函数是C函数…

SOME/IP 草稿

SOME/IP 名词解释 SOME/IP 全称是 Scalable service-Oriented MiddlewarE over IP。也就是基于 IP 协议的面向服务的可扩展性通信中间件协议。 面向服务 SOA基于 IP 协议之上的通信协议中间件 SOME/IP 功能 服务发现 (Service Discovery)远程服务调用 &#xff08;RPC,rem…

React面试题汇总 --2

1. 何为 redux &#xff0c;解决什么问题 操作流程 使用场景 优缺点 &#xff1f; Redux使用详解(一) Redux的核心思想与基本使用__聪明勇敢有力气的博客-CSDN博客Redux使用详解(一) Redux的核心思想与基本使用https://blog.csdn.net/weixin_65402230/article/details/128193…