Android设计模式二

设计模式类图在此链接

//www.greatytc.com/p/4fe3bb697a8f

“接口隔离”模式:

在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题,甚至根本无法实现。采用添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口是一种常见的解决方案。

典型模式
Facade(外观模式)
Proxy(代理模式)
Adapter(适配器模式)
Meditor(中介者模式)

Facade(外观模式)

动机(Motivation)

  • 在一个大型代码外部增加新的特性,会导致新代码和旧代码中的子系统产生过多耦合,抵御变化能力降低。

  • 如何简化外部客户程序和系统间的交互接口?如何将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦?

模式定义
为子系统中的一组接口提供一个一直(稳定)的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用(复用)。
——《设计模式》

要点总结

  • 从客户程序的角度来看,Facade模式简化了整个组件系统的接口,对于组件内部与外部客户程序来说,达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Facade接口的变化。
  • Facade设计模式更注重从框架的层次去看整个系统,而不是单个类的层次。Facade很多时候更是一种架构设计模式。
  • Facade设计模式并非一个集装箱,可以任意地放进任何多个对象。Facade模式中组件的内部应该是“相互耦合关系比较大的一系列组件”,而不是一个简单的功能集合。

Strategy 策略模式

动机(Motivation)

  • 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

  • 如何在运行时根据需要透密地更新对象的算法?将算法与对象本身解耦,从而避免上述问题?

模式定义
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可以独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
——《设计模式》

abstract class TaxStrategy {
    abstract double Calculate(Context context);
}

class CNTax extends TaxStrategy {

    @Override
    double Calculate(Context context) {
        return 0;
    }
}

class USTax extends TaxStrategy {

    @Override
    double Calculate(Context context) {
        return 0;
    }
}

class DETax extends TaxStrategy {

    @Override
    double Calculate(Context context) {
        return 0;
    }
}

class FRTax extends TaxStrategy {

    @Override
    double Calculate(Context context) {
        return 0;
    }
}


public class SaleOrder {
    TaxStrategy taxStrategy;

    public SaleOrder(TaxStrategy taxStrategy) {
        this.taxStrategy = taxStrategy;
    }

    public double CalculateTax() {
        Context context = null;
        double val = taxStrategy.Calculate(context);
        return val;
    }
}

要点总结

  • Strategy及其子类为组件提供了一系列可重用的算法,从而使得类型在运行时方便地根据需要在各个算法之间进行切换。
  • Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。

Observer观察者模式

动机(Motivation)

  • 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

  • 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
——《设计模式》

public class MainActivity extends AppCompatActivity {

    private Button mAppendButton;
    private EditText mEditText;
    private TextView mLabelText;

    private int count=0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mAppendButton = (Button) findViewById(R.id.appendButton);
        mEditText = (EditText) findViewById(R.id.contentEdit);
        mLabelText = (TextView) findViewById(R.id.countText);


        //订阅通知
        mEditText.addTextChangedListener(textWatcher);

        //取消订阅
        //mEditText.removeTextChangedListener(textWatcher);

        mAppendButton.setOnClickListener(clickListener);


    }


    OnClickListener clickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            String content = mEditText.getText().toString().trim();
            //文本框内容处理
            content = content + Integer.toString(count);
            count++;
            mEditText.setText(content);
            mEditText.setSelection(content.length());//光标置于末尾
        }
    };


    TextWatcher textWatcher = new TextWatcher() {

        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            Log.i("BeforeTextChanged:", s.toString() );
        }


        public void onTextChanged(CharSequence s, int start, int before, int count) {

            Log.i("OnTextChanged:", s.toString() );
        }

        public void afterTextChanged(Editable s) {
            String count = Integer.toString(s.length());
            mLabelText.setText(count);
        }
    };

}

要点总结

  • 增加的Listener会组成一个ArrayList,每当目标对象状态发生改变,则遍历ArrayList通知所有观察者。
  • 使用面向对象的抽象,Observer模式使我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
  • 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
  • Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。

“单一职责”模式:

Decorator(装饰模式)
Bridge(桥接模式)

Decorator(装饰模式)

动机(Motivation)

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”由于继承为类型引入的静态特质,使得这种扩展方法缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。

  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?

  • 一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加功能。我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。它将客户请求转发给该组件,并且可能在转发前后执行一些额外的动作。透明性使得你可以递归的嵌套多个装饰,从而可以添加任意多的功能。

模式定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更多灵活(消除重复代码&减少子类个数)。
——《设计模式》

abstract class Stream {
    public abstract char read(int number);

    public abstract void seek(int position);

    public abstract void write(char data);
}

//主体类
class FileStream extends Stream {

    @Override
    public char read(int number) {
        return 0;
    }

    @Override
    public void seek(int position) {

    }

    @Override
    public void write(char data) {

    }
}

class NetworkStream extends Stream {
    @Override
    public char read(int number) {
        return 0;
    }

    @Override
    public void seek(int position) {

    }

    @Override
    public void write(char data) {

    }
}

