Javascript设计模式理论与实战:组合模式

我们平时开发过程中,一定会遇到这种情况:同时处理简单对象和由简单对象组成的复杂对象,这些简单对象和复杂对象会组合成树形结构,在客户端对其处理的时候要保持一致性。比如电商网站中的产品订单,每一张产品订单可能有多个子订单组合,比如操作系统的文件夹,每个文件夹有多个子文件夹或文件,我们作为用户对其进行复制,删除等操作时,不管是文件夹还是文件,对我们操作者来说是一样的。在这种场景下,就非常适合使用组合模式来实现。

基本知识

组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式主要有三个角色:
(1)抽象组件(Component):抽象类,主要定义了参与组合的对象的公共接口
(2)子对象(Leaf):组成组合对象的最基本对象
(3)组合对象(Composite):由子对象组合起来的复杂对象
理解组合模式的关键是要理解组合模式对单个对象和组合对象使用的一致性,我们接下来说说组合模式的实现加深理解。

组合模式的实现

最简单的组合模式

HTML文档的DOM结构就是天生的树形结构,最基本的元素醉成DOM树,最终形成DOM文档,非常适用适用组合模式。
我们常用的jQuery类库,其中组合模式的应用更是频繁,例如经常有下列代码实现:

1 $(".test").addClass("noTest").remove("test");

这句简单的代码就是获取class包含test的元素,然后进行addClass和removeClass处理,其中不论$(“.test”)是一个元素,还是多个元素,最终都是通过统一的addClass和removeClass接口进行调用。

我们简单模拟一下addClass的实现:

 1 var addClass = function (eles, className) {
 2     if (eles instanceof NodeList) {
 3         for (var i = 0, length = eles.length; i < length; i++) {
 4             eles[i].nodeType === 1 && (eles[i].className += (‘ ‘ + className + ‘ ‘));
 5         }
 6     }
 7     else if (eles instanceof Node) {
 8         eles.nodeType === 1 && (eles.className += (‘ ‘ + className + ‘ ‘));
 9     }
10     else {
11         throw "eles is not a html node";
12     }
13 }
14 addClass(document.getElementById("div3"), "test");
15 addClass(document.querySelectorAll(".div"), "test");

这段代码简单的模拟了addClass的实现(暂不考虑兼容性和通用性),很简单地先判断节点类型,然后根据不同类型添加className。对于NodeList或者是Node来说,客户端调用都是同样的使用了addClass这个接口,这个就是组合模式的最基本的思想,使部分和整体的使用具有一致性。

典型的例子

前面我们提到一个典型的例子:产品订单包含多个产品子订单,多个产品子订单组成一个复杂的产品订单。由于Javascript语言的特性,我们将组合模式的三个角色简化成2个角色:
(1)子对象:在这个例子中,子对象就是产品子订单
(2)组合对象:这里就是产品的总订单
假设我们开发一个旅游产品网站,其中包含机票和酒店两种子产品,我们定义了子对象如下:

1 function FlightOrder() { }
2 FlightOrder.prototyp.create = function () {
3     console.log("flight order created");
4 }
5 function HotelOrder() { }
6 HotelOrder.prototype.create = function () {
7     console.log("hotel order created");
8 }

上面的代码定义了两个类:机票订单类和酒店订单类,每个类都有各自的订单创建方法。
接下来我们创建一个总订单类:

 1 function TotalOrders() {
 2     this.orderList = [];
 3 }
 4 TotalOrders.prototype.addOrder = function (order) {
 5     this.orderList.push(order);
 6 }
 7 TotalOrders.prototype.create = function (order) {
 8     for (var i = 0, length = this.orderList.length; i < length; i++) {
 9         this.orderList[i].create();
10     }
11 }

这个对象主要有3个成员:订单列表,添加订单的方法,创建订单的方法。
在客户端使用的时候如下:

1 var flight = new FlightOrder();
2 flight.create();
3
4 var orders = new TotalOrders();
5 orders.addOrder(new FlightOrder());
6 orders.addOrder(new HotelOrder());
7 orders.create();

客户端调用展示了两种方式,一种是单一的创建机票订单,一种是创建多张订单,但最终都是通过create方法进行创建,这就是一个很典型的组合模式的应用场景。

总结

组合模式并不难理解,它主要解决的是单一对象和组合对象在使用方式上的一致性问题。如果对象具有明显的层次结构并且想要统一地使用它们,这就非常适合使用组合模式。在Web开发中,这种层次结构非常常见,很适合使用组合模式,尤其是对于JS来说,不用拘泥于传统面向对象语言的形式,灵活地利用JS语言的特性,达到对部分和整体使用的一致性。

