您的位置:首页 > 移动开发 > Android开发

设计模式实例学习-单例模式(Android中的使用场景)

2015-11-17 10:37 585 查看

设计模式实例学习-单例模式

原创博客,转载请注明出处:

http://blog.csdn.net/u011035622/article/details/49884327

定义

单例模式,故名思议,是指在一个类中通过设置静态使得其仅创造一个唯一的实例。这样设置的目的是满足开发者的希望——这个类只需要被实例化创建一次,同时因为其为静态的缘故,加载的速度也应该快于正常实例化一个类的速度(理论上)。


代码分析

  在Android开发中,当我们需要创建一个唯一的Fragment的时候常常会用到这样的模式,没有代码的学习是虚无的,接下来亮代码学习:

public class SelectFrame extends Fragment {

private final static String selectFrameKey = "SFKey";
private static SelectFrame mSelectFrame;
private ArrayList<String> frameList;
public static SelectFrame getInstance(ArrayList<String> frameList){
if (mSelectFrame == null) {
mSelectFrame = new SelectFrame();
}
Bundle bundle = new Bundle();
bundle.putStringArrayList(selectFrameKey, frameList);
mSelectFrame.setArguments(bundle);
return mSelectFrame;
}
}


  这是我在一个Fragment类里面定义的其中一部分,首先必须要定义一个自身的静态mSelectFrame。然后通过一个静态方法getInstance()来实例化这个mSelectFrame,很明显,这里通过判断其是否为空的方式,使得每一次我们使用getInstance的时候都返回的是同一个对象mSelectFrame。

  getInstance方法中有时我们也会放入一些我们需要传递的参数,比如我这个方法中放入了一个List对象,然后直接在里面用Bundle装载这个List对象,原本我们可能是在外部来做这些操作的,然而现在却直接通过这个方法将数据传入的操作集成到了这个Fragment中,即减少了外部Activity的逻辑代码,也使得这个Fragment在复用的时候操作更方便。(再通过setArguments的方法保存数据)。

  

  接下来看我们的onCreateView方法:

public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.select_frame_fragment, container, false);
Bundle bundle = mSelectFrame.getArguments();
frameList = bundle.getStringArrayList(selectFrameKey);
return view;
}


  这里我们就将从前面getInstance中setArguments保存下来的数据通过Fragment的getArguments方法重新将数据读取出来。这样就完成了我们的目的。

  接下来就是在Activity中创建我们这个Fragment对象了:

selectFrameFrag = SelectFrame.getInstance(nameFrameThumbnail);
fm.beginTransaction().add(R.id.fragment_frame_container, selectFrameFrag).commit();


(fm是FragmentManager)

  这样就OK了。

单例模式分类

  单例模式有两种创建方式,分别为饿汉式和懒汉式。

饿汉式

饿汉式,故名思议,很饿,在一开始就直接创建了这个对象。刚刚上面那个例子就是懒汉式的。

懒汉式

  懒汉式,顾名思义,很懒,只有在你要调用它的时候,通过自己写的方法里面来对他实例化。

代码区别

  也许这么说会有一点不明白,然后其实只要看代码的这个地方:

private static SelectFrame mSelectFrame;


  上面这个代码,这里一开始定义自身的静态时,没有实例化它,那么就是个懒汉.然后只有在我调用getInstance方法的时候,才在里面对他进行实例化(new SelectFrame()).

  然后我们再看看饿汉:

private static SelectFrame mSelectFrame = new SelectFrame();


在定义的时候就已经实例化了.

单例模式线程安全问题

  单例模式毕竟就是像上面讲的这么简单。但需要注意的是,单例模式实例化对象时,饿汉式是线程安全的,而懒汉式是线程不安全的,我们一般会再懒汉式的getInstance方法中通过synchronized上锁。类似于这样:

if (mSelectFrame == null) {
synchronized (SelectFrame.class) {
if (mSelectFrame == null) {
mSelectFrame = new SelectFrame();
}
}
}


  有人说为什么要用两个if(XX==null),这里是为了提高效率,只有一个也是可以的,但效率上大大减低,因为不是每一次调用的时候我们要判断他是否同步,应该是如果判断当前为null的话,我们就直接不让他进入了,不需要判断是否同步。只有满足第一个条件的时候,我们才需要用锁来判断它是否线程安全。(这里的意思也是说明if一条语句的判断速度当然比synchronized (SelectFrame.class)快。。)

  另外,在我们使用单例模式的时候,有些人会去私有化这个类的构造方法,使得这个类只能通过自己写的getInstance()来创建。类似于这样:

private SelectFrame() {
// 并不需要做什么,只需要将这个外面的public改成private就好了=。=
}


  这么一来外部就只能按我要求的方法来创建这个对象了。

  在这里也基本将单例模式的使用基本讲完了,接下来还会继续写其他的设计模式的使用,如果有涉及到Android上的都会尽力用Android上的例子来讲,加深印象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息