浅谈Android设计模式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/xiaoming100001/article/details/80302143

       如果作为低年级入门的同学学习设计模式是比较困难的,建议先补充基础,积累经验再回过头进行学习设计模式,因为其中的重要性关乎到我们是否能够进阶成为相对优秀的Android工程师,高年级大佬麻烦多多指导。在阅读或者分析源码的时候,或多或少离不开设计模式,下面我只是挑了几个来谈谈我学习的理解。
       在分享设计模式之前,我们先了解下设计模式的六大原则:

1.单一职责原则:对于一个类而言,应该仅有一个引起它变化的原因。通俗地理解是不要在Activity中写Bean文件、网络请求处理和Adapter等。
2.开放封闭原则:类、模块、函数等应该是可以拓展,但是不可以修改。在开发中,需求是变化的,如果有新的需求,我们就要重新把类改一遍显然是很爆炸的,所有进来通过扩展的方式实现
3.迪米特原则:一个软件应当尽可能少地和其他实体发生相互作用。
4.接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上,接口的负责化要适度
5.依赖倒置原则:高层模块不应该依赖底层模块,两者都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖与抽象。读起来很拗口,在Java中,抽象是指接口和抽象类;细节是实现类;高层模块就是调用者,底层模块就是具体的实现类,我的理解是类跟类之间的依赖通过抽象产生的。
6.里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。

下面进入设计模式的话题,包括了:

创造型设计模式:单例模式、建造者模式(ps:简单工厂模式和抽象工厂模式理解的还不是很好,所以先不做分享)、结构型模式中的享元模式和行为型设计模式中的策略模式、观察者模式

一、单例模式:保证一个类仅有一个实例,并且提供一个可以访问的方法


/**
 * 6种单例模式写法
 * Created by XQM on 2018/5/13.
 */

//第一种,饿汉式.基于类加载机制,在类加载的时候就完成实例化,如果至始至终没有使用到该类会造成内存浪费
public class SingleDemo {
    private static SingleDemo instance = new SingleDemo();

    public static SingleDemo getInstance(){
        return instance;
    }
}

//第二种,懒汉式,第一次加载时需要实例化,反应慢,在多线程并发不能保证单例
public class SingleDemo{
    private static SingleDemo instance;

    public static SingleDemo getInstance() {
        if (instance == null){
            instance = new SingleDemo();
        }
        return instance;
    }
}

//每次调用都需要同步,造成不必要的同步开销
public class SingleDemo{
    private static SingleDemo instance;

    public static synchronized SingleDemo getInstance() {
        if (instance == null){
            instance = new SingleDemo();
        }
        return instance;
    }
}

//双重检查模式DCL,在某些情况下会失效
public class SingleDemo{
    private static SingleDemo instance;

    public static SingleDemo getInstance() {
        if (instance == null){
            synchronized (SingleDemo.class){
                if (instance == null){
                    instance = new SingleDemo();
                }
            }
        }
        return instance;
    }
}

//静态内部类单例模式,第一次类加载的时候并不会初始化instance,
//当且仅当调用了getInstance()时JVM加载SingleDemoHolder初始化instance,
//所以保证了线程安全和单例,推荐使用
public class SingleDemo{

    public static SingleDemo getInstance() {
       return SingleDemoHolder.instance;
    }

    private static class SingleDemoHolder{
        private static final SingleDemo instance = new SingleDemo();
    }
}

/**
 * 枚举单例
 */
public enum  SingleDemo{
    INSTANCE;

    private void doSomThing(){

    }
}

补充下JVM对内部类的加载顺序

//静态内部类单例模式,推荐使用
public class SingleDemo{
    public static SingleDemo getInstance() {
       return SingleDemoHolder.instance;
    }

    //类静态属性
    public static SingleDemo testOut = new SingleDemo(1);

    static {
        System.out.println("调用静态代码块:Static function");
    }
    private static class SingleDemoHolder{
        static {
            System.out.println("调用匿名内部类:Inner Static");
        }
        private static final SingleDemo instance = new SingleDemo(3);

    }

    public SingleDemo(int i) {
        switch (i){
            case 1:
                System.out.println("调用静态属性: " +" Construct! "+i);
                break;
            case 2:
                System.out.println("调用自身构造方法: " +" Construct! "+i);
                break;
            case 3:
                System.out.println("调用匿名内部类静态属性: " +" Construct! "+i);
                break;
        }
    }
}

//主函数测试,根据下面的结果发现,初始化的时候,静态块和静态变量是按顺序的,内部类按需调用
public class BuilderClient {
    public static void main(String[] args){
        SingleDemo singleDemo = new SingleDemo(2);
        SingleDemo.getInstance();

    }
}

这里写图片描述
二、建造者模式:用来创建复杂对象的模式,将其部件解耦。通常Android中的Dialog或者EventBus使用的时候会碰到。


/**
 * 定义产品
 * Created by XQM on 2018/5/13.
 */