原文地址:http://luopq.com/2015/11/16/design-pattern-composite/

时间: 2024-11-09 23:14:53

Javascript设计模式理论与实战:组合模式的相关文章

Javascript设计模式理论与实战:工厂方法模式

本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用.在之前的<Javascript设计模式理论与实战:简单工厂模式>这篇文章中,我们介绍了简单工厂的知识和一些应用.简单工厂模式存在一个唯一的工厂类,它的优点是所有产品类的实例化集中管理,便于理解,但这既是优点也是缺点.如果产品类的数量较少并且不会经常发生变化,我们可以直接利用简单工厂模式,但是有的时候,需求是随时在变的,产品类也可能随时在增加,如果使用简单工厂模式

javascript设计模式学习之十——组合模式

一.组合模式定义及使用场景 组合模式将对象组合成树形结构,用以表示“部分—整体”的层次结构,除了用来表示树形结构之外,组合模式还可以利用对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性. 实现组合模式的关键: 在java等静态语言中,需要单个对象和组合对象都实现同样的抽象接口,这可以通过抽象类或者接口来实现. 在javascript中,对象的多态性是与生俱来的,没有编译器去检查对象的类型,因此实现组合模式的要点是保证组合兑现个单个对象用友同样的方法,这通常需要使用“鸭子类型”的思想

JavaScript设计模式样例十 —— 组合模式

组合模式(Composite Pattern) 定义:又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.目的:将对象组合成树形结构以表示"部分-整体"的层次结构.场景:您想表示对象的部分-整体层次结构(树形结构),如:文件系统. // 指令 let directive = { eat: { excute: () => { console.log('eat') } }, sleep: { excute: () => { console.log('sleep') }

Javascript设计模式理论与实战:桥接模式

桥接模式将抽象部分与实现部分分离开来,使两者都可以独立的变化,并且可以一起和谐地工作.抽象部分和实现部分都可以独立的变化而不会互相影响,降低了代码的耦合性,提高了代码的扩展性. 基本理论 桥接模式定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化.桥接模式主要有4个角色组成:(1)抽象类(2)扩充抽象类(3)实现类接口(4)具体实现类根据javascript语言的特点,我们将其简化成2个角色:(1)扩充抽象类(2)具体实现类怎么去理解桥接模式呢?我们接下来举例说明 桥接模式的实现 理解桥

Javascript设计模式理论与实战:简单工厂模式

通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式的理论,并且举例说明了简单工厂模式的具体应用. 基本介绍 简单工厂模式是工厂模式中最基本的一种.通过定义一个工厂类,根据参数实例化具体的某个产品类. 举例说明 我们举个例子进行说明:假设我们开发一个旅游行业网站,网站上面销售机票,酒店等产品.一个用户准备购买一张机票.我们可以定义相关类如下: 1 v

Javascript设计模式理论与实战:适配器模式

有的时候在开发过程中,我们会发现,客户端需要的接口和提供的接口发生不兼容的问题.由于特殊的原因我们无法修改客户端接口.在这种情况下,我们需要适配现有接口和不兼容的类,这就要提到适配器模式.通过适配器,我们可以在不用修改旧代码的情况下也能使用它们,这就是适配器的能力. 基本理论 适配器模式:将一个接口转换成客户端需要的接口而不需要去修改客户端代码,使得不兼容的代码可以一起工作. 适配器主要有3个角色组成:(1)客户端:调用接口的类(2)适配器:用来连接客户端接口和提供服务的接口的类(3)适配者:提

设计模式 3 —— 迭代器和组合模式

设计模式目录: 设计模式 1 ——观察者模式 设计模式 2 —— 装饰者模式 设计模式 3 —— 迭代器和组合模式 概要 设计模式 3 -- 迭代器和组合模式

设计模式(七)组合模式Composite(结构型)

设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象.客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的.对这些类区别使用,使得程序更加复杂.递归使用的时候跟麻烦,而我们如何

设计模式(9)--迭代器与组合模式

(1)散列表(hashtable)         共迭代器获取 hashtable.values().iterator();  因为每一笔数据都是由键值对组成. (2)迭代器是用来遍历集合的. Java5后集合都出了自己的遍历方式 如增加for循环.           遍历 也称 游走... (3)数组:Array 长定固定   集合:ArrayList 可扩展,取数据不需要转型 (4)Java中有自己的迭代器接口.在java.util.Iterator  . (5)集合:collectio