上一节讲了面向对象程序设计的6个原则,这一节我们开始讲设计模式中的单例模式。单例模式顾名思义就是一个实例,就是从头到尾就只会同时存在一个实例。
单例模式适用于一个管理者的角色,比如下载任务管理,用户信息管理。他在第一次调用时创建,然后伴随整个应用的生命周期,类中的成员变量和成员方法就可以提供调用。
如以下用户信息管理类
/**
* 用户登录信息管理模块
* @author LZC
*/
public class UserManager {
private static UserManager mInst = null;
private static Object mLock = new Object();
private boolean mHasLogined = false;
private boolean mIsLogining = false;
private String mUserId = "";
public String mToken = "";//登录凭证
public String mNickName = "";
public String mUserIcon = "";//用户头像
public String mPhoneNum;//手机号
public String mSex;//性别“0”女,“1”代表男
public long mBirth;//生日
public String mEmail;//邮箱
public String mQQ;//QQ
/**
*
* 监听
*
*/
//登录
public interface IOnLogin{
void onLogining();
void onLogined();
void onLoginedFailed();
}
//登出
public interface IOnLoginOut{
void onLoginOut();
}
//登录过期
public interface IOnLoginInvalid{
void onLoginInvalid();
}
public interface IOnUserInfoChange{
void onIconChange(String userIcon);
void onGoldChange(int goldCount);
void onNickNameChange(String nickName);
}
private List<IOnLogin> mLoginListeners = new ArrayList<IOnLogin>();
private List<IOnLoginOut> mOnLoginOuts = new ArrayList<IOnLoginOut>();
private List<IOnUserInfoChange> mOnUserInfoChanges = new ArrayList<IOnUserInfoChange>();
private List<IOnLoginInvalid> mOnLoginInvalids = new ArrayList<IOnLoginInvalid>();
private UserManager(){
}
public static UserManager getInst( ){
if(mInst == null){
synchronized(mLock){
if(mInst == null){
mInst = new UserManager();
}
}
}
return mInst;
}
//添加登录监听
public void addLoginListener(IOnLogin listener){
if(mLoginListeners != null && !mLoginListeners.contains(listener)){
mLoginListeners.add(listener);
}
}
//移除登录监听
public void removeLoginListener(IOnLogin listener){
if(listener != null && mLoginListeners.contains(listener))
mLoginListeners.remove(listener);
}
//添加登出监听
public void addLoginOutListener(IOnLoginOut onLoginOut){
if(mOnLoginOuts != null && !mOnLoginOuts.contains(onLoginOut)){
mOnLoginOuts.add(onLoginOut);
}
}
//移除登出监听
public void removeLoginOutListener(IOnLoginOut onLoginOut){
if(onLoginOut != null && mOnLoginOuts.contains(onLoginOut)){
mOnLoginOuts.remove(onLoginOut);
}
}
//添加用户信息和变化监听
public void addUserInfoListener(IOnUserInfoChange onUserInfoChange){
if(onUserInfoChange != null && !mOnUserInfoChanges.contains(onUserInfoChange)){
mOnUserInfoChanges.add(onUserInfoChange);
}
}
//移除用户信息变化监听
public void removeUserInfoListener(IOnUserInfoChange onUserInfoChange){
if(onUserInfoChange != null && mOnUserInfoChanges.contains(onUserInfoChange)){
mOnUserInfoChanges.remove(onUserInfoChange);
}
}
//添加登录失效监听
public void addLoginInvalidListener(IOnLoginInvalid onLoginInvalid){
if(onLoginInvalid != null && !mOnLoginInvalids.contains(onLoginInvalid)){
mOnLoginInvalids.add(onLoginInvalid);
}
}
//移除登录失效监听
public void removeLoginInvalidListener(IOnLoginInvalid onLoginInvalid){
if(onLoginInvalid != null && mOnLoginInvalids.contains(onLoginInvalid)){
mOnLoginInvalids.remove(onLoginInvalid);
}
}
/**
*
* 设置数据
*/
//注销
public void logout(Context context){
HttpClientInst.removeCookie();
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
mHasLogined = false;
mIsLogining = false;
mUserGold = 0;
mUserId = "";
mNickName = "";
mUserIcon = "";
mToken = "";
mPhoneNum = "";//手机号
mSex = "0";//性别“0”女,“1”代表男
mBirth = 0;//生日
mEmail = "";//邮箱
mQQ = "";//QQ
mIsSign = 0;
UserManager.getInst().updateUserIcon(mUserIcon);
preferencesWrapper.setStringValue(Constants.USER_NAME, "");
preferencesWrapper.setStringValue(Constants.USER_PWD, "");
preferencesWrapper.setStringValue(Constants.USER_LOGIN_TYPE, "");
preferencesWrapper.commit();
if(mOnLoginOuts != null){
for(int idx = 0; idx < mOnLoginOuts.size(); ++ idx){
mOnLoginOuts.get(idx).onLoginOut();
}
}
}
/**
* 此方法只有登录接口能调用,其他地方不能随便调用
* @param userBean
* @param hasLogined
*/
//登录后,设置用户信息
public void setUserInfo(UserInfoBean userBean, boolean hasLogined){
saveInfo(userBean);
if(hasLogined){
if(!mHasLogined){
mIsLogining = false;
mHasLogined = true;
if(mLoginListeners != null){
for(int idx = 0; idx < mLoginListeners.size(); ++ idx){
try {
mLoginListeners.get(idx).onLogined();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
//把用户信息保存到本地,只有这三个信息保存到本地,为没登录时登录做准备,其他的都要登录以后才能获得,所以只能放在全局变量里面
private void saveInfo( UserInfoBean userBean){
mUserId = userBean.userId;
mUserIcon = userBean.userIcon;
mToken = userBean.token;
mNickName = userBean.nickName;
mPhoneNum = userBean.phoneNum;//手机号
mSex = userBean.sex;//性别“0”女,“1”代表男
mBirth = userBean.birth;//生日
mEmail = userBean.email;//邮箱
mQQ = userBean.qq;//QQ
mIsSign = userBean.isSign;
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
preferencesWrapper.setStringValue(Constants.USER_NAME, userBean.userName);
preferencesWrapper.setStringValue(Constants.USER_PWD,userBean.password);
preferencesWrapper.setStringValue(Constants.USER_LOGIN_TYPE, userBean.loginType);
preferencesWrapper.commit();
}
//设置当前处于登陆中的状态
public void setLogining(){
mIsLogining = true;
if(mLoginListeners != null){
for(int idx = 0; idx < mLoginListeners.size(); ++ idx){
try {
mLoginListeners.get(idx).onLogining();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//设置登录失败
public void setLoginFailed() {
mIsLogining = false;
mHasLogined = false;
if(mLoginListeners != null){
for(int idx = 0; idx < mLoginListeners.size(); ++ idx){
try {
mLoginListeners.get(idx).onLoginedFailed();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void setLoginOutOfDate(){
mHasLogined = false;
}
/**
* 更改用户信息后更新用户数据
*/
//修改密码后调用
public void updateUserPassword(String password,Context context) {
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
preferencesWrapper.setStringValue(Constants.USER_PWD, password);
preferencesWrapper.commit();
}
//修改头像后调用
public void updateUserIcon(String userIcon){
mUserIcon = userIcon;
for(int i = 0; i < mOnUserInfoChanges.size(); i ++){
mOnUserInfoChanges.get(i).onIconChange(mUserIcon);
}
}
//修改昵称后调用
public void updateNickName(String nickName){
mNickName = nickName;
for(int i = 0; i < mOnUserInfoChanges.size(); i ++){
mOnUserInfoChanges.get(i).onNickNameChange(mNickName);
}
}
/***
* 获取数据
*/
//判断当前是否是正在登陆中的状态
public boolean isLogining(){
return mIsLogining;
}
public boolean isLogined(){
return mHasLogined;
}
public ProtocolLogin createLoginProtocol(Context context, IProtocolListener listener){
return new ProtocolLogin(context,ProtocolLogin.TYPE_AUTO, getLoginType(), getUserName(), getPassword(), listener);
}
public String getLoginType() {
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
return preferencesWrapper.getStringValue(Constants.USER_LOGIN_TYPE, "");
}
//获取用户名
public String getUserName(){
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
return preferencesWrapper.getStringValue(Constants.USER_NAME, "");
}
//获取密码
public String getPassword(){
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
return preferencesWrapper.getStringValue(Constants.USER_PWD, "");
}
//是否可以自动登录
public boolean canAutoLogin(){
PreferenceWrapper preferencesWrapper = new PreferenceWrapper();
String username = preferencesWrapper.getStringValue(Constants.USER_NAME, "");
String password = preferencesWrapper.getStringValue(Constants.USER_PWD, "");
return !(TextUtils.isEmpty(username) || TextUtils.isEmpty(password));
}
//用户id
public String getUserId(){
return mUserId;
}
//用户登录令牌
public String getToken(){
return mToken;
}
//用户图标
public String getUserIcon(){
return mUserIcon;
}
//用户昵称
public String getNickName(){
return mNickName;
}
public String getmPhoneNum() {
return mPhoneNum;
}
public String getmSex() {
return mSex;
}
public long getmBirth() {
return mBirth;
}
public String getmEmail() {
return mEmail;
}
public String getmQQ() {
return mQQ;
}
}
我们在用户信息发生变更时首先调用UserManager.getInst()初始化UserManager类,
private static UserManager mInst = null;
public static UserManager getInst( ){
if(mInst == null){
synchronized(mLock){
if(mInst == null){
mInst = new UserManager();
}
}
}
return mInst;
}
将UserManager的实例存储载mInst 的静态变量中,以提供全局访问。
如果是修改头像,则
public void updateUserIcon(String userIcon){
mUserIcon = userIcon;
for(int i = 0; i < mOnUserInfoChanges.size(); i ++){
mOnUserInfoChanges.get(i).onIconChange(mUserIcon);
}
}
将新的头像存储在这里,并通知OnUserInfoChanges接口,头像更新了。这样不仅可以全局管理用户信息,而且和接口配合使用,可以通知所有注册了OnUserInfoChanges接口的界面可以刷新数据了。这就是单利模式的用处。