android之设计模式

Android中用到的设计模式        Android系统使用Java语言进行开发,Android源码中设计模式的使用无处不在,以至于日常的开发中,也会根据不同的情况直接套用相应的设计模式。阅读Android源码的一大乐趣就是可以学习到Google大牛对设计模式的灵活运用。下面就来看一下Android系统都用了哪些常用的设计模式。 模板方法模式        这应该是我们在Android开发中接触的比较早的设计模式。新... 阅读详情

http://www.linuxidc.com/Linux/2012-01/52269.htm

 

=======================2011-08-26==================================
有时候,最难的是坚持;有时候缺少的是信念。
=======================2011-08-07==================================
从接触设计模式到如今大概4年左右的时间,一直都想有朝一日定要精通,坐于床头,侧望左右,设计模式的书买了7,8本了,也看了很多参考和视频,也用到了一些。但是今天我终于停下来,停下来梳理,停下来欣赏,也停下来反省,总之,我今天停下来了,是为了走的更好,走的更远。

如果有幸我能够把这个系列写到23+N,我想至少我的技术上会为我增色不少,会为我带来更强烈的信心;
如果有幸我能够把这个系列写到23+N,我想至少我去买者方面书籍的时候,我不会那么动心了,我也许不深,你也未必;
如果有幸我能够把这个系列写到23+N,我想至少后面架构和android的底层我会更加了解,我会看的更清楚,也看的更远。
我自己也是这么想得,所以我会坚持,我要把这个进行到底,写下去,写完23,我写+N,写完SDK,我写别人的开源项目,写完开源,我写我个人项目,写完个人项目,我写我自己的开源项目,至少我要写到我认为我应该继续写的时候,我如是想,也如是做!
我就是这么想的!
=======================2011-07-29==================================
看了很多年的设计模式,也看了很多种设计模式,也在工作中用了几个常见的设计模式。
android中,包括源码和一些开源项目,用到了很多经典设计模式,而且也用的非常的精彩。
学习android也有一些日子了,有空的时候看看源代码,看看开源项目的代码,自己也会再工作中写写代码。
今天,斗胆,基于android(其实就是java),把自己对设计模式的一些粗浅认识,默默的分享出来,希望能得到各位同仁的指点,以期设计能力更进一步。
我将以《设计模式:可复用面向对象软件的基础》为准,发掘android中各种设计模式的使用情况,提取核心部分,做为实例。
因为不需要写代码,应用场景又一般是android中自带的,所以文中可能会注重意图介绍和UML结构图的绘制,然后具体设计模式的本身和扩展还需要各位参考其他资料。
下面我列举一些重要的认识点:

设计模式,提供了很多软件工程问题所需处理的解决方案。

根据模式的目的可分为3类:
1.创建型模式:与对象的创建有关。
2.结构性模式:处理类与对象的组合。
3.行为性模式:对类或对象怎样交互和怎样 分配职责进行描述。

面向对象设计的2个基本原则:
1.针对接口编程,而不是针对实现编程。
2.优先使用对象组合,而不是类继承。

面向对象设计的5个设计原则:
1.单一职责原则(SRP)
2.开放封闭原则(OCP)
3.Liskov替换原则(LSP)
4.依赖倒置原则(DIP)
5.接口隔离原则(ISP)

23中设计模式:
1.创建型模式:
(1).工厂方法模式
(2).抽象工厂模式
(3).创建者模式
(4).原型模式
(5).单例模式
2.结构型模式:
(6).适配器模式
(7).桥模式
(8).组合模式
(9).装饰模式
(10).外观模式
(11).享元模式
(12).代理模式
3.行为型模式
(13).解释器模式
(14).模板方法模式
(15).职责链模式
(16).命令模式
(17).迭代器模式
(18).中介者模式
(19).备忘录模式
(20).观察者模式
(21).状态模式
(22).策略模式
(23).访问者模式
除此之外,后来人发现很多新的模式,如空模式等。

下面列举几个常见的问题导致重新设计,可能需要设计模式来分析解决:
1.通过显示的指定一个类来创建对象
2.对特殊操作的依赖
3.对硬件和软件平台的依赖
4.对对象表示或实现的依赖
5.算法依赖
6.紧耦合
7.通过生产子类来扩展功能
8.不能方便的对类进行修改

软件的设计臭味:
1.僵化性
2.脆弱性
3.顽固性
4.粘滞性
5.不必要的复杂性
6.不必要的重复
7.晦涩性
... ...
总而言之,一句话,面向对象特性+原则+模式,折腾来折腾去就是这么个回事。


Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和ViewGroup类的使用。在android UI设计,几乎所有的widget和布局类都依靠这两个类。
组合模式,Composite Pattern,是一个非常巧妙的模式。几乎所有的面向对象系统都应用到了组合模式。

