美文网首页
Android面试系列之【设计模式】

Android面试系列之【设计模式】

作者: 西瓜家族 | 来源:发表于2020-02-20 02:05 被阅读0次

简介

设计模式(Design Pattern)
设计模式是什么?它是一套理论,由前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。“道可道,非常道”非常适合描述设计模式。

不得不说的六大设计原则

  • 单一职责原则:要求我们实现类要职责单一
  • 里氏替换原则:要求我们不要破坏继承关系体系
  • 依赖倒置原则:要求我们要面向接口编程
  • 接口隔离原则:要求我们在设计接口的时候要精简单一
  • 迪米特法则:要求我们要降低耦合
  • 开闭原则:要求我们对扩展开放,对修改关闭

开始学设计模式

设计模式

  1. 创建型
    • 单例模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
    • 建造者模式
    • 原型模式
  2. 结构型
    • 适配器模式
    • 组合模式
    • 装饰模式
    • 代理模式
    • 享元模式
    • 外观模式
    • 桥接模式
  3. 行为型
    • 观察者模式
    • 策略模式
    • 状态模式
    • 模板方法模式
    • 命令模式
    • 解释器模式
    • 迭代模式
    • 责任链模式
    • 访问者模式
    • 中介者模式
    • 备忘录模式

【单例模式】

单例模式可以说是最容易理解的模式了,也是用的最多的模式之一。
什么是单例模式?确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。

什么时候需要使用单例模式呢?如果某个类,创建时需要消耗很多资源,即new出这个类的代价很大;或者是这个类占用很多内存,如果创建太多这个类实例会导致内存占用太多。

懒汉式

public class Singleton{
    // 重点 volatitle 关键字的使用
    private volatile static Singleton instance;

    private Singleton(){};
    
    public static Singleton getInstance(){
        if (instance == null){
            sychronized(Singleton.class){
                if (instance == null)
                    instance=new Singleton();
            }
        }
        return instatnce;
    }
}

基于懒汉式+synchronized的通用单例

public class Singleton<T> {
    private static final ConcurrentMap<Class, Object> INSTANCE_MAP = new ConcurrentHashMap<Class, Object>();

    private Singleton(){}

    public static <T> T getInstance(Class<T> type){
        Object o = INSTANCE_MAP.get(type);
        if (o == null){
            synchronized (INSTANCE_MAP){
                try {
                    o = type.newInstance();
                    INSTANCE_MAP.put(type, o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return (T) o;
    }
}

在Android中的应用

//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);

【建造者模式】

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

什么情况下使用该模式呢?
主要是在创建某个对象时,需要设定很多的参数(通过setter方法),但是这些参数必须按照某个顺序设定,或者是设置步骤不同会得到不同结果。

public class Student {
    private final long id;  // 必须参数
    private final String name;  //  非必须
    private final int age;

    private Student(Builder builder) {
        this.id = builder.id;
        this.name = builder.name;
        this.age = builder.age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getId() {
        return id;
    }

    public static class Builder{
        private final long id;  // 必须参数
        private String name;  //  非必须
        private int age;
        // 返回自身的引用this,这主要是用于链式调用
        public Builder(long id) {
            this.id = id;
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAge(int age) {
            this.age = age;
            return this;
        }

        public Student build(){
            Student student = new Student(this);
            // Builder另一个特性可以对参数进行合法性验证
            if (student.getAge() > 120){
                // Builder模式是非线程安全的,如果要在Builder内部类中检查一个参数的合法性,必需要在对象创建完成之后再检查
                throw  new IllegalStateException("年龄超出限制");
            }
            return student;
        }
    }
}

注意:

  1. Student的构造方法是私有的,也就是说我们不能直接new出来
  2. Student的属性用final修饰,并且我们在构造方法中都为他们进行了初始化操作,只提供了getter方法
  3. 使用builder模式构造出来的对象有更好的可读性
  4. Builder的属性中只给我们必须的属性添加的final修饰,所以必须在构造方法中为他们初始化
    // 优美的链式调用
  Student student = new Student.Builder(1)
                .setName("张三")
                .setAge(18)
                .build();

在Android中的应用

  • Android中的AlertDialog.Builder
private void showDialog(){
        AlertDialog.Builder builder=new AlertDialog.Builder(context);
        builder.setIcon(R.drawable.icon);
        builder.setTitle("Title");
        builder.setMessage("Message");
        builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //TODO
            }
        });
        builder.setNegativeButton("Button2", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //TODO
            }
        });
        
        builder.create().show();
}

