首页 > 其他分享 >4月29日邓老师设计模式面试资料 一般有用 看1

4月29日邓老师设计模式面试资料 一般有用 看1

时间:2023-06-09 15:24:00浏览次数:48  
标签:对象 doSome 29 接口 代理 面试 模式 设计模式 public

【金三银四】设计模式篇

1.谈谈你对设计模式的理解

1.首先谈设计模式的作用:经验的传承,提高了软件复用的水平,最终达到提高软件开发效率

设计原则简单说明
单一职责 一个类只负责一项职责
里氏替换原则 子类可以扩展父类的功能,但不能改变父类原有的功能
依赖倒置原则 要依赖于抽象,不要依赖于具体,核心思想是==面向接口编程==
接口隔离原则 建立单一接口,不要建立庞大臃肿的接口,<br>尽量细化接口,接口中的方法尽量少
迪米特法则 (最少知道原则) 一个对象应该对其他对象保持最少的了解
开闭原则 对扩展开放,对修改关闭

2.设计模式的分类

image.png

3.创建型模式:都是用来帮助我们创建对象的!

image.png

4.结构性模式:关注对象和类的组织

image.png

5.行为型模式:关注系统中对象之间的相互交换,研究系统在运行时对象之间的相互通信和协作,进一步明确对象的职责,共有11中模式

image.png

2.谈谈你对创建型模式的理解

  Java的23种设计模式分为3类,分别是

image.png

而创建型模式中有包含的如下的相关模式:

image.png

而每个设计模式的作用如下:

image.png

3.谈谈你对代理模式的理解

3.1 代理模式的作用

  代理模式的作用是通过代理对象来增强目标对象的功能。利用的是AOP横切的思想。

3.2 代理模式的实现方式

  代理模式的实现方式有三种:静态代理,动态代理(JDK动态代理和CGLIB动态代理)

image.png

3.2.1 静态代理

我们先声明接口和目标实现类

/**
* 定义公共接口
*/
public interface SomeService {
   String doSome();
}

目标类

/**
* 目标对象 target
*/
public class SomeServiceImpl implements SomeService {
   @Override
   public String doSome() {
       System.out.println("目标对象:doSome()" );
       return "hello ...";
  }
}

然后创建对应的代理类

/**
* 代理类
*     增强实现类
*     和实现类实现同一个接口
*/
public class SomeProxy implements SomeService{

  private SomeService target;

  public SomeProxy(SomeService target){
      this.target = target;
  }

  /**
    * 增强的方法
    * @return
    */
  @Override
  public String doSome() {
      System.out.println("目标方法执行之前...");
      String s = target.doSome();
      System.out.println("目标方法执行之后...");
      return s.toUpperCase();
  }
}

然后测试实现

public class MainTest {
   public static void main(String[] args) {
       SomeService some = new SomeServiceImpl();
       SomeProxy proxy = new SomeProxy(some);
       System.out.println(proxy.doSome());
  }
}

对应的输出结果

目标方法执行之前...
目标对象:doSome()
目标方法执行之后...
HELLO ...

可以看到代理对象实现了目标对象的调用,同时增强了目标对象的功能。

3.2.2 JDK动态代理

  上面的静态代理我们需要手动的创建一个对应的代理来实现,不是太灵活,针对目标对象有实现相关接口的情况,我们可以使用JDK动态代理。

public class JdkDynamicProxy {

   /**
    * JDK动态代理:目标对象必须实现相关的接口
    * @param args
    */
   public static void main(String[] args) {
       SomeService target = new SomeServiceImpl();
       SomeService proxy = (SomeService) Proxy.newProxyInstance(JdkDynamicProxy.class.getClassLoader(), // 类加载器
               target.getClass().getInterfaces() // 目标对象实现的相关接口
              , new InvocationHandler() { // 代理对象的回调方法
                   @Override
                   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                       System.out.println("before...");
                       Object invoke = method.invoke(target, args);
                       System.out.println("end...");
                       if (invoke != null) {
                           return invoke.toString().toUpperCase();
                      }
                       return null;
                  }
              });
       // 通过代理对象来执行
       System.out.println("proxy.doSome() = " + proxy.doSome());

  }
}

输出结构

before...
目标对象:doSome()
end...
proxy.doSome() = HELLO ...

