Android面试指南(六)————模式篇

179 阅读2分钟

单例

饿汉:线程安全,类初始化的时候就会触发类的实例化,所以保证只有一个,

缺点:但是会浪费内存,如果不使用单例,就会一直存在

public class Singleton {
    //在静态初始化器中创建单例实例,这段代码保证了线程安全
    private static final Singleton instance = new Singleton();
    //Singleton类只有一个构造方法并且是被private修饰的,所以用户无法通过new方法创建该对象实例
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}

懒汉:synchronized加锁线程安全

public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    //没有加入synchronized关键字的版本是线程不安全的
    public static synchronized  Singleton getInstance() {
        //判断当前单例是否已经存在,若存在则返回,不存在则再建立单例
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

双重校验锁:双重加锁(线程安全)

public class Singleton {
    private static volatile Singleton instance;
    private Singleton() { }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  1. 双重判断的原因?
    • 第一个判断减少锁的使用,提升性能
    • 多个线程同时等待锁,当第一个创建后,就不需要其他线程重复重建
  2. volatile的理解
    • 禁止重排序导致instance获取失败(3)。
  3. new Singleton()方法执行时可能导致分配了空间,并指向了内存空间,但是没有赋值,这样另一个线程拿到后会导致出错

静态内部类:(线程安全)

public class Singleton {
    //私有构造方法
    private Singleton (){

    }
    
    private static class SingletonHelper{
        //声明成员变量
        private static final Singleton instance = new Singleton();
    }
    //对外提供接口获取该实例
    public static Singleton getSingleton(){
        return SingletonHelper.instance;
    }
}

枚举单例:(线程安全)

public enum Singleton {

    INSTANCE;

    public void doSomething() {
        System.out.println("doSomething");
    }

}
调用方法:

public class Main {

    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}

直接通过Singleton.INSTANCE.doSomething()的方式调用即可。方便、简洁又安全。

生产者消费者

生产者添加数据,消费者自己从中间件中获取信息,通过中间件管理数据

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author kangsx
 * @description
 * @date 2020/5/13
 */
public class Mode1 {

    static class Box{
        private Queue<Integer> list = new LinkedList<>();
        int maxSize = 50;

        private void put(int i){
            synchronized (this){
                while(list.size()>=maxSize){
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add(i);
                notifyAll();
            }
        }

        private int get(){
            int i = 0;
            synchronized (this){
                while (list.size()<=0){
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                i = list.remove();
                notifyAll();
            }
            return i;
        }
    }


    static class Producer extends Thread{
        private Box box;

        public Producer(Box box) {
            this.box = box;
        }

        @Override
        public void run() {
            super.run();
            box.put(5);
        }
    }

    static class Consumer extends Thread{
        private Box box;

        public Consumer(Box box) {
            this.box = box;
        }

        @Override
        public void run() {
            super.run();
            int i = box.get();
            System.out.println("i = " + i);
        }
    }

    public static void main(String args[]){
        Box box = new Box();
        //5个生产者
        for(int i = 0;i<5;i++) {
            new Producer(box).start();
        }
        //5个消费者
        for(int i = 0;i<5;i++){
            new Consumer(box).start();
        }
    }
}

观察者

发布者发送数据到订阅者

import java.util.ArrayList;

/**
 * @author kangsx
 * @description
 * @date 2020/5/13
 */
public class Mode2 {
    static public interface IObserver {
        void update(int temp);
    }

    static public interface IObservable {
        void register(IObserver iObserver);

        void unregister(IObserver iObserver);

        void notifyObserver();
    }

    //被观察者(发布者)
    static class Observable implements IObservable {
        private ArrayList<IObserver> list = new ArrayList<>();
        private int temp;

        @Override
        public void register(IObserver iObserver) {
            list.add(iObserver);
        }

        @Override
        public void unregister(IObserver iObserver) {
            list.remove(iObserver);
        }

        @Override
        public void notifyObserver() {
            for (int i = 0; i < list.size(); i++) {
                list.get(i).update(temp);
            }
        }

        public void setTemp(int temp) {
            this.temp = temp;
        }
    }

    //观察者1(订阅者)
    static class Observer1 implements IObserver {

        @Override
        public void update(int temp) {
            System.out.println("Observable1更新为 = " + temp);
        }
    }

    //观察者2(订阅者)
    static class Observer2 implements IObserver {
        @Override
        public void update(int temp) {
            System.out.println("Observable2更新为 = " + temp);
        }
    }

    public static void main(String args[]){
        Observable observable = new Observable();
        Observer1 observer1 = new Observer1();
        Observer2 observer2 = new Observer2();
        observable.register(observer1);
        observable.register(observer2);
        observable.setTemp(32131232);
        observable.notifyObserver();
    }
}

建造者模式

提供复杂参数的对象构造,完全由调用方选择参数配置,反之使用默认。

public class Computer {
    //显示器
    String display;
    //cpu型号
    String cpu;
    //主板型号
    String mainBoard;
    //显卡型号
    String gpu;

    public Computer(Builder builder) {
        this.display = builder.display;
        this.cpu = builder.cpu;
        this.mainBoard = builder.mainBoard;
        this.gpu = builder.gpu;
    }

    @Override
    public String toString() {
        return "显示器是" + display + "\ncpu是" + cpu + "\n主板是" + mainBoard + "\n显卡是" + gpu;
    }

    static class Builder{
        //显示器
        String display;
        //cpu型号
        String cpu;
        //主板型号
        String mainBoard;
        //显卡型号
        String gpu;

        public Builder(){
            this.display = "三星曲屏";
            this.cpu = "i5 8400";
            this.mainBoard = "华硕Z360-B";
            this.gpu = "GTX 1050Ti";
        }

        public Builder setDisplay(String display) {
            this.display = display;
            return this;
        }

        public Builder setcpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public Builder setMainBoard(String mainBoard) {
            this.mainBoard = mainBoard;
            return this;
        }

        public Builder setGpu(String gpu) {
            this.gpu = gpu;
            return this;
        }

        public Computer build(){
            return new Computer(this);
        }
    }

    public static void main(String args[]){
        Computer computer = new Computer.Builder()
                .setcpu("i9 4700u")
                .setGpu("GTX 2060Ti")
                .setMainBoard("华硕Z480")
                .build();
        System.out.println(computer.toString());
    }
}

工厂模式

代理模式

对原有功能进行封装,访问对象不能直接访问原有功能,只能访问我们的功能传达,我们就是代理,作为原有功能和访问对象之间的中介

静态代理:

package proxy;

public class ProxyTest {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.Request();
    }
}

//抽象主题
interface Subject {
    void Request();
}

//真实主题
class RealSubject implements Subject {
    public void Request() {
        System.out.println("访问真实主题方法...");
    }
}

//代理
class Proxy implements Subject {
    private RealSubject realSubject;

    public void Request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }

    public void preRequest() {
        System.out.println("访问真实主题之前的预处理。");
    }

    public void postRequest() {
        System.out.println("访问真实主题之后的后续处理。");
    }
}

动态代理:

IRetrofit iRetrofit = (IRetrofit) Proxy.newProxyInstance(IRetrofit.class.getClassLoader(), new Class<?>[]{IRetrofit.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("-----调用前执行");
                if(method.getDeclaringClass() == Object.class) {
                    System.out.println("-----调用前执行Object");
                    return method.invoke(IRetrofit.class, args);
                }
                IRetrofit iRetrofit1 = new IRetrofit() {
                    @Override
                    public void test() {
                        System.out.println("------test1");
                    }

                    @Override
                    public void kang() {
                        System.out.println("------kang1");
                    }
                };
                Object object = method.invoke(iRetrofit1,args);
                System.out.println("-------调用后执行");
                return null;
            }
        });
        iRetrofit.kang();

打印如下:

-----调用前执行
------kang1
-------调用后执行

即想调用那个方法都可以,在invoke中做了代理,利用反射执行该类