前言

鲍外祖父公建议并使好的作风获得发展了S.O.L.I.D中国共产党第五次全国代表大会口径,用来越来越好地开始展览面向对象编制程序,中国共产党第五次全国代表大会规范分别是:

  1. The Single Responsibility Principle(单一任务SRP)
  2. The Open/Closed Principle(开闭原则OCP)
  3. The Liskov Substitution Principle(里氏替换原则LSP)
  4. The Interface Segregation Principle(接口分离原则ISP)
  5. The Dependency Inversion Principle(信赖反转原则DIP)

中国共产党第五次全国代表大会标准,小编信任在今日头条已经被商量烂了,非常是C#的兑现,然而相对于JavaScript这种以原型为base的动态类型语言来讲还为数没有多少,该种类将分5篇作品以JavaScript编制程序语言为底蕴来展现中国共产党第五次全国代表大会规格的使用。
OK,开首大家的第一篇:单一任务。

塞尔维亚(Република Србија)语原稿:

JavaScript:S.O.L.I.D中国共产党第五次全国代表大会口径之纯净职责SRP

单纯任务

纯净职务的呈报如下:

A class should have only one reason to change
类发生更改的原因应该只有一个

三个类(JavaScript下应当是三个目的)应该有一组严密相关的行事的野趣是怎么样?遵从单一职务的补益是足以让我们很轻易地来保险那些目的,当一个指标封装了成都百货上千职责的话,一旦一个职务供给修改,势必会影响该目的想的其它职分代码。通过解耦能够让各类职务工特别有弹性地变化。

不过,大家如何通晓八个对象的多个人作品表现构造四个任务照旧单个职务?我们得以透过参照他事他说加以考察Object
Design: Roles, Responsibilies, and Collaborations一书提议的Role
Stereotypes概念来调整,该书提议了之类Role Stereotypes来区分任务:

  1. Information holder – 该对象设计为存款和储蓄对象并提供对象音讯给别的对象。
  2. Structurer – 该对象设计为保卫安全对象和消息之间的涉及
  3. 瑟维斯 provider – 该对象设计为拍卖专业并提供劳务给任何对象
  4. Controller – 该对象设计为垄断(monopoly)决策一文山会海担当的职分管理
  5. Coordinator –
    该对象不做任何决策处管事人业,只是delegate工作到别的对象上
  6. Interfacer – 该对象设计为在系统的一一部分中间转播消息(或央浼)

借使您了然了那么些概念,那就狠轻巧通晓你的代码到底是多职分照旧单一职责了。

前言

