java设计模式

1.单例模式

  • 作用
    保证在java应用程序中,一个类Class只有一个实例存在。
  • 优点
    1.由于单例模式在内存中只有一个实例,减少了内存开销
    2.单例模式可以避免对资源的多重占用
    3.单例模式可以在系统设置全局的访问点,优化和共享资源访问。
  • 使用情况
    1.建立目录,数据库连接的单线程操作。
    2.某个需要被频繁访问的实例对象。
    第一种形式
 public class Singleton {

    /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
    private static Singleton instance = null;

    /* 私有构造方法,防止被实例化 */
    private Singleton() {
    }

    /* 懒汉式:第一次调用时初始Singleton,以后就不用再生成了
    静态方法,创建实例 */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

但是这种方法存在一个问题,当对数据库进行频繁的读写操作时,会发生严重的不同步问题。
解决方式
给getInstance方法加个锁呗!在这里我们可以使用synchronized关键字可以同步方法和同步代码块,所以:

 public static synchronized Singleton getInstance() {  

           if (instance == null) {  
                   instance = new Singleton();  
               }  
             return instance;  
 } 

或者

public static Singleton getInstance() {  

     synchronized (Singleton.class) {  
         if (instance == null) {  
             instance = new Singleton();  
         }  
     }  
     return instance;  
 } 

建议使用第二种方式,对代码段加锁。这样可以减少线程阻塞时间。

2.Factory(工厂模式)

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类,对同一个接口的管理类进行管理和实例化创建。
假设需求如下:
动物Animal,它有行为move()。有两个实现类cat和dog。为了统一管理和创建我们设计一个工厂模式。   同时两个子类有各自的行为,Cat有eatFish(),Dog有eatBone().

Animal接口

interface animal {
    void move();
}

Cat类:

public class Cat implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是只肥猫,不爱动");
    }
    public void eatFish() {  
        System.out.println("爱吃鱼");
    } 
}

Dog类:

public class Dog implements Animal{

    @Override
    public void move() {
        // TODO Auto-generated method stub
        System.out.println("我是狗,跑的快");
    }
    public void eatBone() {  
        System.out.println("爱吃骨头");
    } 
}

工厂类

public class Factory {

    //静态工厂方法
    //多处调用,不需要实例工厂类 
     public static Cat produceCat() {  
            return new Cat();  
        } 
     public static Dog produceDog() {  
            return new Dog();  
        }
//当然也可以一个方法,通过传入参数,switch实现
}

使用:

Animal cat = Factory.produceCat();
cat.move();
//-----------------------------
Dog dog = Factory.produceDog();
dog.move();
dog.eatBone();
  • 作用
    工厂模式在业界运用十分广泛,如果都用new来生成对象,随着项目的扩展,animal还可以生出许多其他儿子来,当然儿子还有儿子,同时也避免不了对以前代码的修改(比如加入后来生出儿子的实例),怎么管理,想着就是一团糟。

Animal cat = Factory.produceCat();
 这里实例化了Animal但不涉及到Animal的具体子类(减少了它们之间的偶合联系性),达到封装效果,也就减少错误修改的机会。

Java面向对象的原则,封装(Encapsulation)和分派(Delegation)告诉我们:具体事情做得越多,越容易范错误,

一般来说,这样的普通工厂就可以满足基本需求。但是我们如果要新增一个Animal的实现类panda,那么必然要在工厂类里新增了一个生产panda的方法。就违背了 闭包的设计原则(对扩展要开放对修改要关闭) ,于是有了抽象工厂模式。

2.1Abstract Factory(抽象工厂)

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。   啥意思?就是把生产抽象成一个接口,每个实例类都对应一个工厂类(普通工厂只有一个工厂类),同时所有工厂类都继承这个生产接口。

生产接口Provider:

interface Provider {
    Animal produce(); 
}

每个产品都有自己的工厂类

public class CatFactory implements Provider{

    @Override
    public Animal produce() {
        // TODO Auto-generated method stub
        return new Cat();
    }
}

public class DogFactory implements Provider{

    @Override
    public Animal produce() {
        // TODO Auto-generated method stub
        return new Dog();
    }
}

产品生产

Provider provider = new CatFactory();
Animal cat =provider.produce();
cat.move();

现在我们要加入panda,直接新建一个pandaFactory就行了,这样我们系统就非常灵活,具备了动态扩展功能。

2.2android中的Factory

例如AsyncTack的抽象工厂的实现:

工厂的抽象:

59 public interface ThreadFactory {
//省略为备注
69    Thread newThread(Runnable r);
70 }

产品的抽象(new Runnable就是其实现类):

56   public interface Runnable {
//省略为备注
68    public abstract void run();
69 }

AsyncTask中工厂类的实现:

185    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
186        private final AtomicInteger mCount = new AtomicInteger(1);
187
188        public Thread newThread(Runnable r) {
189            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
190        }
191    };

3.适配器模式。

我们经常要遇到要将两个没有关系类组合类一起使用,第一个方案是修改两个类的接口。第二种方法就是我们要讲到的adapter。

模式中的角色
需要适配的类(Adaptee):需要适配的类
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
目标接口:客户所期待的接口,可以是具体抽象的类,也可以是接口。
// 需要适配的类

class Adaptee {  
    public void specificRequest() {  
        System.out.println("需要适配的类");  
    }  
}  
  
// 目标接口  
interface Target {  
    public void request();  
} 

实现方式

// 适配器类实现标准接口
class Adapter implements Target{
    // 直接关联被适配类
    private Adaptee adaptee;
    
    // 可以通过构造函数传入具体需要适配的被适配类对象
    public Adapter (Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    public void request() {
        // 这里是使用委托的方式完成特殊功能
        this.adaptee.specificRequest();
    }
}

// 测试类
public class Client {
    public static void main(String[] args) {
        // 需要先创建一个被适配类的对象作为参数
        Target adapter = new Adapter(new Adaptee());
        adapter.request();
    }
}

如果Target不是接口而是一个具体的类的情况,这里的Adapter直接继承Target就可以了。
如果Target和 Adaptee都是接口,并且都有实现类。 可以通过Adapter实现两个接口来完成适配。   还有一种叫PluggableAdapters,可以动态的获取几个adapters中一个。使用Reflection技术,可以动态的发现类中的Public方法。

优点
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。   将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码,更好的扩展性。
缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现。如果不是必要,不要使用适配器,而是直接对系统进行重构。

3.1Android的Adapter

android中的Adapter就有很多了,这个大家都经常用。   Adapter是AdapterView视图与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View。


BaseAdapter
BaseAdapter

BaseAdapter的部分源码:

30public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
31    private final DataSetObservable mDataSetObservable = new DataSetObservable();
32
33    public boolean hasStableIds() {
34        return false;
35    }
36    
37    public void registerDataSetObserver(DataSetObserver observer) {
38        mDataSetObservable.registerObserver(observer);
39    }
40
41    public void unregisterDataSetObserver(DataSetObserver observer) {
42        mDataSetObservable.unregisterObserver(observer);
43    }

4.责任链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不受客户影响的情况下动态的重新组织和分配责任。

编程中小体现:

if(a<10){
    ...
}
else if (a<20){
    ...
}
else if(a<30){
    ...
}
else{
    ...
}

程序必须依次扫描每个分支进行判断,找到对应的分支处理。

责任链模式的优点
可以降低系统的耦合度(请求者与处理者代码分离),简化对象的相互连接,同时增强给对象指派职责的灵活性,增加新的请求方式处理类也很方便;
责任链模式的缺点
不能保证请求一定被接收,且由于比较长的责任链,请求的处理可能涉及到多个对象,系统性能将受到一定的影响,而且在进行代码调试时不太方便。每次都是从链头开始,这也正是链表的缺点。

4.1Android中的责任链模式

1、dispatchTouchEvent作用:决定事件是否由onInterceptTouchEvent来拦截处理。
返回super.dispatchTouchEvent时,由onInterceptTouchEvent来决定事件的流向
返回false时,会继续分发事件,自己内部只处理了ACTION_DOWN
返回true时,不会继续分发事件,自己内部处理了所有事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP)

2、onInterceptTouchEvent作用:拦截事件,用来决定事件是否传向子View
返回true时,拦截后交给自己的onTouchEvent处理
返回false时,交给子View来处理

3、onTouchEvent作用:事件最终到达这个方法
返回true时,内部处理所有的事件,换句话说,后续事件将继续传递给该view的onTouchEvent()处理
返回false时,事件会向上传递,由onToucEvent来接受,如果最上面View中的onTouchEvent也返回false的话,那么事件就会消失