1.意图
将对象View和ViewGroup组合成树形结构以表示"部分-整体"的层次结构(View可以做为ViewGroup的一部分)。

组合模式使得用户对单个对象View和组合对象ViewGroup的使用具有一致性。
热点词汇: 部分-整体 容器-内容 树形结构 一致性 叶子 合成 安全性 透明性

2.结构


111



针对View和ViewGroup的实际情况,我们选择安全式的组合模式(在组合对象中添加add,remove,getChild方法),添加少许的注释,我们把上图修改为:


222



3.代码
View类的实现:

public class View{
        //... ...
        //省略了无关的方法
}

ViewGroup的实现:

public abstract class ViewGroup extends View{
   
    public void addView(View child) {
        //...
    }
 
    public void removeView(View view) {
        //...
    }
 
   
    public View getChildAt(int index) {
        try {
            return mChildren[index];
        } catch (IndexOutOfBoundsException ex) {
            return null;
        }
    }
 
    //other methods
}

4.效果
(1).结构型模式
(2).定义了包含基本对象和组合对象的类层次结构。这种结构能够灵活控制基本对象与组合对象的使用。
(3).简化客户代码。基本对象和组合对象有一致性,用户不用区分它们。
(4).使得更容易添加新类型的组件。
(5).使你的设计变得更加一般化。


观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下。
本文以AbstractCursor为例子,展开分析。
观察者模式,Observer Pattern,是一个很实用的模式,本人曾经接触到的各种平台以及曾经参与项目中打印模板解释器中都用到了此模式。

1.意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
热门词汇:依赖 发布-订阅 事件 通知 更新 监听

2.结构


333



这是一个最简单的观察者模式,目标对象能够添加和删除观察者,当自己某种状态或者行为发生改变时,可通过notify通知注册的观察者进行更新操作。
分析AbstractCursor的具体情况,我们发现实际工作有时需要对观察者进行统一管理,甚至观察者类型有很多种而又可以分成几个系列,这个时候是要复杂的多,通过合理的分层这个问题很好解决。下面根据具体情况,我们画出android中abstractCurosr中用到的观察者模式结构图:

444



观察者分成了两个系列。

3.代码
列举其中相关核心代码如下:

 public abstract class AbstractCursor {
    //定义管理器
    DataSetObservable mDataSetObservable = new DataSetObservable();
    ContentObservable mContentObservable = new ContentObservable();
     
    //注册和卸载两类观察者
    public void registerContentObserver(ContentObserver observer) {
        mContentObservable.registerObserver(observer);
    }
 
    public void unregisterContentObserver(ContentObserver observer) {
        // cursor will unregister all observers when it close
        if (!mClosed) {
            mContentObservable.unregisterObserver(observer);
        }
    }
 
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
         
    }
 
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
 
    //2类通知方法
    protected void onChange(boolean selfChange) {
        synchronized (mSelfObserverLock) {
            mContentObservable.dispatchChange(selfChange);
            if (mNotifyUri != null && selfChange) {
                mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
            }
        }
    }
 
    protected void notifyDataSetChange() {
        mDataSetObservable.notifyChanged();
    }
}

 

  再看看Observable<T>类和DataSetObservable类:

 public abstract class Observable<T> {
   
    protected final ArrayList<T> mObservers = new ArrayList<T>();
 
    public void registerObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            if (mObservers.contains(observer)) {
                throw new IllegalStateException("Observer " + observer + " is already registered.");
            }
            mObservers.add(observer);
        }
    }
 
 
    public void unregisterObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            int index = mObservers.indexOf(observer);
            if (index == -1) {
                throw new IllegalStateException("Observer " + observer + " was not registered.");
            }
            mObservers.remove(index);
        }
    }
     
    public void unregisterAll() {
        synchronized(mObservers) {
            mObservers.clear();
        }        
    }
}

 

和

public class DataSetObservable extends Observable<DataSetObserver> {
   
    public void notifyChanged() {
        synchronized(mObservers) {
            for (DataSetObserver observer : mObservers) {
                observer.onChanged();
            }
        }
    }
    //... ... (其他方法)
}

  

观察者DataSetObserver类是一个抽象类:

public abstract class DataSetObserver {
    public void onChanged() {
        // Do nothing
    }
}

 

所以我们具体看它的子类:

public class AlphabetIndexer extends DataSetObserver{
   
    @Override
    public void onChanged() {
        //观察到数据变化,观察者做自己该做的事情
        super.onChanged();
        mAlphaMap.clear();
    }
}

  ContentObserver也是类似。