  • OkHttp中OkHttpClient的创建
OkHttpClient  okHttpClient = new OkHttpClient.Builder()
                 .cache(getCache()) 
                 .addInterceptor(new HttpCacheInterceptor())
                 .addInterceptor(new LogInterceptor())
                 .addNetworkInterceptor(new HttpRequestInterceptor()) 
                 .build();

【工厂模式】

定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方式模式使一个类的实例化延迟到其子类。

public abstract class Product{
    // 产品类的公共方法
    public void method1(){
        // 业务逻辑
    }
    public abstract void method2();
}

public class ConcreteProductA extends Product {
    @Override
    public void method2() {
        // 产品A的业务逻辑
    }
}
public class ConcreteProductB extends Product {
    @Override
    public void method2() {
        // 产品B的业务逻辑
    }
}
public abstract class Creator {
    // 创建一个产品对象
    public abstract <T extends Product > T createProduct(Class<T> clazz);
}
public class ConcreteCreator extends Creator {
    @Override
    public <T extends Product> T createProduct(Class<T> clazz) {
        Product product = null;
        try {
            product = (Product) Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

在Android中的应用

    //抽象产品:Runnable
    public interface Runnable {
        public abstract void run();
    }
    
    //具体产品:Thread
    public class Thread implements Runnable {
        //构造方法
        public Thread(Runnable target, String name) {
            init(null, target, name, 0);
        }
        
        @Override
        //实现抽象产品的抽象方法
        public void run() {
            if (target != null) {
                target.run();
            }
        }
        
        //其他代码略
    }
    
    
    //抽象工厂:ThreadFactory
    public interface ThreadFactory {
        Thread newThread(Runnable r);
    }
    
    //具体工厂:AsyncTask中的实现
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);
        
        //实现抽象工厂的抽象方法
        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());//返回Thread这个产品
        }
    };

【抽象工厂模式】

为创建一组相关或者是相互依赖的对象提供一个接口,而不需要制定他们的具体类。

//抽象产品类-- CPU
public abstract class CPU {
    public abstract void showCPU();
}
//抽象产品类-- 内存
public abstract class Memory {
    public abstract void showMemory();
}
//抽象产品类-- 硬盘
public abstract class HD {
    public abstract void showHD();
}

创建具体产品类

//具体产品类-- Intet CPU
public class IntelCPU extends CPU {

    @Override
    public void showCPU() {
        System.out.println("Intet CPU");
    }
}

//具体产品类-- AMD CPU
public class AmdCPU extends CPU {

    @Override
    public void showCPU() {
        System.out.println("AMD CPU");
    }
}

//具体产品类-- 三星 内存
public class SamsungMemory extends Memory {

    @Override
    public void showMemory() {
        System.out.println("三星 内存");
    }
}

//具体产品类-- 金士顿 内存
public class KingstonMemory extends Memory {

    @Override
    public void showMemory() {
        System.out.println("金士顿 内存");
    }
}

//具体产品类-- 希捷 硬盘
public class SeagateHD extends HD {

    @Override
    public void showHD() {
        System.out.println("希捷 硬盘");
    }
}

//具体产品类-- 西部数据 硬盘
public class WdHD extends HD {

    @Override
    public void showHD() {
        System.out.println("西部数据 硬盘");
    }
}

创建抽象工厂类