public class Computer {
    private String mCpu;
    private String mMain;
    private String mCard;
    private String mRam;

    public String getmCpu() {
        return mCpu;
    }

    public void setmCpu(String mCpu) {
        this.mCpu = mCpu;
    }

    public String getmMain() {
        return mMain;
    }

    public void setmMain(String mMain) {
        this.mMain = mMain;
    }

    public String getmCard() {
        return mCard;
    }

    public void setmCard(String mCard) {
        this.mCard = mCard;
    }

    public String getmRam() {
        return mRam;
    }

    public void setmRam(String mRam) {
        this.mRam = mRam;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "mCpu='" + mCpu + '\'' +
                ", mMain='" + mMain + '\'' +
                ", mCard='" + mCard + '\'' +
                ", mRam='" + mRam + '\'' +
                '}';
    }
}


/**
 * 抽象产品的组建
 * Created by XQM on 2018/5/13.
 */
public abstract class Builder {
    public abstract void buildCpu(String cpu);
    public abstract void buildMainboard(String main_board);
    public abstract void buildGraphicsCard(String graphics_card);
    public abstract void buildRam(String ram);

    public abstract Computer create();
}

/**
 * 真正的建造者,实现build的方法,然后返回组建好的对象
 * Created by XQM on 2018/5/13.
 */
public class BuildComputer extends Builder {
    private Computer computer = new Computer();

    @Override
    public void buildCpu(String cpu) {
        computer.setmCpu(cpu);
    }

    @Override
    public void buildMainboard(String main_board) {
        computer.setmMain(main_board);
    }

    @Override
    public void buildGraphicsCard(String graphics_card) {
        computer.setmCard(graphics_card);
    }

    @Override
    public void buildRam(String ram) {
        computer.setmRam(ram);
    }

    @Override
    public Computer create() {
        return computer;
    }
}

public class Assembly {
    Builder builder;

    public Assembly(Builder builder) {
        this.builder = builder;
    }

    public Computer CreateComputer(String cpu ,String main,String card,String ram){
        builder.buildCpu(cpu);
        builder.buildMainboard(main);
        builder.buildRam(ram);
        builder.buildGraphicsCard(card);
        return builder.create();
    }
}

//测试主类
public class BuilderClient {
    public static void main(String[] args){
        Builder builder = new BuildComputer();
        Assembly assembly = new Assembly(builder);

        Computer sc = assembly.CreateComputer("i7-6700","联想","890","金士顿DDR4");

        System.out.println(sc.toString());

    }
}

三、享元模式:是池技术的重要实现方式,可以减少应用程序创建对象,降低产生OOM风险,提高程序的性能。

/**
 * 抽象享元角色
 * Created by XQM on 2018/5/13.
 */
public interface IGoods {
    void showGoodsPrice(String name);
}

/**
 * 具体享元角色,实现抽象享元角色
 * Created by XQM on 2018/5/13.
 */
public class Goods implements IGoods {
    private String name;//名称,内部状态
    private String attribute;//属性,外部状态

    public Goods(String name) {
        this.name = name;
    }

    @Override
    public void showGoodsPrice(String attribute) {
        if (attribute.equals("红色")){
            System.out.println("有货,价格是:8974元");
        }else {
            System.out.println("有货,价格是:8974元");
        }
    }
}

/**
 * 享元工厂用来创建具体的享元角色,通过map来缓存对象
 * 如果系统存在大量的相似对象或者缓存池的场景可以使用
 * Created by XQM on 2018/5/13.
 */
public class GoodsFactory {
    private static Map<String,Goods> goodsMap = new HashMap<>();

    public static Goods getGoods(String name){
        if (goodsMap.containsKey(name)){
            System.out.println("缓存中找到商品,key:"+name);
            return goodsMap.get(name);
        }else {
            Goods good = new Goods(name);
            goodsMap.put(name,good);
            System.out.println("创建商品,key:"+name);
            return good;
        }
    }
}


/**
 *测试类
 * 享元模式缓存对象,避免OOM
 * Created by XQM on 2018/5/13.
 */
public class FlywightClient {
    public static void main(String[] args){
        Goods goods = GoodsFactory.getGoods("华为3e");
        goods.showGoodsPrice("红色");

        Goods goods1 = GoodsFactory.getGoods("华为3e");
        goods1.showGoodsPrice("幻影黑");

        Goods goods2 = GoodsFactory.getGoods("华为9");
        goods2.showGoodsPrice("幻影黑");

    }
}

这里写图片描述
四、策略模式:定义一系列的算法,把算法封装起来,并且是它们可以相互替换,使得算法可以独立于使用它的客户而独立变化。比如代码有很多if…else或者case,会变得比较臃肿,维护成本也比较高,违背开放封闭原则,通过策略模式就可以简化。

/**
 * 定义一个程序开发的接口
 * 抽象策略角色
 * Created by XQM on 2018/5/13.
 */