1.如果ViewGroup找到了能够处理该事件的View,则直接交给子View处理,自己的onTouchEvent不会被触发;
2.一个点击事件产生后,它的传递过程如下:
Activity->Window->View。顶级View接收到事件之后,就会按相应规则去分发事件。如果一个View的onTouchEvent方法返回false,那么将会交给父容器的onTouchEvent方法进行处理,逐级往上,如果所有的View都不处理该事件,则交由Activity的onTouchEvent进行处理。 
3.如果某一个View开始处理事件,如果他不消耗ACTION_DOWN事件(也就是onTouchEvent返回false),则同一事件序列比如接下来进行ACTION_MOVE,则不会再交给该View处理。
4.可以通过复写onInterceptTouchEvent(ev)方法,拦截子View的事件(即return true),把事件交给自己处理,则会执行自己对应的onTouchEvent方法。
5.子View可以通过调用getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup对其MOVE或者UP事件进行拦截; 
6.ViewGroup默认不拦截任何事件。
7.诸如TextView、ImageView这些不作为容器的View,一旦接受到事件,就调用onTouchEvent方法,它们本身没有onInterceptTouchEvent方法。正常情况下,它们都会消耗事件(返回true),除非它们是不可点击的(clickable和longClickable都为false),那么就会交由父容器的onTouchEvent处理。 
8.点击事件分发过程如下 dispatchTouchEvent—->OnTouchListener的onTouch方法—->onTouchEvent–>OnClickListener的onClick方法。也就是说,我们平时调用的setOnClickListener,优先级是最低的,所以,onTouchEvent或OnTouchListener的onTouch方法如果返回true,则不响应onClick方法…

5.Observer(观察者模式)

有时被称作发布、订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。
将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的(依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者)。

观察者模组成
①抽象主题(Subject)

它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

②具体主题(ConcreteSubject)

将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

③抽象观察者(Observer)

为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

④具体观察者(ConcreteObserver)

实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

言语苍白,上代码:

//抽象观察者
public interface Observer
{
  public void update(String str);
    
}
//具体观察者
public class ConcreteObserver implements Observer{
    @Override
    public void update(String str) {
        // TODO Auto-generated method stub
        System.out.println(str);
    }
}
//抽象主题
public interface Subject
{
    public void addObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers(String str);
}
//具体主题
public class ConcreteSubject implements Subject{
    // 存放观察者
    private List<Observer> list = new ArrayList<Observer>();
    @Override
    public void addObserver(Observer observer) {
        // TODO Auto-generated method stub
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        // TODO Auto-generated method stub
        list.remove(observer);
    }

    @Override
    public void notifyObservers(String str) {
        // TODO Auto-generated method stub
        for(Observer observer:list){
            observer.update(str);
        }
    }
}

下面是测试类:

/**
 * @author fanrunqi
 */
public class Test {
     public static void main(String[] args) {
        //一个主题
         ConcreteSubject eatSubject = new ConcreteSubject();
         //两个观察者
         ConcreteObserver personOne = new ConcreteObserver();
         ConcreteObserver personTwo = new ConcreteObserver();
         //观察者订阅主题
         eatSubject.addObserver(personOne);
         eatSubject.addObserver(personTwo);
         
         //通知开饭了
         eatSubject.notifyObservers("开饭啦");
    }
}

“关于代码你有什么想说的?” “没有,都在代码里了” “(⊙o⊙)哦.....”

6.建造者模式

建造者模式:是将一个复杂的对象的构建与它的表示分离(同构建不同表示),使得同样的构建过程可以创建不同的表示。

一个人活到70岁以上,都会经历这样的几个阶段:婴儿,少年,青年,中年,老年。并且每个人在各个阶段肯定是不一样的,世界上不存在两个人在人生的这5个阶段的生活完全一样,但是活到70岁以上的人,都经历了这几个阶段是肯定的。实际上这是一个比较经典的建造者模式的例子了。

将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。

建造者通常有以下角色:
① Builder:一个抽象接口,用来规范产品对象的各个组成成分的建造。
② ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建,在建造过程完成后,提供产品的实例。
③ Director:指导者,调用具体建造者来创建复杂对象的各个部分,不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
④ Product:要创建的复杂对象。

与抽象工厂的区别:在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。

Product和产品的部分Part接口

 public interface Product { }
 public interface Part { }
Builder:

 public interface Builder { 
    void buildPartOne(); 
    void buildPartTwo(); 
  
    Product getProduct(); 
  } 
ConcreteBuilder:

//具体建造工具
  public class ConcreteBuilder implements Builder { 
    Part partOne, partTwo; 

    public void buildPartOne() {
      //具体构建代码
    }; 
    public void buildPartTwo() { 
      //具体构建代码
    }; 
     public Product getProduct() { 
      //返回最后组装的产品
    }; 
  }
Director :

 public class Director {
    private Builder builder; 
  
    public Director( Builder builder ) { 
      this.builder = builder; 
    } 
    public void construct() { 
      builder.buildPartOne();
      builder.buildPartTwo();
    } 
  } 

建造:

ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director(builder); 
//开始各部分建造 
director.construct(); 
Product product = builder.getResult();

优点

客户端不必知道产品内部组成的细节。

具体的建造者类之间是相互独立的,对系统的扩展非常有利。

由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响

适用场合:
创建一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,但是对象的内部组成构件面临着复杂的变化。

要创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。

6.1Android中的Builder

android中的Dialog就使用了Builder Pattern,下面来看看AlertDialog的部分源码。

371    public static class Builder {
372        private final AlertController.AlertParams P;
373        private int mTheme;

393        public Builder(Context context, int theme) {
394            P = new AlertController.AlertParams(new ContextThemeWrapper(
395                    context, resolveDialogTheme(context, theme)));
396            mTheme = theme;
397        }

AlertDialog的Builder 是一个静态内部类,没有定义Builder 的抽象接口。   对AlertDialog设置的属性会保存在Build类的成员变量P(AlertController.AlertParams)中。
Builder类中部分方法:

416        public Builder setTitle(int titleId) {
417            P.mTitle = P.mContext.getText(titleId);
418            return this;
419        }
452        public Builder setMessage(int messageId) {
453            P.mMessage = P.mContext.getText(messageId);
454            return this;
455        }
        
525        public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
526            P.mPositiveButtonText = text;
527            P.mPositiveButtonListener = listener;
528            return this;
529        }

而show()方法会返回一个结合上面设置的dialog实例

991        public AlertDialog show() {
992            AlertDialog dialog = create();
993            dialog.show();
994            return dialog;
995        }
996    }
997    
998}
972        public AlertDialog create() {
973            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
974            P.apply(dialog.mAlert);
975            dialog.setCancelable(P.mCancelable);
976            if (P.mCancelable) {
977                dialog.setCanceledOnTouchOutside(true);
978            }
979            dialog.setOnCancelListener(P.mOnCancelListener);
980            dialog.setOnDismissListener(P.mOnDismissListener);
981            if (P.mOnKeyListener != null) {
982                dialog.setOnKeyListener(P.mOnKeyListener);
983            }
984            return dialog;
985        }

简单建造:

new AlertDialog.Builder(context)
 .setTitle("标题") 
 .setMessage("消息框")
 .setPositiveButton("确定", null)
 .show();

7.备忘录模式

备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

备忘录模式所涉及的角色有三个:

① Originator(发起人): 负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。

② Memento(备忘录): 负责存储Originnator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento,备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。

③、 Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。

public class Originator {

    private String state;
    /**
     * 工厂方法,返回一个新的备忘录对象
     */
    public Memento createMemento(){
        return new Memento(state);
    }
    /**
     * 将发起人恢复到备忘录对象所记载的状态
     */
    public void restoreMemento(Memento memento){
        this.state = memento.getState();
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
        System.out.println("当前状态:" + this.state);
    }
    
}
public class Memento {
    
    private String state;
    
    public Memento(String state){
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
}
public class Caretaker {

