Android6—设计模式

概念

设计模式Design pattern,是软件开发人员在开发过程中面临的一般问题的解决方案,这些方案是经过相当长的一段时间的的使用和修改总结而出。使用设计模式是为了可重用代码、让代码更容易被他人理解。设计模式是软件工程的结构。

四大要素

模式名称(Name)   问题(Question)
解决方案(Solution) 效果(Efftive)

三大类型

设计模式分为三种类型:

  • 创建型模式:单例模式,抽象工厂模式,建造者模式等。

  • 结构型模式:适配器模式,桥接模式,装饰模式,组合模式等。

  • 行为型模式:观察者模式,中介者模式,访问者模式,解释器模式,迭代器模式,备忘录模式等。

Android中的重要设计模式

单例模式

概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

优点:1、对于那些比较耗内存的类,只实例化一次可以大大提高性能。
      2、保持程序运行的时候该中始终只有一个实例存在内存中。

常见单例方法:
    public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton(){
    }
 
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
建造者模式(Builder模式)

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

优点:对于多参数类,使用重叠构造器,会有难读、难写、难维护的缺点;而直接使用javaBean,又难维护、难以保持参数一致性,特别是多线程的模式下,出bug难以找到原因。builder模式正好解决这一问题,支持链式调用,提高代码可读性。

常见Builder:
public class UserInfo  {
    private String name;
    private String mail;

    public String getName() {
        return name;
    }

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

    public String getMail() {
        return mail;
    }

    public void setMail(String mail) {
        this.mail = mail;
    }  

  //两个不同参数的构造方法
    public UserInfo(String name) {
        this.name = name;
    }

    public UserInfo(String name, String mail) {
        this.name = name;
        this.mail = mail;
    }

    //Bulider 的常见使用
    public static class UserBuilder {
        private String name;
        private String mail;

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

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

上述代码中,如果直接使用构造方法实例化UserInfo。 我们可能会写如下代码:

UserInfo userInfoOne = new UserInfo("张三","999@qq.com");
UserInfo userInfoTwo = new UserInfo("李四");

UserInfo userInfoThree = new UserInfo();
userInfoThree.setName("王五");
userInfoThree.setMail("777@q.com");

如果使用bulider实例化:

UserInfo .Builder builder=new UserInfo.Builder();
UserInfo userInfo=builder
        .name("张三")
        .mail("666@qq.com")
        .build();
观察者模式(发布/订阅模式)

概念:定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新

优点:观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

观察者,我们称它为Observer,有时候我们也称它为订阅者,即Subscriber。
被观察者,我们称它为Observable,即可以被观察的东西,有时候还会称之为主题,即Subject。

假定一种情况,有无数个购房者需要买同一套房子,他们需要知道房子的价格变化。对于这种情况,我们尝试使用观察者模式来解决。

//Observable 观察者
import java.util.Observable;

public class Price extends Observable {
    private int price;

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
        setChanged();
        notifyObservers();
    }

    @Override
    public String toString() {
        return "房价 [price=" + price + "]";
    }
}

//Observable被观察者

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

public class Buyer implements Observer {
    private int id;
    private Price price;

    public Buyer(int id) {
        System.out.println("我是购房者---->" + id);
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Price getPrice() {
        return price;
    }

    @Override
    public void update(Observable observable, Object data) {
        System.out.println("购房者---->" + id + "得到更新");
        this.price = (Price) observable;
        System.out.println("价格---->" + observable.toString());
    }
}

观察者和被观察者构建好之后,在使用时,我们需要将使用addObserver() deleteObserver()来绑定和解除绑定。而在开发过程中,我们会对其进行接口封装,使用registerunregister

适配器模式

概念: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

优点:1、更好的复用性 系统需要使用现有的类,而此类的接口不符合系统
         的需要。那么通过适配器模式就可以让这些功能得到更好的复
         用。
      2、更好的扩展性,在实现适配器功能的时候,可以调用自己开发的功
         能,从而自然地扩展系统的功能。

  • 目标(Target)角色:这就是所期待得到的接口。
  • 源(Adapee)角色:现在需要适配的接口。
  • 适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
public interface Target {  
    public void sampleOperation1();   
    public void sampleOperation2();   
}  

public class Adaptee {  
    public void sampleOperation1(){}  
 } 
类的适配器模式

类的适配器模式把适配的类的API转换成为目标类的API。

public class Adapter extends Adaptee implements Target {  
    @Override  
    public void sampleOperation2() {  
        //写相关的代码  
    }   
}  
对象的适配器模式

与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。

public class Adapter implements Target   {  
    private Adaptee adaptee;  
      
    public Adapter(Adaptee adaptee){  
        this.adaptee = adaptee;  
    }  
    
    public void sampleOperation1(){  
        this.adaptee.sampleOperation1();  
    }  
    
    public void sampleOperation2(){  
        //写相关的代码  
    }  
}  
命令模式

概念: 将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

优点: 1、比较容易地实现一个命令队列。
       2、比较容易将队列记入日志。
       3、请求者和实现者通过接口进一步解耦。
       4、可以容易地实现对请求的撤销和恢复。
       5、加入新的命令不影响其它类的操作。

  • 客户角色(Client):Client可以创建具体的命令对象,并且设置命令对象的接收者。Tips:不能把Clinet理解为我们平常说的客户端,这里的Client是一个组装命令对象和接受者对象的角色,或者你把它理解为一个装配者。
  • 调用者角色(Invoker):负责调用命令对象执行请求,通常会持有命令对象(可以持有多个命令对象)。Invoker是Client真正触发命令并要求命令执行相应操作的地方(使用命令对象的入口)。
  • 命令角色(Command):定义命令的接口,声明具体命令类需要执行的方法。这是一个抽象角色。
  • 具体命令角色(ConcreteCommand):命令接口的具体实现对象,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • 接收者角色(Receiver):Receiver是真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
//接收者角色类
    public class Receiver {
        public void action() {
           //TODO something
        }
    }

//抽象命令角色类
    public interface Command {
        void execute();
    }

//具体命令角色类
    public class ConcreteCommand implements Command {
        private Receiver receiver;

        public ConcreteCommand(Receiver receiver) {
            this.receiver = receiver;
        }

        public void execute() {
            receiver.action();
        }
    }

//请求者角色类
    public class Invoker {
        private Command command;

        public Invoker(Command command) {
            this.command = command;
        }

        public void action() {
            command.execute();
        }
    }

//客户端
    public class Client {
        public static void main(String[] args) {
            Receiver receiver = new Receiver();
            Command command = new ConcreteCommand(receiver);
            Invoker invoker = new Invoker(command);
            invoker.action();
        }
    }

总结

设计模式并不神秘,我们在每天的开发中都会不经意的使用它,去学习它、了解它,能够更好的帮助我们开发。有意地接触这方面的知识,比如高内聚、低耦合、封装变化,在设计接口的时候都是非常重要的原则。如有不足之处,希望多多指出。

原文作者litterMay
原文链接:https://www.jianshu.com/p/d079f8cc4f7f

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342