?
?
先来图:
?
这张图是查看单张照片的界面。
现在的问题是,如何设计和实现这张页面。
大家注意到,随着图片的改变,页面是不刷新的,也就是说你查看另外一张图片时,页面中的很多信息需要同步修改,如下图:
还有一块很重要的信息,那就是图片的评论,也需要随之改变。
我们的要求是,实现这个功能的代码需要清楚,模块化,容易维护,扩展容易。
现在我们的难题似乎是图片改变的同时,其他的信息用一种什么方式随之改变,我们这里定义了一个接口:
?
?
/** * 改变照片的事件xxx */ var PhotoChangeListener = Class.create({ initialize:function(){}, /** * 当改变照片时,该方法被调用 * @param newPhotoId 改变的新的照片id * @param isNext boolean 是否是查看下一张图片 */ handlePhotoChange:function(newPhotoId,isNext){ } }); 用js来定义接口实在是小题大作,不过,这样定义感觉上会更清楚明白一些。 这个xxx处理的代码是在handlePhotoChange里完成。 为此,我们还设计了一个所有照片的持有类,美其名曰:“封装” /** * 照片集合的持有类 * 当调用setCurrentPhoto时,会依次调用photoChangeListeners中的照片改变的事件xxx里的handlePhotoChange方法 */ var PhotosHolder = Class.create({ /** * @param photos 照片对象的列表 */ initialize:function(photos){ }, getPhotoNumber:function(){ }, /** * 得到某个photoId的photo对象 * 如果不存在该photoId的photo,则返回null */ getPhoto:function(photoId){ }, indexOfPhoto:function(photoId){ }, /** * 增加一个照片改变的xxx */ addPhotoChangeListener:function(photoChangeListener){ }, /** * 设置某照片为当前的照片 */ setCurrentPhoto:function(photoId,isNext){ }, /** * 得到下一张照片,如果没有下一张照片,返回null */ nextPhoto:function(){ }, /** * 得到上一张照片,如果没有上一张照片,返回null */ previousPhoto:function(){ }, /** * 得到当前页面上显示的照片 */ getCurrentPhoto:function(){ }, /** * 得到{dy}张图片 */ getFirstPhoto:function(){ }, /** * 得到{zh1}一张图片 */ getLastPhoto:function(){ }, /** * 增加一个照片标记信息 * @param photoMentionInfo 标记信息对象 */ addPhotoMention:function(photoMentionInfo){ }, /** * 增加某张照片的一批标记信息 */ addPhotoMentions:function(photoId,mentions){ }, /** * 删除一个照片标记信息 */ removePhotoMention:function(mentionInfoId){ }, /** * 得到某照片的标记信息,如果不存在,则返回null */ getPhotoMentions:function(photoId){ } });?
?
?
这里给出了接口定义,具体的实现也不是很困难,我们重点注意这两个方 法:addPhotoChangeListener,setCurrentPhoto。方法addPhotoChangeListener用于将图片改变 的xxx注册到图片的持有者中,setCurrentPhoto方法用于客户端设置显示某一张图片,在setCurrentPhoto方法中,如果设置的 图片不是当前显示的图片,就会调用注册到该类的所有图片xxx的handlePhotoChange,剩下的工作就交给各个xxx处理了。
?
这里的设计思想是,解耦。我们可以将图片改变的动作和处理该图片改变的处理分开,往往处理逻辑需要很多,我们只需要增加一个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);?
?
如果哪一部分需要改变,只需要定位到该部分做修改;如果我们需要增加新的逻辑,只要增加一个类就行。