4.效果
(1).行为型模式
(2).目标和观察者间的抽象耦合(经典实现)。
(3).支持广播通信(相信这点android开发者看到后应该有启发吧)。
(4).注意意外的更新,这也是观察者更新进行管理的原因之一。


单例模式,可以说是GOF的23种设计模式中最简单的一个。
这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),很有意思,是一个感觉上很干净的模式,本人很喜欢这个模式。
android中很多地方都用到了单例模式,本文以输入法管理者InputMethodManager为例,展开分析。

单例模式,Singleton Pattern,能够以其特有的优势,替代系统中全局变量,应用非常广泛。

1.意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
热门词汇:单例 唯一 私有构造

2.结构

555



android中有很多系统级别的全局变量,如时间,输入法,账户,状态栏等等,android中对这些都直接或者有些间接用到了单例模式。
以输入法为例,把上图修改为实际情况:

666


非常的简单,但是有一点,从上面我们也看到了synchronized关键字,在多线程的环境下,单例模式为了保证自己实例数量的唯一,必然会做并发控制。
类似这种线程安全的单例,跨进程的单例,参数化的单例等等的情况,确实超出本文的范围,而且都涉及到很多东西,是一个很大的话题,不好展开。

3. 代码:

public final class InputMethodManager {
    static final Object mInstanceSync = new Object();//同步
    //内部全局唯一实例
    static InputMethodManager mInstance;
 
    //对外api
    static public InputMethodManager getInstance(Context context) {
        return getInstance(context.getMainLooper());
    }
     
   
    static public InputMethodManager getInstance(Looper mainLooper) {
        synchronized (mInstanceSync) {
            if (mInstance != null) {
                return mInstance;
            }
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            mInstance = new InputMethodManager(service, mainLooper);
        }
        return mInstance;
    }
}

  客户端调用,比如contextimpl中的getSystemService()方法中如下调用:

 class ContextImpl extends Context{
    @Override
    public Object getSystemService(String name) {
        if (WINDOW_SERVICE.equals(name)) {
            //... ... 省略下面n个if,else if
        } else if (INPUT_METHOD_SERVICE.equals(name)) {
            //获取输入法管理者唯一实例
            return InputMethodManager.getInstance(this);
        }  else if (KEYGUARD_SERVICE.equals(name)) {
             //... ... 省略下面n个if,else if
        } else if (ACCESSIBILITY_SERVICE.equals(name)) {
            //又见单例,无处不在
            return AccessibilityManager.getInstance(this);
        } else if (LOCATION_SERVICE.equals(name)) {
            //... ... 省略下面n个if,else if
        }  else if (NFC_SERVICE.equals(name)) {
            return getNfcManager();
        }
        return null;
    }
}

  非常简单,干净的一个模式。

4.效果
(1).创建型模式。
(2).对唯一实例的受控访问。
(3).避免全局变量污染命名空间。
(4).允许对操作和表示的精化。
(5).比类操作更灵活。


模板方法,和单例模式是我认为GOF的23中最简单的两种模式。
但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分,是面向对象的一种基本认识。
打比方说父亲有很多理想,就行医救人吧,但是父亲医术不行,只能靠儿子,儿子长大后遵从父亲大志,春风拂面,妙手回春,实现了父亲的理想,儿子做的事情早在出生前就定下来了,是父亲之前久定好的模板。

认识到模板方法的这种思想,父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情,对框架学习大有帮助。
本文以View中的draw方法为例,展开分析。
模板方法,TemplateMethod,光是学习这个模式,就会对你产生长远影响的一个模式。

1.意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
热门词汇:骨架 步骤 结构 延迟到子类

2.结构

777



定义了几个步骤1,2,3等,在模板方法中按照一定的结构顺序执行这些步骤。父类的方法可以有缺省实现,也可以是一个空实现,即所谓的钩子操作。
结合实际情况,我们画出View中draw方法涉及到的几个步骤方法如下:

888




学习模板方法对于我们了解框架的基类实现,生命周期和流程控制非常有帮助,我觉得是务必要掌握的一个模式。

3.代码

public class View{
   
    protected void onDraw(Canvas canvas) {
    }
 
   
    protected void dispatchDraw(Canvas canvas) {
    }
 
    //算法骨架
    public void draw(Canvas canvas) {
       if (!verticalEdges && !horizontalEdges) {
            // 步骤1
            if (!dirtyOpaque) onDraw(canvas);
 
            // 步骤2
            dispatchDraw(canvas);
 
            // 步骤3
            onDrawScrollBars(canvas);
 
            return;
        }
    }
    //... ...
}

  我们看看系统组件TextView的实现:

 public class TextView{
    @Override
    protected void onDraw(Canvas canvas) {
        //大量自定义实现代码
    }
}

  如果我们自定义View的话,我们一般也是重写onDraw方法即可:

public class MyView extends View {
 
    public MyView(Context context) {
        super(context);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
 
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
    }
     
}

4.效果
(1).模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
(2).模板方法导致一种方向控制结构,"好莱坞法则":"Don't call me,i will call you.",即一个父类调用子类的操作,而不是相反。
(3).模板调用操作的类型有具体的操作,具体的AbstracClass操作,原语操作,工厂方法,钩子操作。少定义原语操作。
(4).android中对这些重定义操作的命名喜欢在方法前加一个前缀on。
(5).模板方法使用继承来改变算法的一部分。策略模式使用委托来改变整个算法。


备忘录模式,在工作代码中,要么不用,要么经常用到。
举个例子,程序员喜欢写代码,coding,coding,这个时候它的状态是很high,但是每隔一段时间总要去上一下厕所,状态是放松relax,上完测试归来后又恢复到high的状态,继续coding。这个过程对于身后的老板来说,它默认同意你离开去上厕所,他也希望你回来后恢复high的状态继续工作,但是你在这个过程中上厕所的这件事,他是不需要了解细节的,而且做为当事人你也不希望他了解你上厕所的细节吧,你只要回来后恢复激情high着继续工作,老板应该就不会挑你的刺。

这就是备忘录模式。
本文今天就Canvas的一个save(),restore()操作分析一下,但是有一点,看完本文,如果不懂备忘录模式的,应该还是不懂,但是canvas是android的一场大戏,说一说它的特色,对深入学习android绝对有帮助。
学习备忘录模式,通过保存状态,恢复状态的内部实现,对了解一些莫名其妙的看上去无用其实很重要的操作有拨开云雾见青天的作用。

1.意图
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到先前保存的状态。
热门词汇:标记 状态 备忘录 原发器

2.结构和代码

999



组织者,把原发器的状态State(全部或者部分状态,一般是变量的值),通过CreateMemento()方法保存起来,继续运行后,等待合适的时机,在通过SetMemento()方法可以再次恢复到之前的状态。在这个过程中,我们并没有对这些状态做任何的访问和设置,实际上这些状态都是私有的,对外是禁止访问的,我们只是通过Memento对象的两个最简单的方法就达到了这个效果。Memento经常写成Originator的内部类。
在Android中,Canvas有两个方法 save()和restore()方法再做图形变换的时候使用的非常多,因为涉及到跨语言的问题,我不好就认定这个用的是备忘录模式,但是它的这种思想绝对是备忘录的思想。

10 10



我们来读一读它源代码的注释吧,首先看save()保存状态:

public class Canvas {
   
   
    public native int save();
}

 

再看恢复状态restore():

 public class Canvas {
   
   
    public native void restore();
}

  从上面的两个方法中,它们实现了自我状态的恢复,实际上我们只是执行了两个没有接触任何内部信息的方法,实际上这两个方法就是在操作我们看不到的这些内部状态信息。

3.效果
(1).保持封装边界,把很复杂的原发器的内部信息对外部其他对象隐藏起来。
(2).简化的原发器,把状态操作无形中转化到客户手里,简化了原发器的某些实现。
(3).也要注意注意备忘录的管理代价。

 

享元模式,给我的感觉就是对象池,缓存单例对象。
java中的享元模式最经典的例子就是String类了,还有一个最容易理解的就是word文档字符共享的例子,也是享元模式的经典应用。
本文对android中的sql编译类SQLiteCompiledSql说明,展开分析,也是很容易理解的一个例子,其实,android SDK中必然有很多地方需要用到享元模式。

享元模式,Flyweight  Pattern,说的严重点,一些程序如果不使用享元模式的话,根本不能使用面向对象的方法实现,对象会多的撑爆你的内存:"用面向对象思想设计的应用常常会面临对象实例过多的问题"。

1.意图
运用共享技术有效地支持大量细粒度的对象。
热门词汇:共享 池 缓存 内部状态 外部状态 对象 单例

2.结构

11 11