3.2.3 CGLIB动态代理

  如果目标对象实现了对应的接口我们可以通过JDK动态代理的方式来实现,但如果目标对象没有实现任何的接口,这时我们只能通过CGLIB动态代理来实现了,这时我们需要单独引入cglib的依赖

public class CGLIBDynamicProxy {

   /**
    * CGLIB动态代理
    * @param args
    */
   public static void main(String[] args) {
       SomeService target = new SomeServiceImpl();
       SomeServiceImpl proxy = new MethodInterceptor() {

           /**
            * 创建 CGLIB 代理对象的方法
            * @return
            */
           public SomeServiceImpl createProxy() {
               // 创建增强器
               Enhancer e = new Enhancer();
               // 指定父类
               e.setSuperclass(target.getClass());
               // 指定回调接口对象
               e.setCallback(this);
               // 创建CGLIB代理对象
               return (SomeServiceImpl) e.create();
          }

           /**
            * 拦截回调的方法
            */
           @Override
           public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
               System.out.println("cglib -- befor" );
               Object res = method.invoke(target, args);
               System.out.println("cglib -- end");
               return res.toString().toUpperCase();
          }
      }.createProxy();
       System.out.println("proxy.doSome() = " + proxy.doSome());
  }
}

输出的结果

cglib -- befor
目标对象:doSome()
cglib -- end
proxy.doSome() = HELLO ...

4.谈谈你对适配器模式的理解

4.1 适配器的作用

  适配器模式的作用是把两个不兼容的对象通过适配器能够连接起来工作。

image.png

4.2 具体案例分析

  以MyBatis中的日志模块为例来介绍。常见的日志框架有log4j,log4j2,slf4j,logbak等,但是每种日志框架中的日志级别都有差异。

log4j2的接口:

image.png

slf4j的接口

image.png

也就是可以看到不同的日志框架里面所定义的日志级别和对应的方法都有区别,那么我们的框架怎么来统一使用这些日志框架呢?在MyBatis中通过定义了一个日志接口,定义了日志具有的级别和方法。

image.png

那这时候我们就发现具体的日志框架和这个接口其实是没有办法直接来使用的。

image.png

这时我们就需要通过对应的适配器来处理这种情况,以Slf4J为例。

image.png

5.谈谈你对装饰者模式的理解

5.1 装饰者模式的作用

  装饰者模式又称为包装模式(Wrapper),作用是用来动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术, 无须通过继承增加子类就能扩展对象的新功能 。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

image.png

5.2 装饰者模式的应用

  装饰者模式的应用场景还是非常多的,比如

  • IO流中的FileInputStream,FileOutputStream等

  • Spring中的各种Wrapper

  • MyBatis中的缓存设计

我们以MyBatis中的缓存实例为例来看看其具体的实现。

首先是Cache接口

image.png

然后是PerpetualCache实现:仅仅实现了数据基于内存的读写操作。功能单一。

image.png

装饰类:然后在MyBatis中给我们提供了很多的装饰类。

image.png

每个装饰类都有自己的作用

  • BlockingCache:阻塞的

  • LruCache:根据Lru规则来淘汰缓存数据

  • FifoCache:根据FIFO规则来淘汰缓存数据

  • ....

源码中的装饰:

image.png

image.png

比较说明
优点 1. 扩展对象功能,比继承灵活,不会导致类个数急剧增加<br />2. 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象<br />3. 具体构建类和具体装饰类可以独立变化,<br />用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
缺点 1. 产生很多小对象。大量小对象占据内存,一定程度上影响性能。<br />2. 装饰模式易于出错,调试排查比较麻烦。

6.谈谈你对组合模式的理解

6.1 组合模式的作用

  其实解决的是对象与对象之间的包含关系。也就是 部分-整体 的层次结构。

6.2 组合模式的应用

  组合模式在配置文件的加载解析中其实会用的相对比较多。以SpringSecurity的配置文件为例

image.png

上面是具体的定义

image.png

应用

image.png

7.谈谈你对门面模式的理解

  门面模式也称为外观模式,他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。

image.png

  具体的例子比如:MyBatis中的SqlSession接口,对外提供了数据库操作的相关功能,具体的实现细节对调用者是隐藏的,这种模式在实际项目和框架中很频繁

8.谈谈你对桥接模式的理解

  桥接模式的出现是替代掉多层继承的问题。提高了系统的扩展性。