public interface IDevelopStrategy {
    void develop();
}

/**
 * 开发
 * Created by XQM on 2018/5/13.
 */
public class APPStrategy implements IDevelopStrategy {
    @Override
    public void develop() {
        System.out.println("产品发话了,需要开发APP");
    }
}

/**
 * 具体的策略
 * Created by XQM on 2018/5/13.
 */
public class WebSiteStrategy implements IDevelopStrategy {
    @Override
    public void develop() {
        System.out.println("产品发话了,需要开发网站");

    }
}

/**
 * 上下文角色的构造方法根据传递进来不同的具体策略来调用不用的develop()
 * 屏蔽调用者对策略的直接访问,启动承上启下作用
 * Created by XQM on 2018/5/13.
 */
public class Context {
   private IDevelopStrategy strategy;

    public Context(IDevelopStrategy strategy) {
        this.strategy = strategy;
    }

    public void develop(){
        strategy.develop();
    }
}

/**
 * 每一个策略都是一个类,复用性小
 * 上层模块必须知道有哪些策略才可以使用
 * Created by XQM on 2018/5/13.
 */
public class StrategyClient {
    public static void main(String[] args){
        Context context;

        //开发APP
        context = new Context(new APPStrategy());
        context.develop();
        //开发网站
        context = new Context(new WebSiteStrategy());
        context.develop();
    }
}

这里写图片描述
五、观察者模式:定义对象间一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并且被自动更新。常见运用在发布-订阅事件总线。

/**
 * 把所有的观察者对象保存在一个集合中,其中每一个主题可以有任意数量的观察者,可以想象为公众号
 * Created by XQM on 2018/5/13.
 */
public interface ObservedSubject {
    /**
     * 增加观察者
     * @param observer
     */
    void add(Observer observer);

    /**
     * 删除观察者
     * @param observer
     */
    void delete(Observer observer);

    /**
     * 通知更新
     * @param message
     */
    void notify(String message);
}

/**
 * 抽象被观察者的实现类,实现添加、删除和通知观察者的方法
 * Created by XQM on 2018/5/13.
 */
public class SubcriptionSubject implements ObservedSubject {
    private List<Observer> subscriberUsers = new ArrayList<Observer>();
    @Override
    public void add(Observer oberver) {
        subscriberUsers.add(oberver);
    }

    @Override
    public void delete(Observer observer) {
        subscriberUsers.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer:subscriberUsers){
            observer.update(message);
        }
    }
}

/**
 * 抽象观察者
 * Created by XQM on 2018/5/13.
 */
public interface Observer {
    void update(String message);
}
/**
 * 具体观察者
 * Created by XQM on 2018/5/13.
 */
public class SubscriberUser implements Observer {
    private String name;

    public SubscriberUser(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name+"更新了:"+message);
    }
}

/**
 * 优点:观察者和被观察者之间是抽象耦合,容易扩展
 * 缺点:在Java中消息的通知一般是按照顺序的,如果每个观察者造成卡顿,会影响整体的效率,采用异步解决
 * Created by XQM on 2018/5/13.
 */
public class ObserverClient {
    public static void main(String[] args){
        SubcriptionSubject subcriptionSubject = new SubcriptionSubject();

        SubscriberUser user1 = new SubscriberUser("下雨了");
        SubscriberUser user2 = new SubscriberUser("下雪了");
        SubscriberUser user3 = new SubscriberUser("落花了");

        //注册订阅
        subcriptionSubject.add(user1);
        subcriptionSubject.add(user2);
        subcriptionSubject.add(user3);

        //发送更新给订阅者
        subcriptionSubject.notify("不一样的博客更新了");

    }

这里写图片描述
对比下Java中的观察者实现:

import java.util.Observable;

/**
 * 继承Observable类(被观察者发送消息),notifyObservers发送通知
 * Created by XQM on 2018/3/22.
 */
public class Gamedaily extends Observable {
    public void postNewArticle(String content){
        //内容改变
        setChanged();

        //通知所有订阅者改变内容
        notifyObservers(content);
    }
}

import java.util.Observable;
import java.util.Observer;

/**
 * 定义观察者,继承observer接口,实现update方法
 * Created by XQM on 2018/3/22.
 */
public class User implements Observer{
    public String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable observable, Object o) {
        System.out.println("Hi "+name +",公众号更新了内容:"+o);
    }
}


/**
 * Created by XQM on 2018/3/22.
 */
public class Client {
    public static void main(String[] args){
        Gamedaily gamedaily = new Gamedaily();
        User user0 = new User("user0");
        User user1 = new User("user1");
        User user2 = new User("user2");

        gamedaily.addObserver(user0);
        gamedaily.addObserver(user1);
        gamedaily.addObserver(user2);

        gamedaily.postNewArticle("有新文章更新了");
    }
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/xiaoming100001/article/details/80302143