    private Memento memento;
    /**
     * 备忘录的取值方法
     */
    public Memento retrieveMemento(){
        return this.memento;
    }
    /**
     * 备忘录的赋值方法
     */
    public void saveMemento(Memento memento){
        this.memento = memento;
    }
}

使用:

Originator o = new Originator();
Caretaker c = new Caretaker();
//改变负责人对象的状态
o.setState("On");
//创建备忘录对象,并将发起人对象的状态储存起来
 c.saveMemento(o.createMemento());
//修改发起人的状态
o.setState("Off");
//恢复发起人对象的状态
 o.restoreMemento(c.retrieveMemento());

不需要了解对象的内部结构的情况下备份对象的状态,方便以后恢复。

7.1Android中的Memento

Activity的onSaveInstanceState和onRestoreInstanceState就是通过Bundle(相当于备忘录对象)这种序列化的数据结构来存储Activity的状态,至于其中存储的数据结构,这两个方法不用关心。

1365    protected void onSaveInstanceState(Bundle outState) {
1366        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
1367        Parcelable p = mFragments.saveAllState();
1368        if (p != null) {
1369            outState.putParcelable(FRAGMENTS_TAG, p);
1370        }
1371        getApplication().dispatchActivitySaveInstanceState(this, outState);
1372    }
1019    protected void onRestoreInstanceState(Bundle savedInstanceState) {
1020        if (mWindow != null) {
1021            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
1022            if (windowState != null) {
1023                mWindow.restoreHierarchyState(windowState);
1024            }
1025        }
1026    }

8. Prototype(原型模式)

原型模式,能快速克隆出一个与已经存在对象类似的另外一个我们想要的新对象。   工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。

分为深拷贝和浅拷贝。深拷贝就是把对象里面的引用的对象也要拷贝一份新的对象,并将这个新的引用对象作为拷贝的对象引用(多读两遍)。

一般使用原型模式有个明显的特点,就是实现cloneable的clone()方法。

在Intent源码中:

4084    @Override
4085    public Object clone() {
4086        return new Intent(this);
4087    }

这里Intent通过实现Cloneable接口来实现原型拷贝。

9. Strategy(策略模式)      定义:有一系列的算法,将每个算法封装起来(每个算法可以封装到不同的类中),各个算法之间可以替换,策略模式让算法独立于使用它的客户而独立变化。

举例:   一个影碟机,你往里面插什么碟子,就能放出什么电影。   属性动画,设置不同的插值器对象,就可以得到不同的变化曲线。   返回值解析,传入什么样的解析器,就可以把二进制数据转换成什么格式的数据,比如String、Json、XML。

策略模式其实就是多态的一个淋漓精致的体现。

在android中不同Animation动画的实现,主要是依靠Interpolator的不同而实现的。

401     public void setInterpolator(Interpolator i) {
402         mInterpolator = i;
403     }

10. Template(模板模式)

定义:定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定的步骤。      实现流程已经确定,实现细节由子类完成。      生命周期对于我们都不陌生,它就是典型的Template模式,在具体流程确定的情况下,至于我们要复写生命周期那些方法,实现那些功能由继承activity的子类去具体实现。

关键在于必须有具体的执行流程,比如AsyncTask。

11.proxy(代理模式)

定义:为其他对象提供一种代理以控制对这个对象的访问。   代理: 在出发点到目的地之间有一道中间层。

应用:Android跨进程通信方式 ,建议去了解一下Binder机制。

12. Interpreter(解释器模式)

定义语言的文法,并且建立一个解释器来解释该语言中的句子。

比如Android中通过PackageManagerService来解析AndroidManifest.xml中定义的Activity、service等属性。

13. State(状态模式)

行为是由状态来决定的,不同状态下有不同行为。

注意:状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立可相互替换的。

体现:不同的状态执行不同的行为,当WIFI开启时,自动扫描周围的接入点,然后以列表的形式展示;当wifi关闭时则清空。

14. Command(命令模式)

我们有很多命令,把它们放在一个下拉菜单中,用户通过先选择菜单再选择具体命令,这就是Command模式。

本来用户(调用者)是直接调用这些命令的,在菜单上打开文档,就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了。      显然这样做的好处是符合封装的特性,降低耦合度,有利于代码的健壮性 可维护性 还有复用性。Command是将对行为进行封装的典型模式,Factory是将创建进行封装的模式。

android底层逻辑对事件的转发处理就用到了Command模式。

15. Iterator(迭代模式)

提供一种方法顺序访问一个容器对象中的各个元素,而不需要暴露该对象的内部表示。

应用:

在Java中的Iterator类。

Android中的 Cursor。

cursor.moveToFirst();

16. Composite(组合模式)

将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

Android中View的结构是树形结构,每个ViewGroup包含一系列的View,而ViewGroup本身又是View。这是Android中非常典型的组合模式。

17. Flyweight(共享模式/享元模式)

定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。

面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内部状态intrinsic和外部状态extrinsic之分。

说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以Flyweight模式中常出现Factory模式。Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个Flyweight pool(模式池)来存放内部状态的对象。

Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。应用场合很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中。

在Android线程通信中,每次获取Message时调Message.obtain()其实就是从消息池中取出可重复使用的消息,避免产生大量的Message对象。

对于设计模式没有必要去记忆,知道就好,说白了设计模式只是一种处理问题的方法,在遇到具体的问题时,可能会使用一些技巧,而这个技巧有可能是几个模式结合,都只是运用而已。

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

推荐阅读更多精彩内容