//抽象工厂类,电脑工厂类
public abstract class ComputerFactory {
    public abstract CPU createCPU();

    public abstract Memory createMemory();

    public abstract HD createHD();
}

创建具体工厂类

//具体工厂类--联想电脑
public class LenovoComputerFactory extends ComputerFactory {

    @Override
    public CPU createCPU() {
        return new IntelCPU();
    }

    @Override
    public Memory createMemory() {
        return new SamsungMemory();
    }

    @Override
    public HD createHD() {
        return new SeagateHD();
    }
}

//具体工厂类--华硕电脑
public class AsusComputerFactory extends ComputerFactory {

    @Override
    public CPU createCPU() {
        return new AmdCPU();
    }

    @Override
    public Memory createMemory() {
        return new KingstonMemory();
    }

    @Override
    public HD createHD() {
        return new WdHD();
    }
}

//具体工厂类--惠普电脑
public class HpComputerFactory extends ComputerFactory {

    @Override
    public CPU createCPU() {
        return new IntelCPU();
    }

    @Override
    public Memory createMemory() {
        return new KingstonMemory();
    }

    @Override
    public HD createHD() {
        return new WdHD();
    }
}

优点:

  1. 封装性,每个产品的实现类不是高层模块要关心的,它要关心的是接口是抽象。
  2. 产品族内的约束为非公开状态。例如联想电脑使用的是IntelCpu+三星内存+希捷的盘,具体的产品族内的约束是在工厂内实现的。

缺点:
抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?比如我们增加一个主板,抽象类需要增加createBoard(),然后实现类都需要去修改,这就严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约,改变契约有与契约有关系的代码都要修改,这就是有毒代码。上面说的是产品族内扩展困难,但是品牌类型扩建容易,只要增加一个工厂类复制新增加出来的产品生产任务即可。

工厂方法模式与抽象工厂模式比较

  • 在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法具有唯一性。
  • 抽象工厂模式则可以提供多个产品对象,而不是单一的产品对象

【观察者模式】

待续。。。

【代理模式】

待续。。。

【策略模式】

待续。。。

【原型模式】

待续。。。

【状态模式】

待续。。。

【命令模式】

待续。。。

【装饰模式】

待续。。。

【适配器模式】

待续。。。

相关文章

  • Android 设计模式之简单工厂模式

    设计模式系列文章 Android 设计模式之单例模式 Android 设计模式之Builder模式 Android...

  • Android 代理模式

    Android 设计模式系列文章 Android 23种设计模式 前言 代理模式可能是我们平时开发中最常见的模式之...

  • Android面试系列之【设计模式】

    简介 设计模式(Design Pattern) 设计模式是什么?它是一套理论,由前辈们对代码开发经验的总结,是解...

  • Android 外观模式

    Android 设计模式系列文章 Android 23种设计模式 一、前言 Android 外观模式(Facade...

  • Android 组合模式(View与ViewGroup)

    Android 设计模式系列文章 Android 23种设计模式 前言 组合设计模式,又被称为部分整体模式。组合模...

  • Android 享元模式

    Android 设计模式系列文章 Android 23种设计模式 一、前言 享元模式即:Flyweight,它是对...

  • 详解 - Builder模式

    “Android设计模式”这个系列主要是对Android项目中的设计模式进行分析总结,学习自《Android 源码...

  • 详解 - 单例模式

    “Android设计模式”这个系列主要是对Android项目中的设计模式进行分析总结,学习自《Android 源码...

  • Android 迭代器模式

    Android 设计模式系列文章 Android 23种设计模式 前言 迭代器模式又称为游标模式,源于对容器的访问...

  • Android 命令模式

    Android 设计模式系列文章 Android 23种设计模式 前言 命令模式,多被用于程序菜单命令。比如遥控器...

网友评论

      本文标题:Android面试系列之【设计模式】

      本文链接:https://www.haomeiwen.com/subject/trgzfhtx.html