这是一个完整的享元模式结构图。
客户端通过享元工厂获取享元对象,享元对象的创建则根据工厂的享元池来控制,如果有享元池中没有这个对象,则创建这个对象并保存到享元池中,如果享元池中有这个对象,则直接使用这个对象。因为享元对象在共享的同时,说明它重用属性的不变性,不然都是变化的东西,不存在共享,这些不变得属性我们称之为内部状态,独立与外部场景。而另外一些属性,可以根据外部场景变化的,我们称之为外部状态,在上图中我们也看到,我们可以通过Operation改变外部状态。
Android中SQLiteCompiledSql的使用,其实是很多数据库系统典型的实现。从应用启动,通过各种数据库操作,我们不知道进行了多少次的查询操作,而这些操作中又有相当一部分sql语句是相同的,这些编译后的sql编译对象其实是一样的,是可以共用共享的,其实就是缓存。SQLiteCompiledSql就是这样的一个需要共享的享元对象,画出相关的UML图如下:

12 12



其中SqliteDatabase中的mCompiledQuerie就是存放享元对象的容器。
通过这种方式大大减少了sql编译对象的创建,提高了数据库操作的性能。

3.代码
享元对象类SQLiteCompiledSql,主要是内部状态sql语句:

class SQLiteCompiledSql {
    private String mSqlStmt = null;
    native_compile(sql); 
    native_finalize();
}

享元工厂类:

public class SQLiteDatabase{
     Map<String, SQLiteCompiledSql> mCompiledQueries = Maps.newHashMap();
     SQLiteCompiledSql getCompiledStatementForSql(String sql) {
        SQLiteCompiledSql compiledStatement = null;
        boolean cacheHit;
        synchronized(mCompiledQueries) {
            if (mMaxSqlCacheSize == 0) {
                return null;
            }
            cacheHit = (compiledStatement = mCompiledQueries.get(sql)) != null;
        }
        if (cacheHit) {
            mNumCacheHits++;
        } else {
            mNumCacheMisses++;
        }
        return compiledStatement;
    }
 
    private void deallocCachedSqlStatements() {
        synchronized (mCompiledQueries) {
            for (SQLiteCompiledSql compiledSql : mCompiledQueries.values()) {
                compiledSql.releaseSqlStatement();
            }
            mCompiledQueries.clear();
        }
    }
 
    void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {
         //省略具体代码
    }
}

  其他类几个相关类是对这个集合的操作相关,和享元模式没有什么实质性的关系,代码省略。

4.效果
(1).结构型模式;
(2).节约存储的方法:用共享减少内部状态的消耗,用计算时间换取对外部状态的存储;
(3).缓冲。


命令模式,在.net,java平台的事件机制用的非常多,几乎每天都与之打交道。
android中对我印象最深的就是多线程多进程的环境,所以必然大量使用到Runbable,Thread,其实用的就是最简单的命令模式。
命令模式,Command Pattern,把请求封装为一个对象,多么巧妙的一个说法啊。

1.意图

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
热门词汇:动作 事物 请求封装 排队 打包 异步

2.结构

13 13



Command接口提供了Execute方法,客户端通过Invoker调用命令操作来调用Recriver,绕了一大圈,但是却把具体对Receiver的操作请求封装在具体的命令中,是客户端对recriver的操作清晰简明。
但是在实际项目中,我们常常忽略Receiver,而把命令对象的目标对象直接设置为子类自己的成员变量或者作为execute()方法的临时变量。
以Android中的Runnable(在java.lang包下)为例,我们画出UML结构图如下:

14 14



想不到我们天天写的代码无意识中就是用到了命令模式,所谓模式,就是无所不在。

3.代码
命令接口Runnable定义如下:

public interface Runnable {
    public abstract void run();
}

调用者Thread简化版代码:

//命令模式这里不需要继承Runnable接口,但是这里考虑到实际情况,比如方便性等,继承了Runnable接口,实现了run方法,这个是Thread自身的运行run的方法
class Thread implements Runnable {
    private Runnable target;
     
    public Thread(Runnable target) {
        this.target = target;
    }
 
     public synchronized void start() {
 
        if (threadStatus != 0 || this != me)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();//这个是本地方法,调用run方法
        if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
    }
 
    //可选
    public void run() {
    if (target != null) {
        target.run();
    }
    }
}

 

客户端只需要new Thread(new Runnable(){}).start()就开始执行相关的一系列的请求,这些请求大部分都是实现Runnable接口的匿名类。

4.效果
(1).行为型模式;
(2).将调用对象的操作和知道如何实现该操作的对象解耦;
(3).多个命令可以装配成一个复合命令;
(4).增加新的命令很容易。


 

工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式。
android中用到了太多的工厂类,其中有用工厂方法模式的,当然也有很多工厂并不是使用工厂方法模式的,只是工具管理类。
今天以ThreadFactory举例说明一下简单工厂模式和工厂方法模式。
工厂方法模式,Factory Method,简单的方式,不简单的应用。


1.意图
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方式模式使一个类的实例化延迟到其子类。
热门词汇:虚构造器 延迟 创建对象 子类