Bob三叔提出并使好的古板获得进步了S.O.L.I.D中国共产党第五次全国代表大会规范,用来更加好地拓展面向对象编制程序,五大条件分别是:

  1. The Single Responsibility Principle(单一职分SRP)
  2. The Open/Closed Principle(开闭原则OCP)
  3. The Liskov Substitution Principle(里氏替换原则LSP)
  4. The Interface Segregation Principle(接口分离原则ISP)
  5. D中国共产党第五次全国代表大会原则之纯净职务SRP。The Dependency Inversion Principle(信赖反转原则DIP)

    中国共产党第五次全国代表大会条件,小编深信不疑在天涯论坛已经被批评烂了,特别是C#的落到实处,可是相对于JavaScript这种以原型为base的动态类型语言来讲还为数非常少,该种类将分5篇小说以JavaScript编制程序语言为底蕴来呈现中国共产党第五次全国代表大会口径的行使。
    OK,开首大家的率先篇:单一职责。

     

    纯净任务

    单纯性职分的陈述如下:

    A class should have only one reason to change
    类发生更改的原因应该只有一个
    

    二个类(JavaScript下相应是叁个目的)应该有一组严密相关的行为的情致是怎么样?遵循单一任务的利润是足以让大家很轻便地来珍爱这几个指标,当三个指标封装了无数职责的话,一旦一个任务须求修改,势必会影响该对象想的其余职务代码。通过解耦能够让每一种职责工尤其有弹性地扭转。

    唯独,大家什么样晓得三个对象的五个表现构造多个任务依旧单个任务?大家得以因此参谋Object
    Design: Roles, Responsibilies, and Collaborations一书提议的Role
    Stereotypes概念来调节,该书提议了之类Role Stereotypes来区分义务:

    1. Information holder –
      该对象设计为存款和储蓄对象并提供对象音讯给其余对象。
    2. Structurer – 该对象设计为保险对象和新闻之间的关联
    3. Service provider – 该对象设计为管理专门的职业并提供劳务给别的对象
    4. Controller – 该对象设计为垄断(monopoly)决策一多种担任的职分管理
    5. Coordinator –
      该对象不做任何决定管理专门的学问,只是delegate专门的学问到任何对象上
    6. Interfacer – 该对象设计为在系统的逐个部分中转消息(或央求)

      一旦你驾驭了这几个概念,那就狠轻便精晓您的代码到底是多职务照旧单一职分了。

      实例代码

      该实例代码演示的是将商品充裕到购物车,代码极其倒霉,代码如下:

      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 = $('
      
      •  
      • ‘).html(product.getDescription()).attr(‘id-cart’,
        product.getId()).appendTo(#cart); }
        products.forEach(function (product) { var newItem = $(‘
      •  
      • ‘).html(product.getDescription()) .attr(‘id’,
        product.getId()) .dblclick(addToCart) .appendTo(#products);
        }); })();

        金沙注册送58 ,该代码注明了2个function分别用来说述product和cart,而无名函数的职分是立异荧屏和用户交互,那还不是二个很复杂的事例,但无名氏函数里却含有了无数不相干的职务,让大家来探视毕竟有个别许任务:

        1. 率先,有product的聚焦的宣示
        2. 说不上,有多个将product集结绑定到#product元素的代码,并且还附属类小部件了贰个丰裕到购物车的事件管理
        3. 其三,有Cart购物车的来得效果
        4. 第四,有丰裕product item到购物车并出示的效果

          重构代码

          让大家来讲美赞臣(Meadjohnson)下,以便代码各自存放到各自的靶子里,为此,大家参照他事他说加以考察了martinfowler的事件聚合(伊夫nt
          Aggregator)理论在拍卖代码以便各目的之间开始展览通讯。

          率先大家先来促成事件聚合的功能,该功效分为2部分,1个是伊夫nt,用于Handler回调的代码,1个是伊夫ntAggregator用来订阅和发表Event,代码如下:

                  function Event(name) {
                      var handlers = [];
          
                      this.getName = function () {
                          return name;
                      };
          
                      this.addHandler = function (handler) {
                          handlers.push(handler);
                      };
          
                      this.removeHandler = function (handler) {
                          for (var i = 0; i < handlers.length; i++) {
                              if (handlers[i] == handler) {
                                  handlers.splice(i, 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);
                      };
                  }
          

          接下来,大家来声称Product对象,代码如下:

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

          随着来声称Cart对象,该对象的addItem的function里我们要接触公布多少个平地风波itemAdded,然后将item作为参数字传送进去。

          function Cart(eventAggregator) {
              var items = [];
          
              this.addItem = function (item) {
                  items.push(item);
                  eventAggregator.publish(itemAdded, item);
              };
          }
          

          CartController首如果承受cart对象和事件聚合器,通过订阅itemAdded来增添叁个li成分节点,通过订阅productSelected事件来增多product。

          function CartController(cart, eventAggregator) {
              eventAggregator.subscribe(itemAdded, function (eventArgs) {
                  var newItem = $('
          
          •  
          • ‘).html(eventArgs.getDescription()).attr(‘id-cart’,
            eventArgs.getId()).appendTo(#cart); });
            eventAggregator.subscribe(productSelected, function
            (eventArgs) { cart.addItem(eventArgs.product); }); }

            Repository的指标是为了获取数据(能够从ajax里拿走),然后揭露get数据的秘技。

            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;
                }
            }
            

            ProductController里定义了二个onProductSelect方法,首如果发布触发productSelected事件,forEach主若是用于绑定数据到成品列表上,代码如下:

            function ProductController(eventAggregator, productRepository) {
                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 = $('
            
            •  
            • ‘).html(product.getDescription()) .attr(‘id’,
              product.getId()) .dblclick(onProductSelected)
              .appendTo(#products); }); }

              最终证明无名函数(须要确认保障HTML都加载完了手艺进行这段代码,举例位于jQuery的ready方法里):

              (function () {
                  var eventAggregator = new EventAggregator(),
              cart = new Cart(eventAggregator),
              cartController = new CartController(cart, eventAggregator),
              productRepository = new ProductRepository(),
              productController = new ProductController(eventAggregator, productRepository);
              })();
              

              能够看出无名氏函数的代码裁减了众多,首假设叁个对象的实例化代码,代码里大家介绍了Controller的概念,他收受音信然后传递到action,我们也介绍了Repository的定义,首假若用来管理product的体现,重构的结果正是写了一大堆的对象申明,不过好处是每一个对象有了友好明显的任务,该体现数据的来得数据,改管理集合的管理集结,那样耦合度就非常的低了。

              金沙注册送58 1末尾代码

              总结

              见到这些重构结果,有博友恐怕要问了,真的有至关重要做如此复杂么?作者不得不说:要不要这样做取决于你项指标状态。

              若果你的系列是个是个比十分小的体系,代码也不是好些个,那实在是从未有过要求重构得那样复杂,但固然您的类型是个很复杂的大型项目,也许你的小项目以后恐怕升高得一点也不慢的话,这就在最初就得思量SRP原则进行职责分开了,这样才实惠现在的掩护。

               

前言
Bob岳丈建议并使好的作风获得提升了S.O.L.I.D五大条件,用来越来越好地张开面向对象编制程序,中国共产党第五次全国代表大会原则分别是:
Th…

实例代码

该实例代码演示的是将货品增加到购物车,代码比较差,代码如下:

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");
    });
})();

该代码表明了2个function分别用来描述product和cart,而佚名函数的职分是翻新荧屏和用户交互,那还不是二个很复杂的例证,但无名函数里却富含了多数不相干的义务,让我们来拜望到底有些许任务:

  1. 首先,有product的集纳的扬言
  2. 说不上,有贰个将product集结绑定到#product成分的代码,而且还附属类小部件了四个丰盛到购物车的事件管理
  3. 其三,有Cart购物车的显得效果
  4. 第四,有丰裕product item到购物车并出示的效果与利益

重构代码

让大家来分解一下,以便代码各自寄放到各自的对象里,为此,大家参谋了martinfowler的风浪聚合(伊芙nt
Aggregator)理论在管理代码以便各指标时期张开通讯。

首先大家先来促成事件聚合的效果,该意义分为2部分,1个是伊夫nt,用于Handler回调的代码,1个是伊夫ntAggregator用来订阅和公布Event,代码如下:

        function Event(name) {
            var handlers = [];

            this.getName = function () {
                return name;
            };

            this.addHandler = function (handler) {
                handlers.push(handler);
            };

            this.removeHandler = function (handler) {
                for (var i = 0; i < handlers.length; i++) {
                    if (handlers[i] == handler) {
                        handlers.splice(i, 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);
            };
        }

然后,大家来声称Product对象,代码如下:

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

跟着来声称Cart对象,该指标的addItem的function里大家要接触发表叁个风云itemAdded,然后将item作为参数字传送进去。

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

    this.addItem = function (item) {
        items.push(item);
        eventAggregator.publish("itemAdded", item);
    };
}

CartController重如果经受cart对象和事件聚合器,通过订阅itemAdded来充实三个li成分节点,通过订阅productSelected事件来增多product。

function CartController(cart, eventAggregator) {
    eventAggregator.subscribe("itemAdded", function (eventArgs) {
        var newItem = $('<li></li>').html(eventArgs.getDescription()).attr('id-cart', eventArgs.getId()).appendTo("#cart");
    });

    eventAggregator.subscribe("productSelected", function (eventArgs) {
        cart.addItem(eventArgs.product);
    });
}

Repository的指标是为了获取数据(能够从ajax里拿走),然后暴光get数据的不二等秘书技。

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;
    }
}

