?
?
先来图:

?
这张图是查看单张照片的界面。
现在的问题是,如何设计和实现这张页面。
大家注意到,随着图片的改变,页面是不刷新的,也就是说你查看另外一张图片时,页面中的很多信息需要同步修改,如下图:

还有一块很重要的信息,那就是图片的评论,也需要随之改变。
我们的要求是,实现这个功能的代码需要清楚,模块化,容易维护,扩展容易。
现在我们的难题似乎是图片改变的同时,其他的信息用一种什么方式随之改变,我们这里定义了一个接口:
?
?
/**
* 改变照片的事件监听器
*/
var PhotoChangeListener = Class.create({
initialize:function(){},
/**
* 当改变照片时,该方法被调用
* @param newPhotoId 改变的新的照片id
* @param isNext boolean 是否是查看下一张图片
*/
handlePhotoChange:function(newPhotoId,isNext){
}
});
用js来定义接口实在是小题大作,不过,这样定义感觉上会更清楚明白一些。
这个监听器处理的代码是在handlePhotoChange里完成。
为此,我们还设计了一个所有照片的持有类,美其名曰:“封装”
/**
* 照片集合的持有类
* 当调用setCurrentPhoto时,会依次调用photoChangeListeners中的照片改变的事件监听器里的handlePhotoChange方法
*/
var PhotosHolder = Class.create({
/**
* @param photos 照片对象的列表
*/
initialize:function(photos){
},
getPhotoNumber:function(){
},
/**
* 得到某个photoId的photo对象
* 如果不存在该photoId的photo,则返回null
*/
getPhoto:function(photoId){
},
indexOfPhoto:function(photoId){
},
/**
* 增加一个照片改变的监听器
*/
addPhotoChangeListener:function(photoChangeListener){
},
/**
* 设置某照片为当前的照片
*/
setCurrentPhoto:function(photoId,isNext){
},
/**
* 得到下一张照片,如果没有下一张照片,返回null
*/
nextPhoto:function(){
},
/**
* 得到上一张照片,如果没有上一张照片,返回null
*/
previousPhoto:function(){
},
/**
* 得到当前页面上显示的照片
*/
getCurrentPhoto:function(){
},
/**
* 得到第一张图片
*/
getFirstPhoto:function(){
},
/**
* 得到最后一张图片
*/
getLastPhoto:function(){
},
/**
* 增加一个照片标记信息
* @param photoMentionInfo 标记信息对象
*/
addPhotoMention:function(photoMentionInfo){
},
/**
* 增加某张照片的一批标记信息
*/
addPhotoMentions:function(photoId,mentions){
},
/**
* 删除一个照片标记信息
*/
removePhotoMention:function(mentionInfoId){
},
/**
* 得到某照片的标记信息,如果不存在,则返回null
*/
getPhotoMentions:function(photoId){
}
});
?
?
?
这里给出了接口定义,具体的实现也不是很困难,我们重点注意这两个方 法:addPhotoChangeListener,setCurrentPhoto。方法addPhotoChangeListener用于将图片改变 的监听器注册到图片的持有者中,setCurrentPhoto方法用于客户端设置显示某一张图片,在setCurrentPhoto方法中,如果设置的 图片不是当前显示的图片,就会调用注册到该类的所有图片监听器的handlePhotoChange,剩下的工作就交给各个监听器处理了。
?
这里的设计思想是,解耦。我们可以将图片改变的动作和处理该图片改变的处理分开,往往处理逻辑需要很多,我们只需要增加一个PhotoChangeListener,然后注册到photosHolder就行了。
这里作为demo,给出照片信息显示的实现:
?
?
/**
* 照片信息的显示类
*/
var PhotoInfoObserver = Class.create(PhotoChangeListener,{
initialize:function($super,photosHolder){
$super();
this.createTime = $('createTime'); //上传时间
this.hits = $('hits'); //浏览次数
this.comments = $('comments'); //评论次数
if(!this.createTime||!this.hits||!this.comments) return;
this.photosHolder = photosHolder;
this.photosHolder.addPhotoChangeListener(this);
},
handlePhotoChange:function(newPhotoId){
this.createTime.update('上传于:'+this.photosHolder.getCurrentPhoto().createTimeStr);
this.hits.update('浏览('+this.photosHolder.getCurrentPhoto().hits+')');
this.comments.update('评论('+this.photosHolder.getCurrentPhoto().comments+')');
}
});
?
?
?
最终,我们将会实例化所有的处理类:
?
?
this.photosHolder = new PhotosHolder(photos); this.croperHandler = new CroperHandler(this.photosHolder); //照片圈人 this.carouselHandler = new CarouselHandler(this.photosHolder); //照片导航 this.photoDeleter = new PhotoDeleter(this.photosHolder); //删除照片的工具类 this.pageSetter = new PageSetter(this.photosHolder); //设置为封面的工具类 this.originalPhotoView = new OriginalPhotoView(this.photosHolder); //原图查看的工具类 this.descEditObserver = new DescEditObserver(this.loginUserId,this.photosHolder);//描述信息修改 this.photoInfoObserver = new PhotoInfoObserver(this.photosHolder);//照片浏览评论等信息显示 this.exifInfoObserver = new ExifInfoObserver(this.photosHolder);//exif信息显示 this.photoComment = new PhotoComment(this.photosHolder,this.loginUserId,this.loginUserHead);//照片评论 this.photoNumObserver = new CurrentPhotoNumObserver(this.photosHolder);//当前照片序号显示 this.hitsIncreaseObserver = new HitsIncreaseObserver(this.photosHolder);//浏览数递增的观察器 this.statObserver = new StatObserver(this.photosHolder);//页面浏览统计的观察器 this.photosHolder.setCurrentPhoto(this.photoId);?
?
如果哪一部分需要改变,只需要定位到该部分做修改;如果我们需要增加新的逻辑,只要增加一个类就行。