您的位置:首页 > Web前端 > JavaScript

记录对一段js代码重构的理解

2016-01-07 00:00 821 查看
功能具备但组织结构比较混乱的代码:

function Product(id, description) {
this.getId = function () {
return id;
};
this.getDescription = function () {
return description;
};
}

function Cart(eventAggregator) {
var items = [];

this.addItem = function (item) {
items.push(item);
};
}

(function () {
var products = [new Product(1, "Star Wars Lego Ship"),
new Product(2, "Barbie Doll"),
new Product(3, "Remote Control Airplane")],
cart = new Cart();

function addToCart() {
var productId = $(this).attr('id');
var product = $.grep(products, function (x) {
return x.getId() == productId;
})[0];
cart.addItem(product);

var newItem = $('<li></li>').html(product.getDescription()).attr('id-cart', product.getId()).appendTo("#cart");
}

products.forEach(function (product) {
var newItem = $('<li></li>').html(product.getDescription())
.attr('id', product.getId())
.dblclick(addToCart)
.appendTo("#products");
});
})();

下面是重构后的:

/*这里有两个实体:产品和购物车;产品有自己的集合,同时购物车也可以看成产品的集合;产品和购物车都各自的视图;
*单个实体对应的视图上的孤立事件(不会影响到其它实体或对应的视图)不需要用到事件对象,实体之间发生交互时才需要事件对象
*订阅和发布方法的调用对象都是事件集合的实例,这个无关紧要,重要的是它们调用时的位置,与用户有直接交互的视图对应的实体往往是发布者,被联动影响的实体往往是订阅者。
如:用户双击产品,产品会添加到购物车,这里与用户直接交互的是产品,间接被影响的是购物车,每个产品都有同样的双击事件,所以双击事件方法统一写到产品集合中,与实体间交互相关的发布动作紧随其后。产品添加到购物车其实有两个动作:产品实例添加到购物车中缓存、产品出现在购物车视图上。在产品上双击实际上只是直接产生了前一个动作,后一个动作被间接触发了
*/
/*事件对象
*内容:事件名称、事件回调集合、添加/删除/触发事件回调
*事件对象一定有事件名称,不一定有事件回调,创建事件对象时一定要指定事件名称
*/
function Event(name){
var handlers = [];
this.getName = function(){
return name;
};
this.addHandler = function (handler){
handlers.push(handler);
};
this.removeHandler = function(handler){
for(var l=handlers.length;l--;){
if(handler == handlers[l]){
handlers.splice(l+1,1);
break;
}
}
};
this.fire = function(eventArgs){
handlers.forEach(function(h){
h(eventArgs);
});
}
}
/*事件集合
*功能:缓存事件对象,从缓存中获取指定名称的事件对象(提供集合的缓存元素功能)
*往集合中添加指定事件、触发指定事件(对集合中元素的操作能力)
*
*/
function EventAggregator(){
var events = [];
function getEvent(eventName){
return $.grep(events, function(event){
return event.getName() === eventName;
})[0];
}
this.publish = function (eventName, eventArgs){
var event = getEvent(eventName);
if(!event){
event = new Event(eventName);
events.push(event);
}
event.fire(eventArgs);
}
this.subscribe = function(eventName, handler){
var event = getEvent(eventName);
if(!event){
event = new Event(eventName);
events.push(event);
}
event.addHandler(handler);
}
}

/*第二个实体:购物车
*购物车是产品的一个集合
*有添加产品方法,必然会导致一个添加产品事件在这里发布
*可能还有删除产品方法
*只是提供接口,表示它有这些能力,到控制器中去使用这些能力
*/
function Cart(eventAggregator){
var items = [];
this.addItem = function(item){
items.push(item);
eventAggregator.publish('itemAdded', item);/*把它写在这而不是控制器中的原因是:可能有多种方式添加产品到购物车,写在这避免了在控制器里的每一种添加产品方式后都加上这么一句*/
}
}

/*购物车相关事件的观察者
*各种相关事件的订阅
*把它从Cart类中剥离出来的原因就是这里有视图相关的操作,或者把那些对购物车中产品的操作都集中到这里,来体现控制器的语义
*/
function CartController(cart, eventAggregator){
eventAggregator.subscribe('itemAdded', function(eventArgs){
var newItem = $('<li>').html(eventArgs.getDescription()).attr('id-cart',eventArgs.getId()).appendTo('#cart');
});
/*这是个连环事件*/
eventAggregator.subscribe('productSelected', function(eventArgs){
cart.addItem(eventArgs.product);
});
}

/*第一个实体:产品*/
function Product(id, description){
this.getId = function(){
return id;
}
this.getDescription = function(){
return description;
}
}

/*产品的另一个集合
*包括导出数据集合的方法
*也包括从后台获取数据、组装成产品对象的方法
*还可能包含删除产品的方法
*/
function ProductRepository(){
var products = [new Product(1,'Star wars lego ship'),
new Product(2, 'Barbie doll'),
new Product(3, 'Remote control airplane')];
this.getProducts = function(){
return products;
}
}

/*产品的观察者
*给每个产品绑定点击事件
*产品发生点击事件添加到购物车后,必然会导致一个购物车添加产品的事件被发布
*结构和购物车的观察者类似,传入的参数也相似
*/
function ProductController(productRepository, eventAggregator){
var products = productRepository.getProducts();
function onProductSelected(){
var productId = $(this).attr('id');
var product = $.grep(products, function(x){
return x.getId() == productId;
})[0];
eventAggregator.publish('productSelected', {product: product});
}
products.forEach(function(product){
var newItem = $('<li>').html(product.getDescription())
.attr('id', product.getId())
.dblclick(onProductSelected)
.appendTo($('#products'));
});
}

(function(){
var eventAggregator = new EventAggregator(),
cart = new Cart(eventAggregator),
cartController = new CartController(cart, eventAggregator),
productRepository = new ProductRepository(),
productController = new ProductController(eventAggregator, productRepository);
}());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  js代码重构