class MemoryStream extends Stream {
    @Override
    public char read(int number) {
        return 0;
    }

    @Override
    public void seek(int position) {

    }

    @Override
    public void write(char data) {

    }
}

//继承:接口协议
abstract class DecroratorStream extends Stream {
    protected Stream s;

    protected DecroratorStream(Stream s) {  //可以传递Stream的子类,根据不同的主体,进行不同的活动
        this.s = s;
    }
}

class CroptoStream extends DecroratorStream {
    //通过调用父类,实例化s
    public CroptoStream(Stream s) {
        super(s);
    }

    @Override
    public char read(int number) {
        s.read(number);
        return 0;
    }

    @Override
    public void seek(int position) {
        s.seek(position);
    }

    @Override
    public void write(char data) {
        s.write(data);
    }
}

class BufferedStream extends DecroratorStream{
    //通过调用父类,实例化s
    public BufferedStream(Stream s) {
        super(s);
    }

    @Override
    public char read(int number) {
        s.read(number);
        return 0;
    }

    @Override
    public void seek(int position) {
        s.seek(position);
    }

    @Override
    public void write(char data) {
        s.write(data);
    }
}

class Client{
    public static void main(String[] args) {
        FileStream fileStream = new FileStream();
        Stream s1 = new CroptoStream(fileStream);
        Stream s2 = new BufferedStream(new MemoryStream());
        Stream s3 = new CroptoStream(new BufferedStream(new NetworkStream()));
    }
}

要点总结

  • 通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
  • Decorator类在接口是表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另一个Component类。
  • Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。

Bridge (桥接模式)

动机(Motivation)

  • 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个维度的变化。
  • 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?

模式定义
将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。
——《设计模式》

abstract class Messager {
    MessageImp msgImp;  //实现了MessageImp子类的功能

    protected Messager(MessageImp msgImp) {
        this.msgImp = msgImp;
    }

    public abstract void login(String username, String password);
    public abstract void sendMessage(String message);
    public abstract void sendPicture(Image image);

}

abstract class MessageImp{
    public abstract void playSound();
    public abstract void drawShape();
    public abstract void writeText();
    public abstract void connect();
}

//平台实现
class PCMessageImp extends MessageImp{
    @Override
    public void playSound() {

    }

    @Override
    public void drawShape() {

    }

    @Override
    public void writeText() {

    }

    @Override
    public void connect() {

    }
}

class MobileMessageImp extends MessageImp{
    @Override
    public void playSound() {
        
    }

    @Override
    public void drawShape() {

    }

    @Override
    public void writeText() {

    }

    @Override
    public void connect() {

    }
}

//业务抽象
class MessagerLite extends Messager{
    
    protected MessagerLite(MessageImp msgImp) {
        super(msgImp);
    }

    @Override
    public void login(String username, String password) {
        msgImp.connect();
    }

    @Override
    public void sendMessage(String message) {
        msgImp.writeText();
    }

    @Override
    public void sendPicture(Image image) {
        msgImp.drawShape();
    }
}

class MessagerPerfect extends Messager{
    
    protected MessagerPerfect(MessageImp msgImp) {
        super(msgImp);
    }

    @Override
    public void login(String username, String password) {
        msgImp.playSound();
        msgImp.connect();
    }

    @Override
    public void sendMessage(String message) {
        msgImp.playSound();
        msgImp.writeText();
    }

    @Override
    public void sendPicture(Image image) {
        msgImp.playSound();
        msgImp.drawShape();
    }
}

要点总结

  • Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,即“子类化”它们。
  • Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
  • Bridge模式的应用一般在“两个非常强的变化维度”,有时一个类也有多于两个的变化维度,这时可以使用Bridge的扩展模式。

"对象创建“模式:
典型模式
Factory Method(工厂方法)
Abstract Factory(抽象工厂模式)
Prototype(原型模式)
Builder(生成器)

  • 6.Factory Method模式 Factory method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。 Factory Method模式通过面对对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展的策略,较好地解决了这种紧耦合关系。 Factory Method模式解决“单个对象”的需求变化,缺点在于要求创建方法/参数相同。

  • 7.Abstract Factory工厂 该模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。 如果没有应对“多系列对象构建”的需求变化,则没有必须使用这个模式,这时候使用简单工厂完全可以。
    由于设计模式很多,而且设计模式在初学阶段一般不做要求,所以对于初学者大家可以不用掌握,但要在设计中逐渐去体会它。

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

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,922评论 1 15
  • 设计模式基本原则 开放-封闭原则(OCP),是说软件实体(类、模块、函数等等)应该可以拓展,但是不可修改。开-闭原...
    西山薄凉阅读 3,760评论 3 13
  • 本文首发于个人博客:Lam's Blog - 谈谈23种设计模式在Android源码及项目中的应用,文章由Mark...
    格子林ll阅读 4,632评论 1 105
  • 本文是《设计模式——可复用面对对象软件的基础》的笔记。 面对对象设计的几个原则:1.针对接口编程,而不是针对实现编...
    Lension阅读 1,181评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,597评论 18 399