2.结构图和代码
我们先看看标准的工厂方法结构图:

15 15



先抽象的产品类,抽象的工厂类,然后用客户端具体的工厂生产相应的具体的产品,但是客户端并不知道具体的产品是怎么生产的,生产的过程封装在工厂里。所以说,某种程度上,工厂方法模式改变了我们直接用new创建对象的方式,一个很好的开始,意义重大。
以ThreadFactory为例:

16 16



这张图其实和原本的结构图有细微的区别,那就是参数化得工厂,而且从业务意义上也有些不同,但是思想是一样的。
我们来看下具体的代码:

//抽象产品
public interface Runnable {
    public abstract void run();
}
 
//抽象工厂
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());
    }
};
//那么产品类在哪里呢?
//做为参数Runnable r,我们可以创建千千万万个此系列的产品类
//同理,我们可以创建另外类似的工厂,生产某种专门的线程,非常容易扩展

看到这里,我们一方面为它的生产便利性感叹,一方面又为没创建某类产品都要创建一个工厂而感到繁琐,所以我们下面介绍简单工厂,它的结构图如下:

17 17



简单工厂把抽象工厂去掉了,你就创建一个专门生产某类产品就好。在一些特定而又不负责的领域非常实用方便套用这个模式。
在android中的Connection类中使用到了这个类:

18 18



其中Connection这个抽象类,既充当抽象产品类,也充当具体工厂类。
因为这种情况下,我们往往需要的是马上生产子类,getConnection方法往往是静态的,所以简单工厂,也叫静态工厂方法。
我们看看代码如下:

abstract class Connection{    
    static Connection getConnection(
            Context context, HttpHost host, HttpHost proxy,
            RequestFeeder requestFeeder) {
 
        if (host.getSchemeName().equals("http")) {
            return new HttpConnection(context, host, requestFeeder);
        }
 
        // Otherwise, default to https
        return new HttpsConnection(context, host, proxy, requestFeeder);
    }
}

这就是简单工厂,一个很简单的参数化工厂,真的很简单。

3.效果
1. 创建型模式;
2.参数化工厂方法模式得到相应的对象;
3.为子类提供挂钩;
4.连接平行的类层次。

Android面试题_安卓面经(23/30)设计模式源码案例 无论是做哪种编程语言的开发工作,过了新手期后,都需要了解设计模式,在安卓开发中也一样,本人曾在面试中让我列举安卓源码中设计模式的案例。 阅读详情

相关推荐

软考中级-系统集成项目管理工程师**的超详细知识点笔记。

软考中级系统集成项目管理工程师核心知识点摘要 综合知识:涵盖信息化基础(国家信息化六要素、信息系统开发方法)、系统集成特点(高技术性、团队协作)、IT服务管理(ITIL流程)、网络技术(OSI模型、TCP/IP)、信息安全(CIA三要素、加密技术)、软件工程(生命周期、测试类型)、面向对象分析与设计(UML图)、新一代信息技术(云计算、大数据、物联网)。 案例分析:聚焦项目管理十大知识领域,重点包括: 整体管理(项目章程、变更控制流程) 范围管理(WBS分解、需求跟踪矩阵) 进度管理

最爱で毛毛熊的博客 1991

安卓设计模式应用总结

####1.建造者模式建造者模式顾名思义,类似一个大楼都是按照一砖一瓦建造完成, 他通常结合链式调用一起使用该模式Android 比较热门的第三方框架均有使用举例:Rxjava, Retrofit, Okhttp, Geendao, 等等#####2.观察者模式观察者模式是一种行为模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

weixin_38504171的博客 1557

S32K3xx系列DMA驱动实战:EB配置与Mcal接口应用全解析(含Adc硬件触发示例)

本文深入解析S32K3xx系列MCU的DMA驱动开发,涵盖EB工具配置与Mcal接口应用,特别包含ADC硬件触发示例。通过详细架构分析、实战配置步骤和工业级应用案例,帮助开发者掌握AUTOSAR环境下DMA高效数据传输技术,提升汽车电子和工业控制系统的性能。

weixin_29162439的博客 466

安卓设计模式理解

前言 关于安卓的设计模式这个老生常谈的话题,多余的话就不多赘述了。文章内容仅限于我个人对设计模式的理解,便于记录和复盘。 说明 主流的3中设计模式已在下文中列出,现针对设计模式的 MV 先做说明,再对各个设计模式的层级叙述。 M–>Model(模型层,以下简称M层) 即代码中各个bean或者model这种对象类。通常我们在和后台接口数据交互的时候都要书写一个对应的数据模型,通过json解析后用于装填数据方便我们存取做数据的操作。 V–>View(视图层,以下简称V层) 即我们绘制的xml布局