ProductController里定义了四个onProductSelect方法,主借使公布触发productSelected事件,forEach首如果用于绑定数据到成品列表上,代码如下:

function ProductController(eventAggregator, productRepository) {
    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></li>').html(product.getDescription())
                                    .attr('id', product.getId())
                                    .dblclick(onProductSelected)
                                    .appendTo("#products");
    });
}

最后注明佚名函数(须要确定保障HTML都加载完了才具实施这段代码,比如位于jQuery的ready方法里):

(function () {
    var eventAggregator = new EventAggregator(),
cart = new Cart(eventAggregator),
cartController = new CartController(cart, eventAggregator),
productRepository = new ProductRepository(),
productController = new ProductController(eventAggregator, productRepository);
})();

能够看来无名函数的代码收缩了许多,重如若八个对象的实例化代码,代码里我们介绍了Controller的概念,他经受信息然后传递到action,大家也介绍了Repository的定义,首假使用来管理product的显得,重构的结果正是写了第一次全国代表大会堆的对象评释,不过好处是各个对象有了温馨了然的职务,该展现数据的呈现数据,改处理集结的管理集结,那样耦合度就相当的低了。

金沙注册送58 2金沙注册送58 3最终代码

        function Event(name) {
            var handlers = [];

            this.getName = function () {
                return name;
            };

            this.addHandler = function (handler) {
                handlers.push(handler);
            };

            this.removeHandler = function (handler) {
                for (var i = 0; i < handlers.length; i++) {
                    if (handlers[i] == handler) {
                        handlers.splice(i, 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 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);
                eventAggregator.publish("itemAdded", item);
            };
        }

        function CartController(cart, eventAggregator) {
            eventAggregator.subscribe("itemAdded", function (eventArgs) {
                var newItem = $('<li></li>').html(eventArgs.getDescription()).attr('id-cart', eventArgs.getId()).appendTo("#cart");
            });

            eventAggregator.subscribe("productSelected", function (eventArgs) {
                cart.addItem(eventArgs.product);
            });
        }

        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(eventAggregator, productRepository) {
            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></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);
        })();

总结

看到那么些重构结果,有博友大概要问了,真的有至关重要做如此复杂么?作者只能说:要不要那样做取决于你项目标情景。

倘若您的品种是个是个可怜小的品种,代码也不是广大,那实在是尚未供给重构得如此复杂,但只要你的体系是个很复杂的大型项目,或许您的小项目今后可能进步得快速的话,那就在早先时期就得思虑SRP原则开始展览任务分开了,那样才方便未来的爱抚。

一同与推荐

正文已联合签字至目录索引:深刻明白JavaScript连串

深深通晓JavaScript种类小说,蕴含了原创,翻译,转发等各种型的稿子,假如对您有用,请推荐协助一把,给大伯写作的重力。


相关文章

网站地图xml地图