image.png

具体的应用比如JDBC中的DriverManager其实有用到桥接模式,不同的数据库厂商对应不同的驱动和连接

9.谈谈你对享元模式的理解

  这个问题相对来说比较冷门,用到的也比较少,主要是针对内存这块的节省处理,如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存.

享元模式以共享的方式高效地支持大量细粒度对象的重用。

享元对象能做到共享的关键是区分了内部状态和外部状态。 • 内部状态 :可以共享,不会随环境变化而改变 • 外部状态 :不可以共享,会随环境变化而改变

比如以围棋为例:

image.png

 

标签:对象,doSome,29,接口,代理,面试,模式,设计模式,public
From: https://www.cnblogs.com/shan13936/p/17469307.html

相关文章

  • 9.3 模版设计模式
    抽象类的设计应该是比类更高一层的设计。抽象类最大好处:1.对子类方法对统一管理;2.可以自身提供有一些普通方法,并且这些普通方法可以调用抽象方法(这些抽象方法必须在有子类提供实现的时候才会生效)abstractclassAction{ //定义公共行为类 publicstaticfinal......
  • 序) 设计模式参考资料
    https://sourcemaking.com/design_patternshttp://javapapers.com/design-patterns/  DesignPatternsInsoftwareengineering,a designpattern isageneralrepeatablesolutiontoacommonlyoccurringprobleminsoftwaredesign.Adesignpatternisn't......
  • 电弧炉用石墨电极行业市场现状调研及未来趋势报告2023-2029
    2023-2029全球电弧炉用石墨电极行业调研及趋势分析报告2022年全球电弧炉用石墨电极市场规模约409亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近667亿元,未来六年CAGR为7.0%。石墨电极在电弧炉中用作以电弧形式放电对炉料进行加热......
  • 磁饱和稳压器行业市场现状调研及未来趋势报告2023-2029
    2023-2029全球磁饱和稳压器行业调研及趋势分析报告2022年全球磁饱和稳压器市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。从核心市场看,中国磁饱和稳压器市场占据全球约%的市场份额,为全球最主......
  • 真空旋转蒸发器行业市场现状调研及未来趋势报告2023-2029
    2023-2029全球真空旋转蒸发器行业调研及趋势分析报告2022年全球真空旋转蒸发器市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。随着工业自动化和智能化的发展,真空旋转蒸发器也将朝着自动化和智......
  • 智能电动家居桌行业市场现状调研及未来趋势报告2023-2029
    2023-2029全球智能电动家居桌行业调研及趋势分析报告2022年全球智能电动家居桌市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。随着人们对舒适、健康和个性化工作环境的需求增加,智能电动家居桌......
  • 代理IP出现错误代码429如何解决
    代理IP出现错误代码429主要是因为请求过多,即客户端向服务端发送请求过于频繁,超出服务器设置的请求限制,导致连接失败。这种问题通常出现在需要频繁获取数据或者进行大量操作时。那么,如何解决代理IP出现错误代码429呢?以下是一些可能的解决方法:1.增加请求间隔时间:可以尝试......
  • JAVA面试题解惑系列(六)——字符串(String)杂谈
    关键字:java面试题字符串string作者:臧圩人(zangweiren)网址:http://zangweiren.javaeye.com上一次我们已经一起回顾了面试题中常考的到底创建了几个String对象的相关知识,这一次我们以几个常见面试题为引子,来回顾一下String对象相关的其它一些方面。String的l......
  • 4月24日吴老师大数据面试资料
    SQL试题一现在有以下一个数据表字段名称备注id唯一IDdate日期(分区字段)reg_time注册时间(时间戳)leave_time注销时间(时间戳)请用一个sql计算2022年1月-2022年2月期间每天注册用户次日留存率?举个例子:0101注册用户20人,0101注册用户在0102注销用户10人,次日留......
  • C++面试八股文:C++中指针、引用、解引用和取地址有什么不同?
    C++面试八股文:C++中指针、引用、解引用和取地址有什么不同?某日小二参加XXX科技公司的C++工程师开发岗位2面:面试官:指针、引用、解引用和取地址是C++中的重要概念,请问它们在语法和语义上有所不同?小二:指针是一个变量,它存储了一个内存地址。小二:引用是一个别名,它允许使用一个......