• Standup Timer的简单工厂Factory和单件模式


    前言

      学习android一段时间了,为了进一步了解android的应用是如何设计开发的,决定详细研究几个开源的android应用。从一些开源应用中吸收点东西,一边进行量的积累,一边探索android的学习研究方向。这里我首先选择了jwood的 Standup Timer 项目。
      在Standup Timer的 数据访问层net.johnpwood.android.standuptimer.dao使用到了单件模式,我们首先来看一下net.johnpwood.android.standuptimer.dao的项目结构,理解各个类的职责,然后再详细了解其中的设计。

    DAO的包的结构

      
      DAO在Standup Timer中充当数据访问层的职责,数据库采用的是SQLite。我们来逐个了解一下上图中各类的职责,他们是负责干什么的!

    CannoUpdateMeetingException.java

      它继承自RuntimeException类,负责抛出对应的异常。注:private static final long serialVersionUID = 1L;用来表明类序列化时的不同版本间的兼容性,1L为默认值。DuplicateTeamException.java和InvalidTeamNameException.java相同。

    DAOFactory.java

      这是有所改变的工厂类(与原本的简单工厂模式不太一样,最大的区别在于多态的使用上),负责生产MeetingDAO 、TeamDAO类。

    DAOHelper.java

      继承自SQLiteOpenHelper,并且实现了DatabaseConstants接口,负责在第一调用时生成对应表和表字段,以及更新数据库。

    DatebaseConstants.java

      一个包含数据库名称和版本常量的接口,由DAOHelper实现。将数据库名称和版本分离处理,方便日后的版本升级甚至数据库名变更。将数据库名和版本的管理从DAOHelper中分离处理,降低了耦合度,使DAOHelper职责更单一,符合单一职责原则(其实我很难说明将这两个常量放置于接口当中是否妥当)。

    MeetingDAO.java

      继承自DAOHelper.java负责会议表的具体数据访问业务。因为DAOHelper.java实现了DatebaseConstants接口,所有在MeetingDAO的构造函数当中可以直接调用DATABASE_NAME和DATABASE_VERSION。如果getWritableDatabase()是第一次调用,系统将自动创建数据库和数据库表字段。
    代码
    public MeetingDAO(Context ctx) {
    super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public Meeting save(Meeting meeting) {
    if (meeting.getId() ==null) {
    SQLiteDatabase db
    = getWritableDatabase();
    return createNewMeeting(db, meeting);
    }
    else {
    String msg
    ="Attempting to update an existing meeting. Meeting entries cannot be updated.";
    Logger.w(msg);
    thrownew CannotUpdateMeetingException(msg);
    }
    }
    TeamDAO.java与MeetingDAO的基本一样。
     

    DAOFactroy

      我们先来看看在Model对DAO的调用代码:
    代码
    privatestatic DAOFactory daoFactory = DAOFactory.getInstance();

    public Meeting save(Context context) {
    MeetingDAO dao
    =null;
    Meeting meeting
    =null;
    try {
    dao
    = daoFactory.getMeetingDAO(context);
    meeting
    = dao.save(this);
    }
    catch (Exception e) {
    Logger.e(e.getMessage());
    }
    finally {
    dao.close();
    }

    return meeting;
    }
    在Model 中 DAOFactory 的实例是由DaoFactory.getMeetingDAO(Context) 方法返回的,而对应的数据库访问类则由 daoFcatroy.getXXXXDAO(Context)方法返回。如果你看过一些有关设计模式的文章就很容易发现,这是单件模式。
      下面来分析一下DAOFactory的代码:
    代码
    publicclass DAOFactory {
    privatestatic DAOFactory instance =null;
    publicstatic DAOFactory getInstance() {
    if (instance ==null) {
    instance
    =new DAOFactory();
    }
    return instance;
    }

    private DAOFactory() {
    }
    }
    private DAOFactroy(){} 构造函数私有表明 DAOFactory 无法通过new关键字来实例化。要实例化只能通过静态的方法 getInstance()。在getInstance()方法中首先判断句柄instance是否为null,为空表示DAOFactory的实例尚未创建,然后调用 new DAOFactory() 创建实例(注意!因为是在 DAOFactory内部,所以可以访问private DAOFactory()成员),如果不为null则直接返回已创建的DAOFactory实例。这便是简单的单件模式设计方法(这里并没有考虑到多线程并发的问题,实际上就android的Standup Timer项目本身而言也不存在多线程的并发问题)。单件模式是一种比较简单的设计模式,比较容易理解,大家可以网上搜索一下,有很多相关的文章。
      我们再来看看 MeetDAO  和 TeamDAO的相关代码;
    代码
    privateboolean cacheDAOInstances =false;
    private TeamDAO cachedTeamDAO =null;
    private MeetingDAO cachedMeetingDAO =null;



    public TeamDAO getTeamDAO(Context context) {
    if (cacheDAOInstances) {
    if (cachedTeamDAO ==null) {
    cachedTeamDAO
    =new TeamDAO(getProperDAOContext(context));
    }
    return cachedTeamDAO;
    }
    else {
    returnnew TeamDAO(getProperDAOContext(context));
    }
    }

    public MeetingDAO getMeetingDAO(Context context) {
    if (cacheDAOInstances) {
    if (cachedMeetingDAO ==null) {
    cachedMeetingDAO
    =new MeetingDAO(getProperDAOContext(context));
    }
    return cachedMeetingDAO;
    }
    else {
    returnnew MeetingDAO(getProperDAOContext(context));
    }
    }
     private Context getProperDAOContext(Context context) {  
         if (globalContext != null) {            
          return globalContext;       
       } else {          
          return context;     
             } 
       }
    cacheDAOInstances是布尔值,相当于一个开关,用以判定是否需要对DAO类使用缓存(单件模式)。如果为True则进入单件模式的构建,如果为False 着直接返回一个新的DAO实例。这里通过getMeetingDAO 和getTeamDAO两个方法返回对应的DAO实例。另外getProperDAOContext()方法是负责解决DAOFactory 内的私有变量private Context globalContext  和方法的参数 context 间需要调用哪一个上下文context的冲突。其实我们也可以改写DAOFactory的生成方式:
    代码
    privatestatic DAOFactory instance =null;

    private Context globalContext =null;

    publicstatic DAOFactory getInstance(Context context) {
    if (instance ==null) {
    instance
    =new DAOFactory(context);


    }
    return instance;
    }

    private DAOFactory() {
    globalContext
    =context;
    }
    这样在其他的方法中就可以省去 context参数。
  • 相关阅读:
    绝对定位position: absolute;
    加号选择器(ul>li + li)
    position: absolute;绝对定位水平居中问题
    nth-child 和 nth-of-type 的区别
    Scrapy Shell 待续。。。
    TypeError: write() argument must be str, not bytes
    ModuleNotFoundError :No module named 'win32api'
    scrapy 简介
    3月27下午(补交)
    软件工程作业二:需求分析
  • 原文地址:https://www.cnblogs.com/keyindex/p/1825806.html
Copyright © 2020-2023  润新知