heromrwang的博客 375

1.30 Cubemx_STM32H743 SD_Card纳入文件管理系统

Cubemx_STM32H743 SD_Card纳入文件管理系统1、简介2、CubeMX配置 1、简介 和前面文章原理其实一样的。 1.29 Cubemx_STM32F429\H743 nandflash、spifalsh纳入文件管理系统 现在一并将SD卡、NandFlash、SPIFlash一并作为文件管理。 下面直接介绍SDcard,其他参考前面文章。 2、CubeMX配置 ...

oDuanYanGuHong的博客 1080

YOLOv11超详细教程:Windows+Linux双环境搭建,新手也能秒上手

新建数据集目录结构:custom_data/│ ├── train/ # 训练图片│ └── val/ # 验证图片│ ├── train/ # 训练标签(YOLO格式)│ └── val/ # 验证标签└── custom_data.yaml # 配置文件编写nc: 1 # 类别数names: ['defect'] # 类别名开始训练:# Windows# Linux安装Python3.8~3.11,配置虚拟环境;

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 775

安卓开发之设计模式

这次来学习一下安卓开发中几种常见的设计模式,主要参考AndroidCot。 安卓开发中的设计模式大致上可分为如下几类: 所谓设计模式其实更像是在编写代码时的经验总结,使用这些模式规范能让我们的程序更健壮稳定、容易扩展。此外在编写面向对象程序时,我们也需要遵循以下6个原则: 原则 描述 单一职责原则 一个类只负责一个功能领域中的相应职责 开闭原则 对象应该对于扩展是开放的,但是对于修改是封闭的 里氏替换原则 所有引用基类的地方必须能透明地使用其子类的对象 依赖倒置原则 主要是实现

iris的博客 1229

【LAMMPS学习】四、运行 LAMMPS(2)命令行选项

本部分解释了在安装可执行文件或下载源代码并构建可执行文件后如何运行 LAMMPS。命令文档页面描述了输入脚本的结构以及它们可以包含的命令。

荷塘阅色 5244

Android开发 安卓中常用设计模式总结

安卓开发当中用到了各种各样的java设计模式,在此对其做以总结,一方面这是面试常考问题;另一方面,通过不断总结,也可以增强这方面的意识,知其然并知其所以然,方便日后灵活运用。     1,适配器模式      ListView、GridView、RecycleView等。     不同的数据提供者使用同一个适配器来向同一个客户提供服务。     2,建造者模式     AlertDial

到此一游 909

华为OD新系统机试真题-勇攀数字高峰(Java/Py/C/C++/Js/Go)

新系统 华为OD机试新系统【勇登数字高峰】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD新系统机试真题【勇登数字高峰】

qq_45776114的博客 1551

【读代码】深入解析Ragas:RAG应用效果评估最好的工具

Ragas是由Exploding Gradients团队开发的专业LLM应用评估框架,通过自动化测试和量化指标帮助开发者构建可靠的AI系统。# 典型架构模块 ├── metrics # 50+评估指标实现 ├── testset # 测试集生成系统 ├── embeddings # 多模态嵌入支持 ├── integrations # 主流框架集成 ├── optimizers # 遗传算法优化器 └── experimental # 前沿功能实验区。

kakaZhui的博客 852

Android中常用的设计模式

一:参考文档先介绍参考文档(或许我们更容易明白):另记录本人可参考 QQ15 MobileSafe 两个Demo有哪些在实际 Android 项目中用到的设计模式?Android开发中常见的设计模式Android中常见的设计模式Android设计模式之23种设计模式一览Android中常用设计模式二:然后总结一下其总结内容多根据参考文献文档而来,还请了解文档内容(一)什么是设计模式1. 基本定义:...

豆子的博客 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

安卓设计模式之MVC

最近一直在想怎么去优化一下现有的项目的代码和框架,项目中代码的臃肿和繁多在修改需求的时候带来了非常大的不方便,在大的项目工程中,一个好的框架,好的设计模式,能减少很大的工作量,所以最近一直在深入的学习MVC和MVP设计模式,这一篇对对于MVC的介绍非常的简单明了,想学习MVC设计模式的可以看看,欢迎有心得的相互交流,相互学习。 原文地址:http://www.2cto.com/kf/201506

Mr_Leixiansheng的博客 789

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

android设计模式原则,腾讯安卓面试

当大三春招没有办法提前去实习转正的时候,大三秋招其实到了关键的时候。一般在我们学校学计算的,基本大三秋招确定了 offer,大四去实习,这个是大部分人选择的规划。所以在yunOS实习之后,从杭州飞回广州,回来的时候是9月5号,进入秋招时段。

