Android面试之Java设计模式

3,218 阅读5分钟

本文是Android面试题整理中的一篇,结合右下角目录食用更佳

1. 单例模式

一个类仅有一个实例,供全局访问,以下是几种实现方式

//饿汉模式
public class Singleton{
  private static Singleton instance = new Singleton();
  
  private Singleton(){};
  
  public Singleton getInstance(){
  return instance;
  }
}

// 懒汉模式
public class Singleton{
  private volatile static Singleton instance = null;
  
  private Singleton(){};
  
  public Singleton getInstance(){
   if(instance == null){
       synchronized(Singleton.class){
         if(instance == null) {
           instance = new Singleton();
      }
     }
   }
   return instance;
  }
}

//静态内部类(推荐)
public class Singleton{
  private static class SingletonHolder{
  public static Singleton instance = new Singleton();
  }
  private static Singleton instance = new Singleton();
  
  private Singleton(){};
  
  public Singleton getInstance(){
   return SingletonHolder;
  }
}

1.X 单例如何防止反射攻击

  1. 使用一个static的标记位,再次实力化时验证其值,抛出异常
  2. 或者使用枚举

2. 建造者(Builder)模式

将对象的构建与展示分离,允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。

Android中典型的用到Builder的地方是AlertDialog,以下是构建AlertDialog举例

//显示基本的AlertDialog  
    private void showDialog(Context context) {  
        AlertDialog.Builder builder = new AlertDialog.Builder(context);  
        builder.setIcon(R.drawable.icon);  
        builder.setTitle("Title");  
        builder.setMessage("Message");  
        builder.setPositiveButton("Button1",  
                new DialogInterface.OnClickListener() {  
                    public void onClick(DialogInterface dialog, int whichButton) {  
                        setTitle("点击了对话框上的Button1");  
                    }  
                });  
        builder.setNeutralButton("Button2",  
                new DialogInterface.OnClickListener() {  
                    public void onClick(DialogInterface dialog, int whichButton) {  
                        setTitle("点击了对话框上的Button2");  
                    }  
                });  
        builder.setNegativeButton("Button3",  
                new DialogInterface.OnClickListener() {  
                    public void onClick(DialogInterface dialog, int whichButton) {  
                        setTitle("点击了对话框上的Button3");  
                    }  
                });  
        builder.create().show();  // 构建AlertDialog, 并且显示
    } 

3. 观察者模式

观察者模式在对象间建立了一对多的关系,当一个对象状态发生改变时,通知和它关联的所有对象它的改变,让这些对象作出相应的调整。

在Android中,我们往ListView添加数据后,都会调用Adapter的notifyDataChanged()方法,其中使用了观察者模式:当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged函数,这个函数又会调用DataSetObservable的notifyChanged函数,这个函数会调用所有观察者(AdapterDataSetObserver)的onChanged方法,在onChanged函数中又会调用ListView重新布局的函数使得ListView刷新界面

4. 代理(Proxy)模式

适用场景:被代理的对象A不能直接访问或者出于对A的保护,不想让它被直接访问
给某一个对象A创建一个代理对象B,通过控制B来间接控制A,B与A实现了同一个接口。

  1. 代理可以分为静态代理和动态代理。使用动态代理时我们需要实现中介类(实现InvocationHandler接口),并调用Proxy.newProxyInstance方法帮助我们动态生成一个代理。
  2. Android 的 Binder 中就运用了代理模式

5. 装饰者模式

装饰模式动态的将责任附加到对象上,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案

6. 代理和装饰的区别

代理强调限制,装饰强调增强原有功能

7. 适配器模式

将一个类的接口A转换成客户希望的另一个接口B。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

8. 工厂和抽象工厂

  1. 简单工厂将对象生成的过程进行了封装9
  2. 工厂方法根据依赖倒置原则,将对象创建的过程交给子类
  3. 抽象工厂是为了生成一族对象,例如有一个生成一套服装的工厂(生产上衣和裤子),它的实现有休闲工厂/正装工厂;这个时候如果我们生成一个休闲工厂实例,并需要红上衣绿裤子,那么产出的是休闲红上衣+休闲绿裤子

9. 命令模式

命令中包含接受者和一些信息,Client创建命令,并将其交给执行者,执行者不必知道命令的细节,只需调用excute执行,命令会调用接受者执行。

Handler模式是典型的命令模式:Looper不知道Message的实现细节,只管调用它执行

10. 外观模式

外观模式提供了一个统一的接口,来访问子系统的一群接口:实现了客户和子系统的解偶

11. 原型模式

当创建对象的成本较大时,我们可以选择原型模式,通过clone已经存在的对象生成一个新的对象

12. 责任链模式

对一个请求,用一条链表来处理,链表上每一个节点都有可能消耗掉这个请求或者继续传递给后边的节点

Android 中的有序广播和View的事件分发是典型的责任链模式

13. 模版方法

在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。

14. 策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化

如安卓动画中的插值器

15. 组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构,单个对象和对象的组合实现了同一个接口,组合模式使得用户对单个对象和组合对象的使用具有一致性。

Android中典型的例子View,具体的View和ViewGroup都实现了View接口,同时可以将多个View添加到一个ViewGroup作为一个整体View。

16. 享元模式

享元模式是为数不多的、只为提升系统性能而生的设计模式。它的主要作用就是复用大对象(重量级对象),以节省内存空间和对象创建时间。

如Andrid 中 Message m = Message.obtain(); 用的就是享元模式

17. Activity中的设计模式

  1. 模版方法:生命周期
  2. 装饰者:ContextWrapper内部有个Context引用mContext
  3. 解释器:Manifest中定义Activity
  4. 备忘录:Activity的onSaveInstanceState和onRestoreInstanceState