Комбинированный режим
- Что такое комбинированный режим
- Комбинации паттернов в жизни
- Практическое применение комбинированной модели
- Зачем использовать наследование js
официальный:组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 "组合对象" 的含义。
- Ну, вы можете игнорировать ту чушь, которую я сказал выше, и слушать мой ББ ниже.
легендарный23
Название китайского паттерна проектирования уже всем рассказало, что это за рутина, но в дальнейшем мы обсудим не только понимание, но и поиск возможностей ее использования.
Комбинации паттернов в жизни
В жизни еще много комбинаций:麦当劳套餐
,饭店美团X人套餐
,联通流量包
Подождите, они сочетают в себе несколько «отдельных людей» в целом «, это пример от жизни, позвольте мне поговорить с недавним практическим небольшим проектом.
Возьмите каштан:
Недавно в компании появился небольшой модуль под названием «Диаграмма Ганта»,github
В основном это так:
Но как может компания хотеть такую традиционную вещь, она должна быть инновационной! ! ! Что именно есть, традиционные только一条线
, босс: добавь меня两条
, а预期
, а实际
, иметьmileStone
(веха), добавить总进度
, Добавить...组合模式
Бар 😆.
Во-первых, мы убедимся, что имя компонента называетсяGantt
(KFC) Ну и что же включают в себя компоненты: разделить на эти мелкие составляющие (пакеты):画图
Пакет (включает: индикатор выполнения, фоновую сетку, дополнение контента),格式化
Пакет, а также несколько простых инструментов: получить самое длинное время, форматирование даты, просто чтобы дать вам каштан.
Это будет выглядеть так, когда это будет сделано:
адрес с открытым исходным кодом на githubДавайте сделаем здесь спецификацию.В дальнейшем я буду называть виджеты Ганта (магазин) (пакетами), а методы-прототипы в компонентах называются (члены).
- Сначала создайте колесо наследника↓
//建立一个属于我们自己的Jquery,里面只有inheritObject、inheritPrototype两个方法,
(function () {
var util = {
inheritObject: function (o) {//对象继承封装
var F = function () {
};
F.prototype = o;
return new F();
},
inheritPrototype: function (subclass, supperclass) {//原型继承封装
var obj = this.inheritObject(supperclass.prototype);
obj.constructor = subclass;
subclass.prototype = obj;
}
};
window.$ = window.util = util;
})(window);//把闭包变量弄到全局
var Gantt = function (data) {
this.ganttData = data;
this.children = [];
this.element = null;
}
Gantt.prototype = {
init: function () {
throw new Error('此方法必须子类重写')
},
build: function () {
throw new Error('此方法必须子类重写')
},
}
/**
* 创建 Gantt外层容器
* @param name
* @param parent
* @constructor
*/
var Container = function (name, parent) {
Gantt.call(this);
this.name = name;
this.parent = parent;
this.init();//构建子容器的基本点(id,dom,name)
}
$.inheritPrototype(Container, Gantt); //
Container.prototype = {
/**
*重写父类init
*/
init: function () {
this.element = document.createElement('div');//创建一个div元素
this.element.name = this.name;
this.element.id = 'ganttView';
this.parent.append(this.element);
},
/**
*重写父类build
*/
build: function (child, text) {
child.append(document.createTextNode(text)); //添加测试描述
this.children.push(child);
this.element.appendChild(child);
return this;
},
getElement: function () {
return this.element;
},
draw: function () {
this.parent.appendChild(this.element)
}
}
//调用方法
var ganttView = new Container('GanttView', document.body);
ganttView.build(document.createElement("div"), '左侧详情项目1')
.build(document.createElement("div"), '左侧详情项目2').build(document.createElement("div"), '右侧画图')
```
节约时间css就不写了,
float:left;
height,width,
color,backbround,
text:center.....脑补中...
```
Затем мы замечаем,Container
является вторичным контейнером на основеparent
То есть самый примитивный элемент 'тело' постепенно прорисовывается внутрь, а есть более сложное наполнение (вычисление максимального временного диапазона, отрисовка фона, добавление календаря и т.д.)
Также должно бытьitem
внутри увеличение描述
,详情
,画图
Ждать
Конечно, описания, детали и чертежи — это всего лишь «пакеты», а «члены» нижнего уровня по-прежнему необходимы в качестве основы. Члены — это самое основное, у них больше нет подклассов, но они наследуют родительский класс.
Итак, давайте изменим код в целом:
var Gantt = function (data) {
this.ganttData = data;
this.children = [];
this.element = null;
}
Gantt.prototype = {
init: function () {
throw new Error('此方法必须子类重写')
},
build: function () {
throw new Error('此方法必须子类重写')
},
}
/**
* 创建 Gantt外层容器
* @param name
* @param parent
* @constructor
*/
var Container = function (name, parent) {
Gantt.call(this);
this.name = name;
this.parent = parent;
this.init();//构建子容器的基本点(id,dom,name)
}
$.inheritPrototype(Container, Gantt); //
Container.prototype = {
/**
*重写父类init
*/
init: function () {
this.element = document.createElement('div');//创建一个div元素
this.element.id = 'ganttView';
this.element.textContent= this.name;
this.parent.append(this.element);
},
/**
*重写父类build
*/
build: function (child) {
// child.append(document.createTextNode(text)); //添加测试描述
this.children.push(child);
this.element.appendChild(child.element);
return this;
},
getElement: function () {
return this.element;
},
draw: function () {
this.parent.appendChild(this.element)
}
}
/**
* 创建 Gantt基础成员
* @param name
* @param parent
* @constructor
*/
var Item = function (name, parent) {
Gantt.call(this);
this.name = name;
this.parent = parent;
this.init();//构建子容器的基本点(id,dom,name)
}
$.inheritPrototype(Item, Container); //
Item.prototype = {
/**
*重写父类init
*/
init: function () {
this.element = document.createElement('div');//创建一个div元素
this.element.id = 'ganttItem';
this.element.textContent = this.name;
// this.parent.append(this.element);
// return this.element;
},
/**
*重写父类build
*/
build: function (text) {
//可以再画进度条,以及为进度条绑定点击事件
},
getElement: function () {
return this.element;
},
draw: function () {
this.parent.appendChild(this.element)
}
}
//调用方法
var container = new Container('GanttView', document.body);
container.build(new Item('左侧详情项目1'))
.build(new Item('左侧详情项目2'))
```
![](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2017/10/18/997cfd2b701a539045c4dad52aa460f3~tplv-t2oaga2asx-image.image)
- 为什么要使用`继承`,贼麻烦.我直接`new`不行么?
“行,但是记住一点,我们使用了组合模式就要保障接口的统一,这也是[面向对象编程](https://juejin.cn/post/6844903475843694600)的思想,类似`java`的`interface`接口,这样我们处理回调、异常更加方便,简化了复杂的整体,又通过子类丰富了整体。“
我原来写的甘特图,是一次性生成的,如果产品提出,若使用`长轮循`监听到服务器,如果服务器增加了一个任务,以动画的形式动态添加一条进度条,这对于我以前的组件来说改动比较大,但是这个就很简单了,可能我们加一个add原型方法继承就好了。
- 那么组合模式有啥好处?
“使得项目更加模块化,一个组件可以无限向下分成各个套餐,直到到达最底层的成员,以原子粒度书写代码,对于代码维护十分有利。”
开源的[Gantt插件](https://github.com/pkwenda/gantt.js)是基于`Jquery`的扩展插件,没有用到svg等笨重的组件,只依赖jquery,只有14k,还有一些亮点没有提交,当时写的比较匆忙,现在最近想想也许当时考虑用组合模式更加适合于以后需求的变更。极大节约开发时间。
### 最后希望大家能写出更加风骚的代码