2401_83642079的博客 756

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

安卓开发用到的设计模式(1)创建型模式

本文介绍了在Android开发中常用的创建型设计模式及其应用场景。单例模式用于确保类只有一个实例,如系统服务和数据管理器;工厂模式通过隐藏创建逻辑来简化对象创建,如Fragment和IntentService的实例化;抽象工厂模式用于创建一系列相关对象,如主题系统和数据访问层;建造者模式通过分离构建过程与表示来创建复杂对象,如Dialog和Retrofit的配置;原型模式通过复制原型实例来创建新对象,如Intent的克隆和配置对象的复制。

分享Android应用和系统开发、音视频编码、性能优化相关知识 1405

最快的了解安卓中常用的设计模式

让在安卓中常用的设计模式通俗易通!

DoubleC的博客 1149

安卓开发用到的设计模式(2)结构型模式

本文介绍了安卓开发中常用的五种结构型设计模式:适配器模式(用于RecyclerView和网络请求适配)、装饰器模式(扩展Context功能与View装饰)、代理模式(管理图片加载和权限检查)、桥接模式(实现主题切换和数据存储分离)以及组合模式(构建View树结构和菜单层级)。这些模式通过解耦接口与实现、复用对象结构等方式,有效提升了代码的可维护性和扩展性,是安卓开发中的核心架构思想。

分享Android应用和系统开发、音视频编码、性能优化相关知识 1213

安卓设计模式的实现

http://blog.youkuaiyun.com/happy_horse/article/details/50908439 点击打开链接 安卓设计模式实现

hbuwanglei的博客 317

dashboard android,安卓仪表盘dashboard设计模式

安卓仪表盘dashboard设计模式像软件设计模式,UI设计模式也是针对重复出现的问题提出了一个通用的解决方案,模式的出现是作为一种天然的产品设计过程,对于每个模式都有标题 例子问题建议。实际就是最佳实践。五种设计模式:DashboardAction BarSearch BarQuick ActionsCompanion WidgetDashboard:一个应用程...

weixin_29850921的博客 312

Android 23种设计模式

转自:Android 23种设计模式 - 简书 Android 23种设计模式 1、Android 单例模式 2、Android Builder模式 3、Android 原形模式(深浅拷贝) 4、Android 工厂模式 5、Android 策略模式 6、Android 状态模式 7、Android 责任链模式 8、Android 命令模式 9、Android 观察者模式 10、Android 备忘录模式 11、Android 迭代器模式 12、Android 模板方法模式 13、Android 访问者

Gabriel的专栏 4486

Android 设计模式

因此,大多数人已经从传统的模型视图控制器(MVC)模式转向模型视图演示者(MVP)或模型视图视图模型(MVVM)模式。它负责公开方法、命令和其他属性,这些属性有助于维护视图的状态,并作为视图上的操作结果操纵模型,以触发视图本身的事件。视图有对视图模型的引用,但视图模型对视图没有任何了解。视图和视图模型之间有多对一的关系,意味着多个视图可以映射到一个视图模型。演示者通过视图接收用户的输入,然后通过模型处理用户数据,并将结果返回视图。视图和视图模型之间的双向数据绑定确保视图模型中的模型和属性与视图同步。

m0_57989954的博客 1065

安卓开发用到的设计模式(3)行为型模式

1. 命令模式(Command Pattern) 2. 策略模式(Strategy Pattern) 3. 观察者模式(Observer Pattern) 4. 模板方法模式(Template Method Pattern) 5. 责任链模式(Chain of Responsibility Pattern) 6. 状态模式(State Pattern) 7. 访问者模式(Visitor Pattern) 8. 中介者模式(Mediator Pattern) 9. 迭代器模式(Iterator Pattern

分享Android应用和系统开发、音视频编码、性能优化相关知识 1318

Android之设计模式总结篇

Android面试之设计模式

是非的Android学习之路 806

Android 常用设计模式和实例

设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

Android 领域开发程序员,希望通过写博客的方式不断的总结提升自己,大家共同进步哦! 2114

安卓开发设计模式(三)——行为型设计模式

行为型设计模式专注于对象间的交互逻辑和职责分配,通过定义对象间的通信方式、行为分配规则,实现行为的复用、解耦与灵活扩展。核心是解决“对象如何协作完成任务”的问题,不改变对象的内部结构,而是优化对象间的协作关系,让系统更具灵活性和可维护性。

. 1358
上一篇: Android Socket Transference R&D
下一篇: Java常用基础技术
JavaLearner12
博客等级 码龄15年 2粉丝 8原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值