├── .idea ├── javascript-design-patterns02-master.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── 1-面向对象编程 ├── chapter_01JavaScript │ ├── 1.1.入职第一天.js │ ├── 1.10可以链式添加吗.js │ ├── 1.11换一种方式使用方法.js │ ├── 1.2函数的另一种形式.js │ ├── 1.3用对象收编变量.js │ ├── 1.4对象的另一种形式.js │ ├── 1.5真假对象.js │ ├── 1.6类也可以.js │ ├── 1.7一个检测类.js │ ├── 1.8方法还可以这样用.js │ └── 1.9函数的祖先.js └── chapter_02面向对象编程 │ ├── 2.2.1创建一个类.js │ ├── 2.2.2属性与方法的封装.js │ ├── 2.2.3闭包的实现_1.js │ ├── 2.2.3闭包的实现_2.js │ ├── 2.2.4创建对象的安全模式.js │ ├── 2.3.1类式继承_1.js │ ├── 2.3.1类式继承_2.js │ ├── 2.3.2构造函数继承.js │ ├── 2.3.3组合继承.js │ ├── 2.3.4原型式继承.js │ ├── 2.3.5寄生式继承.js │ ├── 2.3.6寄生组合式继承.js │ ├── 2.4.1单继承.js │ ├── 2.4.2多继承.js │ ├── 2.5多态_1.js │ └── 2.5多态_2.js ├── 2-创建型设计模式 ├── chapter_03简单工厂模式 │ ├── 3.1工作中的第一次需求.js │ ├── 3.2如果类太多,那么提供一个.js │ ├── 3.3一个对象有时候也可代替许多类_1.js │ ├── 3.3使用工厂模式改进需求_2.js │ └── README.md ├── chapter_04工厂方法模式 │ ├── 4.1广告展现.js │ ├── 4.3安全模式类.js │ └── 4.4安全的工厂方法.js ├── chapter_05抽象工厂模式 │ ├── 5.1抽象类 │ ├── 5.2抽象工厂模式.js │ └── README.md ├── chapter_06建造者模式 │ ├── 6.2创建对象的另一种形式.js │ └── README.md ├── chapter_07原型模式 │ ├── 7.2创建一个焦点图.js │ ├── 7.3最优的解决方案.js │ ├── 7.5原型继承.js │ └── README.md └── chapter_08单例模式 │ ├── 8.5无法修改的静态变量.js │ ├── 8.6惰性单例.js │ └── README.md ├── 3-结构性设计模式 ├── chapter_09外观模式 │ ├── 9.2兼容方式.js │ ├── 9.3除此之外.js │ ├── 9.4小型代码库.js │ └── README.md ├── chapter_10适配器模式 │ ├── 10.4适配异类框架.js │ ├── 10.5参数适配器.js │ ├── 10.6数据适配.js │ ├── 10.7服务器端数据适配.js │ └── README.md ├── chapter_11代理模式 │ ├── 11.3站长统计.js │ ├── 11.4JSONP.html │ ├── 11.5X域代理B页面.html │ ├── 11.5X域被代理A页面.html │ ├── 11.5Y域中被请求的文件接口.php │ └── README.md ├── chapter_12装饰者模式 │ └── 12.2装饰者模式.js ├── chapter_13桥接模式 │ └── 13.3桥接模式.js ├── chapter_14组合模式 │ ├── 1.jpg │ ├── 14.4组合要有容器类.js │ ├── 14.5创建一个新闻类.js │ ├── 14.6把新闻模块创建出来.js │ └── demo.html └── chapter_15享元模式 │ ├── 15.3享元对象.js │ ├── 15.4实现需求.js │ ├── 15.5享元动作.js │ └── demo.html ├── 4-行为型设计模式 ├── chapter_16模板方法模式 │ ├── 16.3创建基本提示框.js │ ├── 16.4模板的原型方法.js │ ├── 16.5根据模板类创建类.js │ ├── 16.6继承类也可作为模板类.js │ └── demo.html ├── chapter_17观察者模式 │ ├── 17.3 创建一个观察者.js │ ├── 17.6大显身手.js │ ├── 17.7对象间解耦.js │ ├── 17.8演练.js │ └── demo.html ├── chapter_18状态模式 │ ├── 18.6状态优化.js │ ├── 18.7两种使用方式.js │ └── demo.html ├── chapter_19策略模式 │ ├── 19.3策略对象.js │ ├── 19.6表单验证.js │ ├── 19.7拓展与调用.js │ └── demo.html ├── chapter_20职责链模式 │ ├── 20.3第一站-请求模式.js │ ├── 20.4下一站-响应数据适配模块.js │ ├── 20.5终点站-创建组件模块.js │ └── 20.6单元测试.js ├── chapter_21命令模式 │ ├── 21.2命令对象.js │ └── 21.3视图创建.js ├── chapter_22访问者模式 │ ├── 22.4事件自定义数据.js │ ├── 22.5对象访问器.js │ └── demo.html ├── chapter_23中介者模式 │ ├── 23.2创建中介者对象.js │ ├── 23.5订阅消息.js │ └── 23.6发布消息.js ├── chapter_24备忘录模式 │ └── 24.3新闻缓存器.js ├── chapter_25迭代器模式 │ └── 25.2迭代器.js └── chapter_26解释器模式 │ ├── 26.4同级兄弟元素遍历.js │ ├── 26.5遍历文档树.js │ └── demo.html ├── 5-技巧型设计模式 ├── chapter_28委托模式 │ └── 28.4内存外泄.html ├── chapter_29数据访问对象模式 │ ├── 29.10连接MongoDB.js │ ├── 29.11操作集合.js │ ├── 29.2数据访问对象类.js │ └── 29.9node配置项.js └── chapter_30节流模式 │ └── 30.2节流器.js └── README.md /.idea/javascript-design-patterns02-master.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 150 | 151 | 152 | 154 | 155 | 210 | 211 | 212 | 213 | 214 | true 215 | DEFINITION_ORDER 216 | 217 | 218 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | JavaScript 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 271 | 272 | 273 | 274 | 277 | 278 | 281 | 282 | 283 | 284 | 287 | 288 | 291 | 292 | 295 | 296 | 299 | 300 | 301 | 302 | 305 | 306 | 309 | 310 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 362 | 363 | project 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | project 380 | 381 | 382 | true 383 | 384 | 385 | 386 | DIRECTORY 387 | 388 | false 389 | 390 | 391 | 392 | 393 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 1484117007430 402 | 420 | 421 | 422 | 423 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 450 | 451 | 454 | 457 | 458 | 459 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.1.入职第一天.js: -------------------------------------------------------------------------------- 1 | function checkName() { 2 | // 验证姓名 3 | } 4 | 5 | function checkEmail() { 6 | // 验证邮箱 7 | } 8 | 9 | function checkPassword() { 10 | // 验证密码 11 | } 12 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.10可以链式添加吗.js: -------------------------------------------------------------------------------- 1 | Function.prototype.addMethod = function(name, fn) { 2 | this[name] = fn; 3 | return this; 4 | }; 5 | 6 | // 添加方法就可以这样做了 7 | var methods = function() {}; 8 | Function.addMethod("checkName", function() { 9 | // 验证姓名 10 | }).addMethod("checkEmail", function() { 11 | // 验证邮箱 12 | }); 13 | 14 | /** 同样也可以进行链式调用 15 | * 既然添加方法的时候可以将this返回实现,那么添加的每个方法将this返回就可以实现链式调用 16 | */ 17 | var metods = function() {}; 18 | methods.addMethod("checkName", function() { 19 | // 验证姓名 20 | return this; 21 | }).addMethod("checkEmail", function() { 22 | // 验证邮箱 23 | return this; 24 | }); 25 | 26 | // 调用 27 | methods.checkName().checkEmail(); 28 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.11换一种方式使用方法.js: -------------------------------------------------------------------------------- 1 | Function.prototype.addMethod = function(name, fn) { 2 | this.prototype[name] = fn; 3 | return this; 4 | }; 5 | 6 | // 此时我们还可以按照上一种方式添加方法 7 | var Methods = function() {}; 8 | Methods.addMethod("checkName", function() { 9 | // 验证姓名 10 | }).addMethod("checkEmail", function() { 11 | // 验证邮箱 12 | }); 13 | 14 | // 但是我们现在使用的时候需要注意了,不能直接使用,要通过new关键字来创建新对象想。 15 | var m = new Methods(); 16 | m.checkEmail(); 17 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.2函数的另一种形式.js: -------------------------------------------------------------------------------- 1 | var checkName = function() { 2 | // 验证姓名 3 | }; 4 | 5 | var checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | 9 | var checkPassword = function() { 10 | // 验证密码 11 | }; 12 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.3用对象收编变量.js: -------------------------------------------------------------------------------- 1 | var CheckObject = { 2 | checkName: function() { 3 | // 验证姓名 4 | }, 5 | checkEmail: function() { 6 | // 验证邮箱 7 | }, 8 | checkPassword: function() { 9 | // 验证密码 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.4对象的另一种形式.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() {}; 2 | CheckObject.checkName = function() { 3 | // 验证姓名 4 | }; 5 | CheckObject.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | CheckObject.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.5真假对象.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() { 2 | return { 3 | checkName: function() { 4 | // 验证姓名 5 | }, 6 | checkEmail: function() { 7 | // 验证密码 8 | }, 9 | checkPassword: function() { 10 | // 验证密码 11 | } 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.6类也可以.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() { 2 | this.checkName = function() { 3 | // 验证姓名 4 | }; 5 | this.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | this.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.7一个检测类.js: -------------------------------------------------------------------------------- 1 | var CheckObject = function() {}; 2 | CheckObject.prototype.checkName = function() { 3 | // 验证姓名 4 | }; 5 | CheckObject.prototype.checkEmail = function() { 6 | // 验证邮箱 7 | }; 8 | CheckObject.prototype.checkPassword = function() { 9 | // 验证密码 10 | }; 11 | 12 | /** 也可以这样做 */ 13 | var CheckObject = function() {}; 14 | CheckObject.prototype = { 15 | checkName: function() { 16 | // 验证姓名 17 | }, 18 | checkEmail: function() { 19 | // 验证邮箱 20 | }, 21 | checkPassword: function() { 22 | // 验证密码 23 | } 24 | }; 25 | 26 | /** 注意:这两种方式不能混用,否则一旦混用,如在后面为对象的原型对象复制新对象时,那么他将会覆盖掉之前对prototype对象赋值的方法 */ 27 | 28 | // 调用 29 | var a = new CheckObject(); 30 | a.checkName(); 31 | a.checkEmail(); 32 | a.checkPassword(); 33 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.8方法还可以这样用.js: -------------------------------------------------------------------------------- 1 | var CheckObject = { 2 | checkName: function() { 3 | // 验证姓名 4 | return this; 5 | }, 6 | checkEmail: function() { 7 | // 验证邮箱 8 | return this; 9 | }, 10 | checkPassword: function() { 11 | // 验证密码 12 | return this; 13 | } 14 | }; 15 | 16 | // 调用 17 | CheckObject.checkName().checkEmail().checkPassword(); 18 | 19 | /** 同样的方式也可以放到类的原型对象中 */ 20 | var CheckObject = function() {}; 21 | CheckObject.prototype = { 22 | checkName: function() { 23 | // 验证姓名 24 | return this; 25 | }, 26 | checkEmail: function() { 27 | // 验证邮箱 28 | return this; 29 | }, 30 | checkPassword: function() { 31 | // 验证密码 32 | return this; 33 | } 34 | }; 35 | 36 | // 调用的时候需要先创建一下 37 | var a = new CheckObject(); 38 | a.checkName().checkEmail().checkPassword(); 39 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_01JavaScript/1.9函数的祖先.js: -------------------------------------------------------------------------------- 1 | /** 2 | * prototype.js是什么 3 | * 一款JavaScript框架,里面为我们方便的封装了很多方法,他最大的特点是对原生对象(JavaScript语言为们提供的对象类,如Function、Array、Object等等)的拓展。 4 | * 例如我们想给每一个函数都添加一个检测邮箱的方法可以这么做 5 | */ 6 | 7 | Function.prototype.checkEmail = function() { 8 | // 验证邮箱 9 | }; 10 | 11 | // 这时候调用就比较方便了 12 | var f = function() {}; 13 | f.checkEmail(); 14 | 15 | // 如果你习惯类的形式,也可以这么用 16 | var f = new Function(); 17 | f.checkEmail(); 18 | 19 | /** 这样做会无缘原生对象Function,所以别人创建的函数也会被你创建的函数所污染,造成不必要的开销,但是你可以抽象出一个统一添加方法的功能方法 */ 20 | Function.prototype.addMethod = function(name, fn) { 21 | this[name] = fn; 22 | }; 23 | 24 | // 如果你想添加永祥验证和姓名验证方法你可以这样做 25 | var methods = function() {}; 26 | // 或者 27 | var methods = new Function(); 28 | methods.addMethod("checkName", function() {}); 29 | methods.addMethod("checkEmail", function() {}); 30 | 31 | // 调用 32 | methods.checkEmail(); 33 | methods.checkName(); 34 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.2.1创建一个类.js: -------------------------------------------------------------------------------- 1 | var Book = function(id, bookname, price) { 2 | this.id = id; 3 | this.name = bookname; 4 | this.price = price; 5 | }; 6 | 7 | /** 在类的原型上添加属性和方法,有两种方式,一种是一一为源性对象属性赋值,另一种则是将一个对象赋值给类的原型对象。但这两种不要混用 */ 8 | Book.prototype.display = function() { 9 | // 展示这本书 10 | }; 11 | 12 | // 或者 13 | Book.prototype = { 14 | display: function() {} 15 | }; 16 | 17 | var book = new Book(10, "JavaScript设计模式", 50); 18 | console.log(book.bookname); 19 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.2.2属性与方法的封装.js: -------------------------------------------------------------------------------- 1 | // 私有属性与私有方法,对象公有属性和对象公有方法,构造器 2 | var Book = function(id, name, price) { 3 | // 私有属性 4 | var num = 1; 5 | // 私有方法 6 | function checkId() {} 7 | // 特权方法 8 | this.getName = function() {}; 9 | this.getPrice = function() {}; 10 | this.setName = function() {}; 11 | this.setPrice = function() {}; 12 | // 对象公有属性 13 | this.id = id; 14 | this.copy = function() {}; 15 | // 构造器 16 | this.setName(name); 17 | this.setPrice(price); 18 | }; 19 | 20 | // 类静态公有属性(对象不能访问) 21 | Book.isChinese = true; 22 | // 类静态公有方法(对象不能访问) 23 | Book.resetTime = function() { 24 | console.log("new Time"); 25 | }; 26 | Book.prototype = { 27 | // 公有属性 28 | isJSBook: false, 29 | // 公有方法 30 | display: function() {} 31 | }; 32 | 33 | var b = new Book(11, "JavaScript设计模式", 50); 34 | console.log(b.num); // undefined 35 | console.log(b.isJSBook); // false 36 | console.log(b.id); // 11 37 | console.log(b.isChinese); // undefined 38 | 39 | console.log(Book.isChinese); // true 40 | Book.resetTime(); // new Time 41 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.2.3闭包的实现_1.js: -------------------------------------------------------------------------------- 1 | var Book = (function() { 2 | // 静态私有属性 3 | var bookNum = 0; 4 | // 静态私有方法 5 | function checkBook(name) {} 6 | 7 | // 返回构造函数 8 | return function(newId, newName, newPrice) { 9 | // 私有变量 10 | var name, price; 11 | // 私有方法 12 | function checkId(id) {} 13 | 14 | // 特权方法 15 | this.getName = function() {}; 16 | this.getPrice = function() {}; 17 | this.setName = function() {}; 18 | this.setPrice = function() {}; 19 | // 公有属性 20 | this.id = newId; 21 | // 公有方法 22 | this.copy = function() {}; 23 | bookNum++; 24 | if (bookNum > 100) { 25 | throw new Error("我们仅出版100本书"); 26 | } 27 | // 构造器 28 | this.setName(name); 29 | this.setPrice(price); 30 | }; 31 | })(); 32 | 33 | Book.prototype = { 34 | // 静态公有属性 35 | isJSBook: false, 36 | // 静态公有方法 37 | display: function() {} 38 | }; 39 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.2.3闭包的实现_2.js: -------------------------------------------------------------------------------- 1 | /** 在闭包外部添加原型属性和方法看上去像似脱离了闭包这个类,所以在有时候在闭包内部实现一个完整的类然后将其返回 */ 2 | var Book = (function() { 3 | // 静态私有变量 4 | var bookNum = 0; 5 | // 静态私有方法 6 | function checkBook(name) {} 7 | // 创建类 8 | function _book(newId, newName, newPrice) { 9 | // 私有变量 10 | var name, price; 11 | // 私有方法 12 | function checkID(id) {} 13 | // 特权方法 14 | this.getName = function() {}; 15 | this.getPrice = function() {}; 16 | this.setName = function() {}; 17 | this.setPrice = function() {}; 18 | // 公有属性 19 | this.id = newId; 20 | // 公有方法 21 | this.copy = function() {}; 22 | bookNum++; 23 | if (bookNum > 100) { 24 | throw new Error("我们仅出版100本书。"); 25 | } 26 | // 构造器 27 | this.setName(name); 28 | this.setPrice(price); 29 | } 30 | // 构造原型 31 | _book.prototype = { 32 | // 静态公有属性 33 | isJSBook: false, 34 | display: function() {} 35 | }; 36 | })(); 37 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.2.4创建对象的安全模式.js: -------------------------------------------------------------------------------- 1 | /** 在JavaScript创建对象时有一种安全模式就可以安全解决忘记使用new关键字而引发的错误 */ 2 | /** 反面示例 */ 3 | var Book = function(title, time, type) { 4 | this.title = title; 5 | this.time = time; 6 | this.type = type; 7 | }; 8 | 9 | // 实例化一本书 10 | var book = Book("JavaScript", "2014", "js"); 11 | console.log(book); // undefined 12 | console.log(window.title); // JavaScript 13 | console.log(window.time); // 2014 14 | console.log(window.type); // js 15 | 16 | /** 图书安全类 */ 17 | var Book = function(title, time, type) { 18 | // 判断执行过程中this是否是当前这个对象(如果是用new创建的) 19 | if (this instanceof Book) { 20 | this.title = title; 21 | this.time = time; 22 | this.type = type; 23 | } else { 24 | // 否则重新创建这个对象 25 | return new Book(title, time, type); 26 | } 27 | }; 28 | 29 | var book = Book("javaScript", "2014", "js"); 30 | 31 | // 测试 32 | console.log(book); // Book 33 | console.log(book.title); // JavaScript 34 | console.log(book.time); // 2014 35 | console.log(book.type); // js 36 | console.log(window.title); // undefined 37 | console.log(window.type); // undefined 38 | console.log(window.time); // undefined 39 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.1类式继承_1.js: -------------------------------------------------------------------------------- 1 | /** 类式继承 */ 2 | // 声明父类 3 | function SuperClass() { 4 | this.superValue = true; 5 | } 6 | // 为父类添加公有方法 7 | SuperClass.prototype.getSuperValue = function() { 8 | return this.superValue; 9 | }; 10 | // 声明子类 11 | function SubClass() { 12 | this.SubValue = false; 13 | } 14 | 15 | // 继承父类 16 | SubClass.prototype = new SuperClass(); 17 | // 为子类添加公有方法 18 | SubClass.prototype.getSubValue = function() { 19 | return this.SubValue; 20 | }; 21 | 22 | var instance = new SubClass(); 23 | console.log(instance.getSuperValue()); // true 24 | console.log(instance.getSubValue()); // false 25 | 26 | console.log(instance instanceof SuperClass); // true 27 | console.log(instance instanceof SubClass); // true 28 | console.log(SubClass instanceof SuperClass); // false 29 | console.log(SubClass.prototype instanceof SuperClass); // true 30 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.1类式继承_2.js: -------------------------------------------------------------------------------- 1 | /** 这种类式继承有两个缺点。其一,由于子类听过其原型prototype对父类实例化,继承了父类。所以说父类中的公有属性要是有引用属性。就会在子类中被所有实例共用,因此一个子类的实例更改子类原型从父类构造函数继承来的共有属性就会直接影响到其他子类 */ 2 | 3 | function SuperClass() { 4 | this.books = ["JavaScript", "html", "css"]; 5 | } 6 | 7 | function SubClass() {} 8 | SubClass.prototype = new SuperClass(); 9 | var instance1 = new SubClass(); 10 | var instance2 = new SubClass(); 11 | console.log(instance2.books); // ["JavaScript", "html", "css"] 12 | instance1.books.push("设计模式"); 13 | console.log(instance2.books); // ["JavaScript", "html", "css", "设计模式"] 14 | 15 | /** 其二,由于子类实现的的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类的时候也无法对父类构造函数内的属性进行初始化 */ 16 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.2构造函数继承.js: -------------------------------------------------------------------------------- 1 | /** 构造函数式继承 */ 2 | // 声明父类 3 | function SuperClass(id) { 4 | // 引用类型公有属性 5 | this.books = ["JavaScript", "html", "css"]; 6 | // 值类型公有属性 7 | this.id = id; 8 | } 9 | 10 | // 父类声明原型方法 11 | SuperClass.prototype.showBooks = function() { 12 | console.log(this.books); 13 | }; 14 | 15 | // 声明子类 16 | function SubClass(id) { 17 | // 继承父类 18 | SuperClass.call(this, id); 19 | } 20 | 21 | // 创建第一个子类的示例 22 | var instance1 = new SubClass(10); 23 | var instance2 = new SubClass(11); 24 | 25 | instance1.books.push("设计模式"); 26 | console.log(instance1.books); // ["JavaScript", "html", "css", "设计模式"]; 27 | console.log(instance1.id); // 10 28 | console.log(instance2.books); // ["JavaScript", "html", "css"] 29 | console.log(instance2.id); // 11 30 | 31 | instance1.showBooks(); // TypeError 32 | 33 | /** 由于这类继承没有涉及原型prototype,所以父类的原型的方法自然不会被子类继承。 */ 34 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.3组合继承.js: -------------------------------------------------------------------------------- 1 | /** 类式继承是通过子类的原型prototype对父类实例化来实现的,构造函数式继承是通过在子类的构造函数作用环境中执行一次父类的构造函数来实现的,组合继承只要同时做到两点即可 */ 2 | 3 | /** 组合式继承 */ 4 | // 声明父类 5 | function SuperClass() { 6 | // 值类型公有属性 7 | this.name = name; 8 | // 引用类型公有属性 9 | this.books = ["html", "css", "JavaScript"]; 10 | } 11 | 12 | // 父类原型公有方法 13 | SuperClass.prototype.getName = function() { 14 | console.log(this.name); 15 | }; 16 | 17 | // 声明子类 18 | function SubClass(name, time) { 19 | // 构造函数式继承父类属性 20 | SuperClass.call(this, name); 21 | // 子类中新增公有属性 22 | this.time = time; 23 | } 24 | 25 | // 类式继承 子类原型继承父类 26 | SubClass.prototype = new SuperClass(); 27 | // 子类原型方法 28 | SubClass.prototype.getTime = function() { 29 | console.log(this.time); 30 | }; 31 | 32 | // 测试 33 | var instance1 = new SubClass("js book", 2014); 34 | instance1.books.push("设计模式"); 35 | console.log(instance1.books); // ["html", "css", "JavaScript", "设计模式"] 36 | instance1.getName(); // js book; 37 | instance1.getTime(); // 2014 38 | 39 | var instance2 = new SubClass("css book", 2013); 40 | console.log(instance2.books); // ["html", "css", "JavaScript"] 41 | instance1.getName(); // css book; 42 | instance1.getTime(); // 2013 43 | 44 | /** 这种继承方式在使用构造函数继承时执行了一遍父类的构造函数,而在实现子类原型的类式继承时又调用了一遍父类构造函数,因此父类构造函数调用了两遍,所以这种继承方式并不是最完美的方式 */ 45 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.4原型式继承.js: -------------------------------------------------------------------------------- 1 | /** 原型式继承 */ 2 | function inheritObject(o) { 3 | // 声明一个过渡函数对象 4 | function F() {} 5 | // 过渡对象的原型继承符对象 6 | F.prototype = o; 7 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 8 | return new F(); 9 | } 10 | 11 | // 测试用例 12 | var book = { 13 | name: "js book", 14 | alikeBook: ["css book", "html book"] 15 | }; 16 | 17 | var newBook = inheritObject(book); 18 | newBook.name = "ajax book"; 19 | newBook.alikeBook.push("xml book"); 20 | 21 | var otherBook = inheritObject(book); 22 | otherBook.name = "flash book"; 23 | otherBook.alikeBook.push("as book"); 24 | 25 | console.log(newBook.name); // ajax book 26 | console.log(newBook.alikeBook); // ["css book", "html book", "xml book", "as book"] 27 | console.log(otherBook.name); // flash book 28 | console.log(otherBook.alikeBook); // ["css book", "html book", "xml book", "as book"] 29 | console.log(book.name); // js book 30 | console.log(book.alikeBook); // ["css book", "html book", "xml book", "as book"] 31 | 32 | /** 跟类式继承一样,引用类型的属性被共用 */ 33 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.5寄生式继承.js: -------------------------------------------------------------------------------- 1 | /** 寄生式继承 */ 2 | 3 | function inheritObject(o) { 4 | // 声明一个过渡函数对象 5 | function F() {} 6 | // 过渡对象的原型继承父对象 7 | F.prototype = o; 8 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 9 | return new F(); 10 | } 11 | 12 | // 声明基对象 13 | var book = { 14 | name: "js book", 15 | alikeBook: ["css book", "html book"] 16 | }; 17 | 18 | function createBook(obj) { 19 | // 通过原型继承方式创建新对象 20 | var o = new inheritObject(obj); 21 | // 拓展新对象 22 | o.getName = function(){ 23 | console.log(name); 24 | }; 25 | // 返回拓展后的新对象 26 | return o; 27 | } 28 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.3.6寄生组合式继承.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 寄生式继承 继承原型 3 | * 传递参数 subClass 子类 4 | * 传递参数 superClass 父类 5 | **/ 6 | 7 | function inheritObject(o) { 8 | // 声明一个过渡函数对象 9 | function F() {} 10 | // 过渡对象的原型继承父对象 11 | F.prototype = o; 12 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 13 | return new F(); 14 | } 15 | 16 | function inheritPrototype(subClass, superClass) { 17 | // 复制一份父类的原型保存在变量中 18 | var p = inheritObject(superClass.prototype); 19 | p.constructor = subClass; 20 | subClass.prototype = p; 21 | } 22 | 23 | /** 测试用例 */ 24 | // 定义父类 25 | function SuperClass(name) { 26 | this.name = name; 27 | this.colors = ["red", "blue", "green"]; 28 | } 29 | 30 | //定义父类原型方法 31 | SuperClass.prototype.getName = function() { 32 | console.log(this.name); 33 | }; 34 | 35 | // 定义子类 36 | function SubClass(name, time) { 37 | // 构造函数式继承 38 | SuperClass.call(this,name); 39 | // 子类增强属性 40 | this.time = time; 41 | } 42 | 43 | // 寄生式继承父类原型 44 | inheritPrototype(SubClass,SuperClass); 45 | // 子类新增原型方法 46 | SubClass.prototype.getTime = function(){ 47 | console.log(this.time); 48 | }; 49 | // 创建两个测试方法 50 | var instance1 = new SubClass("js book", 2014); 51 | var instance2 = new SubClass("css book", 2013); 52 | 53 | instance1.colors.push("black"); 54 | console.log(instance1.colors); // ["red", "blue", "green", "black"] 55 | console.log(instance2.colors); // ["red", "blue", "green"] 56 | instance2.getName(); // css book 57 | instance2.getTime(); // 2013 58 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.4.1单继承.js: -------------------------------------------------------------------------------- 1 | /** 单继承 属性复制 */ 2 | var extend = function(target, source) { 3 | for (var property in source) { 4 | // 将对象中的属性复制到目标对象中 5 | target[property] = source[property]; 6 | } 7 | // 返回目标对象 8 | return target; 9 | }; 10 | 11 | // 测试用例 12 | var book = { 13 | name: "JavaScript设计模式", 14 | alike: ["css", "html", "JavaScript"] 15 | }; 16 | var anotherBook = { 17 | color: "blue" 18 | }; 19 | extend(anotherBook, book); 20 | console.log(anotherBook.name); // JavaScript设计模式 21 | console.log(anotherBook.alike); // ["css", "html", "JavaScript"] 22 | 23 | anotherBook.alike.push("ajax"); 24 | anotherBook.name = "设计模式"; 25 | console.log(anotherBook.name); // 设计模式 26 | console.log(anotherBook.alike); // ["css", "html", "JavaScript", "ajax"] 27 | console.log(book.name); // JavaScript设计模式 28 | console.log(book.alike); // ["css", "html", "JavaScript", "ajax"] 29 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.4.2多继承.js: -------------------------------------------------------------------------------- 1 | /** 多继承 属性复制 */ 2 | var mix = function() { 3 | var i = 1, // 从第二个参数开始为被继承的对象 4 | leng = arguments.length, // 获取参数长度 5 | target = arguments[0], // 第一个参数为目标对象 6 | arg; // 缓存参数对象 7 | // 遍历被继承的对象 8 | for (; i < len; i++) { 9 | // 缓存当前对象 10 | arg = arguments[i]; 11 | // 遍历被继承对象中的属性 12 | for (var variable in arg) { 13 | // 将被继承对象中的属性复制到目标对象中 14 | target[variable] = arg[variable]; 15 | } 16 | } 17 | 18 | // 返回目标对象 19 | return target; 20 | }; 21 | 22 | /** mix方法的作用就是将传入的多个对象的属性复制到源对象中,这样既可实现多个对象的属性的继承 */ 23 | /** 也可以将他绑定到原生对象Object上,这样所有的对象就可以拥有这个方法了 */ 24 | 25 | Object.prototype.mix = function() { 26 | var i = 0, 27 | len = arguments.length, 28 | arg; 29 | // 遍历被继承的对象 30 | for (; i < len; i++) { 31 | // 缓存当前对象 32 | arg = arguments[i]; 33 | // 遍历被继承对象中的属性 34 | for (var variable in object) { 35 | // 将被继承对象中的属性复制到目标对象中 36 | this[variable] = arg[variable]; 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.5多态_1.js: -------------------------------------------------------------------------------- 1 | /** 多态:同一个方法多种调用方式 */ 2 | 3 | function add() { 4 | // 获取参数 5 | var arg = arguments, 6 | len = arg.length; 7 | switch (len) { 8 | // 如果没有参数 9 | case 0: 10 | return 10; 11 | case 1: 12 | return 10 + arg[0]; 13 | case 2: 14 | return arg[0] + arg[1]; 15 | } 16 | } 17 | 18 | // 测试用例 19 | console.log(add()); // 10 20 | console.log(add(5)); // 15 21 | console.log(add(6, 7)); // 13 22 | -------------------------------------------------------------------------------- /1-面向对象编程/chapter_02面向对象编程/2.5多态_2.js: -------------------------------------------------------------------------------- 1 | /** 也可以将多态转化为更易懂的类形式 */ 2 | function Add() { 3 | // 无参数算法 4 | function zero() { 5 | return 10; 6 | } 7 | // 一个参数算法 8 | function one(num) { 9 | return num + 10; 10 | } 11 | // 两个参数算法 12 | function two(num1, num2) { 13 | return num1 + num2; 14 | } 15 | // 相加公有方法 16 | this.add = function() { 17 | var arg = arguments, 18 | len = arg.length; 19 | switch (len) { 20 | // 如果没有参数 21 | case 0: 22 | return zero(); 23 | case 1: 24 | return one(arg[0]); 25 | case 2: 26 | return two(arg[0], arg[1]); 27 | } 28 | }; 29 | } 30 | 31 | // 实例化类 32 | var A = new Add(); 33 | // 测试 34 | console.log(A.add()); // 10 35 | console.log(A.add(5)); // 15 36 | console.log(A.add(6, 7)); // 13 37 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_03简单工厂模式/3.1工作中的第一次需求.js: -------------------------------------------------------------------------------- 1 | /** 简单工厂模式,又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象 */ 2 | 3 | // 反面案例 4 | // 用户名输入警示框 5 | var LoginAlert = function(text) { 6 | this.content = text; 7 | }; 8 | LoginAlert.prototype.show = function() { 9 | // 显示警示框 10 | }; 11 | var userNameAlert = new LoginAlert(); 12 | userNameAlert.show(); 13 | 14 | // 在输入密码功能中也调用警示框类 15 | var passwordAlert = new LoginAlert(); 16 | passwordAlert.show(); 17 | 18 | /** 在警示框中添加一个按钮 */ 19 | // 重新创建一个类 20 | var loginConfirm = function(text) { 21 | this.content = text; 22 | }; 23 | loginConfirm.prototype.show = function() { 24 | // 显示确认框 25 | }; 26 | var loginFailConfirm = new loginConfirm("您的用户名不存在,请重新输入"); 27 | loginFailConfirm.show(); 28 | 29 | /** 在警示框中添加输入框 */ 30 | // 重新创建一个类 31 | var LoginPrompt = function(text) { 32 | this.content = text; 33 | }; 34 | LoginPrompt.prototype.show = function() { 35 | // 显示提示框 36 | }; 37 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_03简单工厂模式/3.2如果类太多,那么提供一个.js: -------------------------------------------------------------------------------- 1 | /** 简单工厂模式 */ 2 | 3 | // 篮球基类 4 | var Basketball = function() { 5 | this.intro = "篮球盛行于美国。"; 6 | }; 7 | Basketball.prototype = { 8 | getMember: function() { 9 | console.log("每个队伍中需要5名队员。"); 10 | }, 11 | getBallSize: function() { 12 | console.log("篮球很大。"); 13 | } 14 | }; 15 | 16 | // 足球基类 17 | var Football = function() { 18 | this.intro = "足球在世界范围内很流行。"; 19 | }; 20 | Football.prototype = { 21 | getMember: function() { 22 | console.log("每个队伍需要11名队员。"); 23 | }, 24 | getBallSize: function() { 25 | console.log("足球很大"); 26 | } 27 | }; 28 | 29 | // 网球基类 30 | var Tennis = function() { 31 | this.intro = "每年有很多网球系列赛。"; 32 | }; 33 | Tennis.prototype = { 34 | geMember: function() { 35 | console.log("每个队伍需要一名队员"); 36 | }, 37 | getBallSize: function() { 38 | console.log("网球很小。"); 39 | } 40 | }; 41 | 42 | // 运动工厂 43 | var SportsFactory = function(name) { 44 | switch (name) { 45 | case "NBA": 46 | return new Basketball(); 47 | case "wordCup": 48 | return new Football(); 49 | case "FrenchOpen": 50 | return new Tennis(); 51 | } 52 | }; 53 | 54 | // 调用:创建一个足球 55 | var football = SportsFactory("wordCup"); 56 | console.log(football); 57 | console.log(football.intro); 58 | football.getMember(); 59 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_03简单工厂模式/3.3一个对象有时候也可代替许多类_1.js: -------------------------------------------------------------------------------- 1 | /** 工厂模式 */ 2 | 3 | function createBook(name, time, type) { 4 | // 创建一个对象,并对对象拓展属性和方法 5 | var o = {}; 6 | o.name = name; 7 | o.type = type; 8 | o.time = time; 9 | o.getName = function() { 10 | console.log(this.name); 11 | }; 12 | // 将对象返回 13 | return o; 14 | } 15 | 16 | var book1 = createBook("js book", 2014, "js"); 17 | var book2 = createBook("css book", 2013, "css"); 18 | 19 | book1.getName(); 20 | book2.getName(); 21 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_03简单工厂模式/3.3使用工厂模式改进需求_2.js: -------------------------------------------------------------------------------- 1 | function createPop(type, text) { 2 | // 创建一个对象,并对对象拓展属性和方法 3 | var o = {}; 4 | o.content = text; 5 | o.show = function() { 6 | // 显示方法 7 | }; 8 | if (type == "alert") { 9 | // 警示框差异部分 10 | } 11 | if (type == "prompt") { 12 | // 提示框差异部分 13 | } 14 | if (type == "confirm") { 15 | // 确认框差异部分 16 | } 17 | // 将对象返回 18 | return o; 19 | } 20 | // 创建警示框 21 | var userNameAlert = createPop("alert", "用户名只能是26个字母和数字"); 22 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_03简单工厂模式/README.md: -------------------------------------------------------------------------------- 1 | ###简单工厂模式 2 | 又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用来创建同一类对象。 3 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_04工厂方法模式/4.1广告展现.js: -------------------------------------------------------------------------------- 1 | /** 工厂方法模式:通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例 */ 2 | 3 | /** 反面示例 */ 4 | // 创建Java学科类 5 | var Java = function(content) { 6 | // 将内容保存在content里面以备以后使用 7 | this.content = content; 8 | // 创建对象时,通过闭包,直接执行,将内容按需求的样式插入到页面内 9 | (function(content) { 10 | var div = document.createElement("div"); 11 | div.innerHTML = content; 12 | div.style.color = "green"; 13 | document.getElementById('container').appendChild(div); 14 | })(content); 15 | }; 16 | 17 | // 创建PHP学科类 18 | var Php = function(content) { 19 | this.content = content; 20 | (function(content) { 21 | var div = document.createElement("div"); 22 | div.innerHTML = content; 23 | div.style.color = "yellow"; 24 | document.getElementById('container').appendChild(div); 25 | })(content); 26 | }; 27 | 28 | // 创建JavaScript学科类 29 | var JavaScript = function(content) { 30 | this.content = content; 31 | (function(content) { 32 | var div = document.createElement("div"); 33 | div.innerHTML = content; 34 | div.style.color = "pink"; 35 | document.getElementById('container').appendChild(div); 36 | })(content); 37 | }; 38 | 39 | // 学科类工厂 40 | function JobFactory(type, content) { 41 | switch (type) { 42 | case "java": 43 | return new Java(content); 44 | case "php": 45 | return new Php(content); 46 | case "JavaScript": 47 | return new JavaScript(content); 48 | } 49 | } 50 | 51 | // 测试 52 | JobFactory("JavaScript", "JavaScript哪家强"); 53 | 54 | /** 如果此时需求追加在添加一个UI学科,再使用简单工厂模式,便不利于扩展 */ 55 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_04工厂方法模式/4.3安全模式类.js: -------------------------------------------------------------------------------- 1 | /** 使用安全模式类可以屏蔽创建类的实例时,忽略使用new关键字造成的错误 */ 2 | 3 | var Demo = function() {}; 4 | Demo.prototype = { 5 | show: function() { 6 | console.log("成功获取!"); 7 | } 8 | }; 9 | 10 | var d = new Demo(); 11 | d.show(); // 成功获取! 12 | var t = Demo(); 13 | t.show(); // Uncaught TypeError: Cannot read property 'show' of undefined 14 | 15 | /** 安全模式类 */ 16 | var Demo = function() { 17 | if (!(this instanceof Demo)) { 18 | return new Demo(); 19 | } 20 | }; 21 | 22 | var d = Demo(); 23 | d.show(); // 成功获取! 24 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_04工厂方法模式/4.4安全的工厂方法.js: -------------------------------------------------------------------------------- 1 | // 安全模式创建的工厂类 2 | var Factory = function(type, content) { 3 | if (this instanceof Factory) { 4 | var s = new this[type](content); 5 | return s; 6 | } else { 7 | return new Factory(type, content); 8 | } 9 | }; 10 | 11 | // 工厂原型中设置创建所有类型数据对象的基类 12 | Factory.prototype = { 13 | Java: function(content) { 14 | // 将内容保存在content里面以备以后使用 15 | this.content = content; 16 | // 创建对象时,通过闭包,直接执行,将内容按需求的样式插入到页面内 17 | (function(content) { 18 | var div = document.createElement("div"); 19 | div.innerHTML = content; 20 | div.style.color = "green"; 21 | document.getElementById('container').appendChild(div); 22 | })(content); 23 | }, 24 | Php: function(content) { 25 | this.content = content; 26 | (function(content) { 27 | var div = document.createElement("div"); 28 | div.innerHTML = content; 29 | div.style.color = "yellow"; 30 | document.getElementById('container').appendChild(div); 31 | })(content); 32 | }, 33 | JavaScript: function(content) { 34 | this.content = content; 35 | (function(content) { 36 | var div = document.createElement("div"); 37 | div.innerHTML = content; 38 | div.style.color = "pink"; 39 | document.getElementById('container').appendChild(div); 40 | })(content); 41 | } 42 | }; 43 | 44 | var data = [{ 45 | type: "JavaScript", 46 | content: "JavaScript哪家强" 47 | }, { 48 | type: "Java", 49 | content: "Java哪家强" 50 | }, { 51 | type: "Php", 52 | content: "php哪家强" 53 | }, { 54 | type: "Php", 55 | content: "UI哪家强" 56 | }, { 57 | type: "Java", 58 | content: "UI哪家强" 59 | }, { 60 | type: "JavaScript", 61 | content: "JavaScript哪家强" 62 | }, { 63 | type: "JavaScript", 64 | content: "JavaScript哪家强" 65 | }]; 66 | 67 | for (var i = 0; i < data.length; i++) { 68 | Factory(data[i].type, data[i].content); 69 | } 70 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_05抽象工厂模式/5.1抽象类: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jixianu/JS-design-patterns/8ce5a0d5d40fb35242a13a5d2361fcb3062435bf/2-创建型设计模式/chapter_05抽象工厂模式/5.1抽象类 -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_05抽象工厂模式/5.2抽象工厂模式.js: -------------------------------------------------------------------------------- 1 | /** 抽象工厂方法 */ 2 | 3 | var VehicleFactory = function(subType, superType) { 4 | // 判断抽象工厂中是否有该抽象类 5 | if (typeof VehicleFactory[superType] === "function") { 6 | // 缓存类 7 | var F = function() {}; 8 | // 继承父类属性和方法 9 | F.prototype = new VehicleFactory[superType](); 10 | // 将子类 constructor 指向子类 11 | subType.constructor = subType; 12 | // 子类原型继承“父类” 13 | subType.prototype = new F(); 14 | } else { 15 | // 不存在该抽象类抛出错误 16 | throw new Error("未创建该抽象类"); 17 | } 18 | }; 19 | 20 | // 小汽车抽象类 21 | VehicleFactory.Car = function() { 22 | this.type = "car"; 23 | }; 24 | VehicleFactory.Car.prototype = { 25 | getPrice: function() { 26 | return new Error("抽象方法不能调用"); 27 | }, 28 | getSpeed: function() { 29 | return new Error("抽象方法不能调用"); 30 | } 31 | }; 32 | 33 | // 公交车抽象类 34 | VehicleFactory.Bus = function() { 35 | this.type = "bus"; 36 | }; 37 | VehicleFactory.Bus.prototype = { 38 | getPrice: function() { 39 | return new Error("抽象方法不能调用"); 40 | }, 41 | getPassengerNum: function() { 42 | return new Error("抽象方法不能调用"); 43 | } 44 | }; 45 | 46 | // 货车抽象类 47 | VehicleFactory.Truck = function() { 48 | this.type = "truck"; 49 | }; 50 | VehicleFactory.Truck.prototype = { 51 | getPrice: function() { 52 | return new Error("抽象方法不能调用"); 53 | }, 54 | getTrainload: function() { 55 | return new Error("抽象方法不能调用"); 56 | } 57 | }; 58 | 59 | /** 抽象与实现 */ 60 | 61 | // 宝马汽车子类 62 | var BMG = function(price, speed) { 63 | this.price = price; 64 | this.speed = speed; 65 | }; 66 | 67 | // 抽象工厂实现对Car抽象类的继承 68 | VehicleFactory(BMG, "Car"); 69 | BMG.prototype.getPrice = function() { 70 | return this.price; 71 | }; 72 | BMG.prototype.getSpeed = function() { 73 | return this.speed; 74 | }; 75 | 76 | // 兰博基尼汽车子类 77 | var Lamborghini = function(price, speed) { 78 | this.price = price; 79 | this.speed = speed; 80 | }; 81 | // 抽象工厂实现对Car抽象类的继承 82 | VehicleFactory(Lamborghini, "Car"); 83 | Lamborghini.prototype.getPrice = function() { 84 | return this.price; 85 | }; 86 | Lamborghini.prototype.getSpeed = function() { 87 | return this.speed; 88 | }; 89 | 90 | // 宇通汽车类 91 | var YUTONG = function(price, passenger) { 92 | this.price = price; 93 | this.passenger = passenger; 94 | }; 95 | VehicleFactory(YUTONG, "Bus"); 96 | YUTONG.prototype.getPrice = function() { 97 | return this.price; 98 | }; 99 | YUTONG.prototype.getPassengerNum = function() { 100 | return this.getPassengerNum(); 101 | }; 102 | 103 | // 奔驰汽车子类 104 | var BenzTruck = function(price, trainLoad) { 105 | this.price = price; 106 | this.trainLoad = trainLoad; 107 | }; 108 | // 抽象工厂实现对Truck抽象类的继承 109 | VehicleFactory(BenzTruck, "Truck"); 110 | BenzTruck.prototype.getPrice = function() { 111 | return this.price; 112 | }; 113 | BenzTruck.prototype.getTrainload = function() { 114 | return this.trainLoad; 115 | }; 116 | 117 | /** 测试 */ 118 | 119 | var truck = new BenzTruck(1000000,1000); 120 | console.log(truck.getPrice()); // 1000000 121 | console.log(truck.getTrainload()); // 1000 122 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_05抽象工厂模式/README.md: -------------------------------------------------------------------------------- 1 | ###抽象工厂模式 2 | 通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类产品的实例。 3 | 抽象类中定义的方法只是显性的定义一些功能。但没有具体的实现,而一个对象是要具有一套完整的功能的,所以用抽象类穿件的对象当然也是“抽象”的了,所以我们不能使用它来创建一个真实的对象。 4 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_06建造者模式/6.2创建对象的另一种形式.js: -------------------------------------------------------------------------------- 1 | // 创建一位人类 2 | var Human = function(params) { 3 | // 技能 4 | this.skill = params && params.skill || "保密"; 5 | // 兴趣爱好 6 | this.hobby = params && params.hobby || "保密"; 7 | }; 8 | 9 | // 人类原型方法 10 | Human.prototype = { 11 | getSkill: function() { 12 | return this.skill; 13 | }, 14 | getHobby: function() { 15 | return this.hobby; 16 | } 17 | }; 18 | 19 | // 实例化姓名类 20 | var Named = function(name) { 21 | var that = this; 22 | // 构造器 23 | // 构造函数解析姓名的姓与名 24 | (function(name, that) { 25 | that.wholeName = name; 26 | if (name.indexOf(" ") > -1) { 27 | that.firstName = name.slice(0, name.indexOf(" ")); 28 | this.secondName = name.slice(name.indexOf(" ")); 29 | } 30 | })(name, that); 31 | }; 32 | 33 | // 实例化职位类 34 | var Work = function(work) { 35 | var that = this; 36 | // 构造器 37 | // 构造函数中通过传入的职位特征来设置相应的职位以及描述 38 | (function(work, that) { 39 | switch (work) { 40 | case "code": 41 | that.work = "工程师"; 42 | that.workDescript = "每天沉醉于编程"; 43 | break; 44 | case "UI": 45 | case "UE": 46 | that.work = "设计师"; 47 | that.workDescript = "设计更似一种艺术"; 48 | break; 49 | case "teach": 50 | that.work = "教师"; 51 | that.workDescript = "分享也是一种快乐"; 52 | break; 53 | default: 54 | that.work = work; 55 | that.workDescript = "对不起,我们现在还不清楚你所选择的职位的相关描述。"; 56 | } 57 | })(work, that); 58 | }; 59 | 60 | // 更换期望的职位 61 | Work.prototype.changeWork = function(work) { 62 | this.work = work; 63 | }; 64 | // 添加对职位的描述 65 | Work.prototype.changeDescript = function(setence) { 66 | this.workDescript = setence; 67 | }; 68 | 69 | /** 70 | * 应聘者建造者 71 | * 参数 name: 姓名(全名) 72 | * 参数 work: 期望职位 73 | **/ 74 | 75 | var Person = function(name, work) { 76 | // 创建应聘者缓存对象 77 | var _person = new Human(); 78 | // 创建应聘者姓名解析对象 79 | _person.name = new Named(name); 80 | // 将创建的应聘者期望职位 81 | _person.work = new Work(work); 82 | // 将创建的应聘者对象返回 83 | return _person; 84 | }; 85 | 86 | /** 测试用例 */ 87 | var person = new Person("xiao ming", "code"); 88 | console.log(person.skill); // 保密 89 | console.log(person.name.firstName); // xiao 90 | console.log(person.work.work); // 工程师 91 | console.log(person.work.workDescript); // 每一天在编程中度过 92 | person.work.changeDescript("更改一下职位描述!"); 93 | console.log(person.work.workDescript); // 更改一下职位描述! 94 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_06建造者模式/README.md: -------------------------------------------------------------------------------- 1 | ###建造者模式 2 | 将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示。 3 | 4 | ###建造者模式与工厂模式的区别 5 | 工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出(创建)的是什么。不关心你创建的整个过程,仅仅需要知道你最终创建的结果。所以通过工厂模式我们得到的都是对象实例或者族类。然而建造者模式在创建对象是要更为复杂一些,虽然其目的也是为了创建对象,但是他更多关心的是穿件这个对象的整个过程,甚至于创建对象的每一个细节。 6 | 7 | 以前工厂模式创建出来的是一个对象,他追求的是创建的结果,别无他求,所以那仅仅是一个实实在在的创建过程,而建造者模式就有所不同,他不仅仅可以得到创建的结果,而且也参与了创建的具体过程,对于创建的具体实现的细节也参与了干涉,所以说创建的对象更复杂,或者说这种模式创建的对象是一个复合对象。 8 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_07原型模式/7.2创建一个焦点图.js: -------------------------------------------------------------------------------- 1 | // 图片轮播类 2 | var LoopImages = function(imgArr, container) { 3 | this.imagesArray = imgArr; // 轮播图片数组 4 | this.container = container; // 轮播图片容器 5 | this.createImage = function() {}; // 创建轮播图片 6 | this.changeImage = function() {}; // 切换下一张图片 7 | }; 8 | 9 | // 上下滑动切换类 10 | var SliderLoopImg = function(imgArr, container) { 11 | // 构造函数继承图片轮播类 12 | LoopImages.call(this, imgArr, container); 13 | // 重写继承的“切换下一张图片”方法 14 | this.changeImage = function() { 15 | console.log("SliderLoopImg changeImage function"); 16 | }; 17 | }; 18 | 19 | // 渐隐切换类 20 | var FadeLoopImg = function(imgArr, container, arrow) { 21 | LoopImages.call(this, imgArr, container); 22 | this.arrow = arrow; 23 | this.changeImage = function() { 24 | console.log("FadeLoopImg changeImage function"); 25 | }; 26 | }; 27 | 28 | /** 测试用例 */ 29 | // 实例化一个渐隐切换图片类 30 | var fadeImg = new FadeLoopImg(["001.jpg", "002.jpg", "003.jpg"], "slide", ["left.jpg", "right.jpg"]); 31 | 32 | fadeImg.changeImage(); // FadeLoopImg changeImage function 33 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_07原型模式/7.3最优的解决方案.js: -------------------------------------------------------------------------------- 1 | // 图片轮播类 2 | var LoopImages = function(imgArr, container) { 3 | this.imagesArray = imgArr; 4 | this.container = container; 5 | }; 6 | 7 | LoopImages.prototype = { 8 | // 创建轮播图片 9 | createImage: function() { 10 | console.log("LoopImages createImage function"); 11 | }, 12 | // 切换下一张图片 13 | changeImage: function() { 14 | console.log("LoopImages changeImage function"); 15 | } 16 | }; 17 | 18 | // 上下滑动切换类 19 | var SliderLoopImg = function(imgArr, container) { 20 | // 构造函数继承图片轮播类 21 | LoopImages.call(this, imgArr, container); 22 | }; 23 | SliderLoopImg.prototype = new LoopImages(); 24 | // 重写继承的“切换下一张图片”方法 25 | SliderLoopImg.prototype.changeImage = function() { 26 | console.log("SliderLoopImg changeImage function"); 27 | }; 28 | 29 | // 渐隐切换类 30 | var FadeLoopImg = function(imgArr, container, arrow) { 31 | LoopImages.call(this, imgArr, container); 32 | // 切换箭头私有变量 33 | this.arrow = arrow; 34 | }; 35 | FadeLoopImg.prototype = new LoopImages(); 36 | FadeLoopImg.prototype.changeImage = function() { 37 | console.log("FadeLoopImg changeImage function"); 38 | }; 39 | LoopImages.prototype.getImageLength = function() { 40 | return this.imagesArray.length; 41 | }; 42 | FadeLoopImg.prototype.getContainer = function(){ 43 | return this.container; 44 | }; 45 | /** 测试用例 */ 46 | var fadeImg = new FadeLoopImg(["001.jpg", "002.jpg", "003.jpg"], "slide", ["left.jpg", "right.jpg"]); 47 | console.log(fadeImg.container); // slide 48 | fadeImg.changeImage(); // FadeLoopImg changeImage function 49 | console.log(fadeImg.getImageLength()); // 3 50 | console.log(fadeImg.getContainer()); // slide 51 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_07原型模式/7.5原型继承.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于已经存在的模板对象克隆出新对象的模式 3 | * arguments[0],arguments[1],arguments[2]:参数1,参数2,参数3 表示模板对象 4 | * 注意。这里对模板引用类型的属性实际上进行了浅复制(引用类型属性共享),当然根据需求也可以进行深复制(引用类型属性赋值) 5 | **/ 6 | 7 | function prototypeExtend() { 8 | var F = function() {}, // 缓存类,为实例化返回对象临时创建 9 | args = arguments, 10 | i = 0, 11 | len = args.length; 12 | for (; i < len; i++) { 13 | // 遍历每个模板对象中的属性 14 | for (var j in args[i]) { 15 | // 将这些属性复制到缓存类原型中 16 | F.prototype[j] = args[i][j]; 17 | } 18 | } 19 | // 返回缓存类的一个实例 20 | return new F(); 21 | } 22 | 23 | var penguin = prototypeExtend({ 24 | speed: 20, 25 | swim: function() { 26 | console.log("游泳速度 " + this.speed); 27 | } 28 | }, { 29 | run: function(speed) { 30 | console.log("奔跑速度 " + speed); 31 | } 32 | }, { 33 | jump: function() { 34 | console.log("跳跃动作"); 35 | } 36 | }); 37 | 38 | penguin.swim(); 39 | penguin.run(10); 40 | penguin.jump(); 41 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_07原型模式/README.md: -------------------------------------------------------------------------------- 1 | ###原型模式 2 | 用原型实例指向创建对象的类,适用于创建新的对象的类共享原型对象的属性基方法。 3 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_08单例模式/8.5无法修改的静态变量.js: -------------------------------------------------------------------------------- 1 | var Conf = (function() { 2 | // 私有变量 3 | var conf = { 4 | MAX_NUM: 100, 5 | MIN_NUM: 1, 6 | COUNT: 1000 7 | }; 8 | // 返回取值器对象 9 | return { 10 | // 取值器方法 11 | get: function(name){ 12 | return conf[name] ? conf[name] : null; 13 | } 14 | }; 15 | })(); 16 | 17 | var count = Conf.get("COUNT"); 18 | console.log(count); // 1000 19 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_08单例模式/8.6惰性单例.js: -------------------------------------------------------------------------------- 1 | /** 有时候对于单例对象需要延迟创建,所以在单例中还存在一种延迟创建的形式,有人也称之为“惰性单例” */ 2 | 3 | // 惰性单例模式 4 | var LarySingle = (function() { 5 | // 单例实例引用 6 | var _instance = null; 7 | // 单例 8 | function Single() { 9 | // 这里定义私有属性和方法 10 | return { 11 | publicMethod: function() {}, 12 | publicProperty: "1.0" 13 | }; 14 | } 15 | // 获取单例对象接口 16 | return function() { 17 | // 如果未创建单例将创建单例 18 | if(!_instance){ 19 | _instance = Single(); 20 | } 21 | // 返回单例 22 | return _instance; 23 | }; 24 | })(); 25 | -------------------------------------------------------------------------------- /2-创建型设计模式/chapter_08单例模式/README.md: -------------------------------------------------------------------------------- 1 | ###单例模式 2 | 又被称为单体模式,是只允许实例化一次的对象类。有时候我们也用一个对象来规划一个命名空间,并井井有条的管理对象的属性与方法。 3 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_09外观模式/9.2兼容方式.js: -------------------------------------------------------------------------------- 1 | /** 外观模式实现 */ 2 | 3 | function addEvent(dom, type, fn) { 4 | // 对于支持DOM2级事件处理程序addEventListener方法的浏览器 5 | if (dom.addEventListener) { 6 | dom.addEventListener(type, fn, false); 7 | } else if (dom.attachEvent) { 8 | // 对于不支持addEventListener方法但支持attchEvent方法的浏览器 9 | dom.attachEvent("on" + type, fn); 10 | } else { 11 | // 对于不支持addEventListener方法,也不支持attchEvent方法,但支持“on”+事件名的浏览器 12 | dom["on" + type] = fn; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_09外观模式/9.3除此之外.js: -------------------------------------------------------------------------------- 1 | // 获取事件对象 2 | var getEvent = function(evnet) { 3 | // 标准浏览器返回event,IE下window.event 4 | return event || window.event; 5 | }; 6 | 7 | // 获取元素 8 | var getTarget = function(event) { 9 | var event = getEvent(event); 10 | // 标准浏览器下 event.target,IE下event.srcElement 11 | return event.target || event.srcElement; 12 | }; 13 | 14 | // 组织默认行为 15 | var preventDefault = function(event) { 16 | var event = getEvent(event); 17 | // 标准浏览器 18 | if (event.preventDefault) { 19 | event.preventDefault(); 20 | } else { 21 | // IE浏览器 22 | event.returnValue = false; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_09外观模式/9.4小型代码库.js: -------------------------------------------------------------------------------- 1 | // 简约版属性样式库方法 2 | var A = { 3 | // 通过id获取元素 4 | g: function(id) { 5 | return document.getElementById(id); 6 | }, 7 | // 设置css属性 8 | css: function(id, key, value) { 9 | document.getElementById(id).style[key] = value; 10 | }, 11 | // 设置元素的属性 12 | attr: function(id, key, value) { 13 | document.getElementById(id)[key] = value; 14 | }, 15 | html: function(id, html) { 16 | document.getElementById(id).innerHTML = html; 17 | }, 18 | // 为元素绑定事件 19 | on: function(id, type, fn) { 20 | document.getElementById(id)["on" + type] = fn; 21 | } 22 | }; 23 | 24 | // 测试 25 | A.css("box", "background", "red"); // 设置css样式 26 | A.attr("box", "className", "box"); // 设置class 27 | A.html("box", "这是新添加的内容"); // 设置内容 28 | A.on("box", "click", function() { // 绑定事件 29 | A.css("box", "width", "500px"); 30 | }); 31 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_09外观模式/README.md: -------------------------------------------------------------------------------- 1 | ###外观模式 2 | 为一组复杂的子系统接口提够一个更高级的统一接口,通过这个接口是的对子系统接口的访问更容易,在JavaScript中有时候也会用于对底层接口兼容性做统一封装来简化用户使用。 3 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_10适配器模式/10.4适配异类框架.js: -------------------------------------------------------------------------------- 1 | // 定义框架 2 | var A = A || {}; 3 | // 通过ID获取元素 4 | A.g = function(id) { 5 | return document.getElementById(id); 6 | }; 7 | // 为元素绑定事件 8 | A.on = function(id, type, fn) { 9 | // 如果传递参数是字符串则以id处理,否则以元素对象处理 10 | var dom = typeof id === "string" ? this.g(id) : id; 11 | // 标准DOM2级添加事件方式 12 | if (dom.addEventListener) { 13 | dom.addEventListener(type, fn, false); 14 | } else if (dom.attachEvent) { 15 | dom.attachEvent("on" + type, fn); 16 | } else { 17 | // 简易添加事件方式 18 | dom["on" + type] = fn; 19 | } 20 | }; 21 | /** 测试 */ 22 | A.on(window, "load", function() { 23 | // 按钮点击事件 24 | A.on("mybutton", "click", function() { 25 | // do something; 26 | }); 27 | }); 28 | 29 | /** 应用适配器模式调用jquery */ 30 | A.g = function(id) { 31 | // 通过jQuery获取jQuery对象,然后返回第一个成员 32 | return $(id).get(0); 33 | }; 34 | 35 | A.on = function(id, type, fn) { 36 | // 如果传递参数是字符串则以id处理,否则以元素对象处理 37 | var dom = typeof id === "string" ? $("#" + id) : $(id); 38 | dom.on(type, fn); 39 | }; 40 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_10适配器模式/10.5参数适配器.js: -------------------------------------------------------------------------------- 1 | /** 应用适配器模式来为函数提供默认参数,以保证函数传参的完整性 */ 2 | function doSomeThing(obj) { 3 | var _adapter = { 4 | name: "雨夜清河", 5 | title: "设计模式", 6 | age: 24, 7 | color: "pink", 8 | size: 100, 9 | prize: 50 10 | }; 11 | for (var variable in _adapter) { 12 | _adapter[i] = obj[i] || _adapter[i]; 13 | } 14 | // 或者 extend(_adapter, obj) 注:此时可能会多添加属性 15 | // do things 16 | } 17 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_10适配器模式/10.6数据适配.js: -------------------------------------------------------------------------------- 1 | /** 应用适配器模式将数组转换为对象形式 */ 2 | 3 | var arr = ["JavaScript", "book", "前端编程语言", "8月1日"]; 4 | 5 | // 目标格式 6 | var obj = { 7 | name: "", 8 | type: "", 9 | title: "", 10 | time: "" 11 | }; 12 | 13 | function arrToObjAdapter(arr) { 14 | return { 15 | name: arr[0], 16 | type: arr[1], 17 | title: arr[2], 18 | time: arr[3] 19 | }; 20 | } 21 | 22 | var adapterData = arrToObjAdapter(arr); 23 | console.log(adapterData); // Object {name: "JavaScript", type: "book", title: "前端编程语言", time: "8月1日"} 24 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_10适配器模式/10.7服务器端数据适配.js: -------------------------------------------------------------------------------- 1 | /** 使用适配器模式将后端返回的数据格式化为理想的数据格式 */ 2 | 3 | // 理想的数据格式是一个一维数组 4 | function ajaxAdapter(data) { 5 | // 处理数据并返回新数据 6 | return [data["key1"], data["key2"], data["key3"]]; 7 | } 8 | 9 | $.ajax({ 10 | url: "someAdress.php", 11 | success: function(data, status) { 12 | if (data) { 13 | // 使用适配后的数据--返回的对象 14 | doSomething(ajaxAdapter(data)); 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_10适配器模式/README.md: -------------------------------------------------------------------------------- 1 | ###适配器模式 2 | 将一个类(对象)的接口(方法或者属性)转化成另一个接口,以满足用户的需求,使类(对象)之间接口的不兼容问题通过适配器得意解决。 3 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/11.3站长统计.js: -------------------------------------------------------------------------------- 1 | // 统计代理 2 | var Count = (function(){ 3 | // 缓存图片 4 | var img= new Image(); 5 | // 返回统计函数 6 | return function(param){ 7 | // 统计请求字符串 8 | var str = "http://www.count.com/a.gif?"; 9 | // 拼接请求字符串 10 | for(var i in param){ 11 | str += i + "=" + param[i]; 12 | } 13 | // 发送统计请求 14 | img.src = str; 15 | }; 16 | })(); 17 | 18 | // 测试用例:统计num 19 | Count({num: 10}); 20 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/11.4JSONP.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/11.5X域代理B页面.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 35 | 36 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/11.5X域被代理A页面.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 13 | 16 |
17 | 18 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/11.5Y域中被请求的文件接口.php: -------------------------------------------------------------------------------- 1 | //将从X域过来的请求的数据解析并获取回调函数字段与代理模板路径字段数据,并打包返回,并将自己的Header重定向为X域的代理模板B所在的路径 2 | 7 | /* 8 | 测试结果 9 | 控制台输出依次是 10 | 成功接收数据 success 11 | */ -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_11代理模式/README.md: -------------------------------------------------------------------------------- 1 | ###代理模式 2 | 由于一个对象不能直接饮用另一个对象,所以需要通过代理对象在这两个对象之间起到中介作用。 3 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_12装饰者模式/12.2装饰者模式.js: -------------------------------------------------------------------------------- 1 | // 装饰者 2 | var decorator = function(input, fn){ 3 | // 获取事件源 4 | var input = document.getElementById(input); 5 | // 若事件源已经绑定事件 6 | if (typeof input.onclick === 'function') { 7 | // 缓存事件源原有回调函数 8 | var oldClickFn = input.onclick; 9 | // 为事件源定义新的事件 10 | input.onclick = function () { 11 | // 事件源原有回调函数 12 | oldClickFn(); 13 | // 执行事件源新增回调函数 14 | fn(); 15 | } 16 | } else { 17 | // 事件源未绑定事件,直接为事件源添加新增回调函数 18 | input.onclick = fn; 19 | } 20 | // do other things 21 | }; 22 | 23 | //电话输入框功能装饰 24 | decorator('tel_input', function () { 25 | document.getElementById('tel_demo_text').style.display = 'none'; 26 | }); 27 | //姓名输入框功能装饰 28 | decorator('name_input', function () { 29 | document.getElementById('name_demo_text').style.display = 'none'; 30 | }); 31 | //地址输入框功能装饰 32 | decorator('address_input', function () { 33 | document.getElementById('address_demo_text').style.display = 'none'; 34 | }); 35 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_13桥接模式/13.3桥接模式.js: -------------------------------------------------------------------------------- 1 | // 多维变量类 2 | // 运动单元 3 | function Speed(x, y) { 4 | this.x = x; 5 | this.y = y; 6 | } 7 | Speed.prototype.run = function() { 8 | console.log( '运动起来' ); 9 | } 10 | 11 | // 着色单元 12 | function Color(cl) { 13 | this.color = cl; 14 | } 15 | Color.prototype.draw = function () { 16 | console.log( '绘制色彩' ); 17 | } 18 | 19 | // 变形单元 20 | function Shape(sp) { 21 | this.shape = sp; 22 | } 23 | Shape.prototype.change = function () { 24 | console.log( '改变形状' ); 25 | } 26 | 27 | // 说话单元 28 | function Speek(wd) { 29 | this.word = wd 30 | } 31 | Speek.prototype.say = function () { 32 | console.log( '书写字体' ); 33 | } 34 | 35 | // 球类 36 | function Ball(x, y, c) { 37 | this.speed = new Speed(x, y); 38 | this.color = new Color(c); 39 | } 40 | Ball.prototype.init = function () { 41 | // 实现运动 42 | this.speed.run(); 43 | // 实现着色 44 | this.color.draw(); 45 | } 46 | 47 | // 人类 48 | function People(x, y, f){ 49 | this.speed = new Speed(x, y); 50 | this.font = new Speek(f); 51 | } 52 | People.prototype.init = function () { 53 | this.speed.run(); 54 | this.font.say(); 55 | } 56 | 57 | // 精灵类 58 | function Spirite(x, y, c, s) { 59 | this.speed = new Speed(x, y); 60 | this.color = new Color(c); 61 | this.shape = new Shape(s); 62 | } 63 | Spirite.prototype.init = function () { 64 | this.speed.run(); 65 | this.color.draw(); 66 | this.shape.change(); 67 | } 68 | 69 | var p = new People(10, 12, 16); 70 | p.init(); -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_14组合模式/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jixianu/JS-design-patterns/8ce5a0d5d40fb35242a13a5d2361fcb3062435bf/3-结构性设计模式/chapter_14组合模式/1.jpg -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_14组合模式/14.4组合要有容器类.js: -------------------------------------------------------------------------------- 1 | // 寄生组合式继承 2 | function inheritObject(o) { 3 | // 声明一个过渡函数对象 4 | function F() {} 5 | // 过渡对象的原型继承父对象 6 | F.prototype = o; 7 | // 返回过渡对象的一个实例,该实例的原型继承了父对象 8 | return new F(); 9 | } 10 | 11 | function inheritPrototype(subClass, superClass) { 12 | // 复制一份父类的原型保存在变量中 13 | var p = inheritObject(superClass.prototype); 14 | p.constructor = subClass; 15 | subClass.prototype = p; 16 | } 17 | var News = function () { 18 | // 子组件容器 19 | this.children = []; 20 | // 当前组件元素 21 | this.element = null; 22 | } 23 | // 抽象工厂模式 24 | News.prototype = { 25 | init : function () { 26 | throw new Error('请重写你的方法'); 27 | }, 28 | add : function () { 29 | throw new Error('请重写你的方法'); 30 | }, 31 | getElement : function () { 32 | throw new Error('请重写你的方法'); 33 | } 34 | } 35 | 36 | // 容器类构造函数 37 | var Container = function (id, parent) { 38 | // 构造函数继承父类 39 | News.call(this); 40 | // 模块id 41 | this.id = id; 42 | // 模块的父容器 43 | this.parent = parent; 44 | // 构建方法 45 | this.init(); 46 | } 47 | // 寄生式继承父类原型方法 48 | inheritPrototype(Container, News); 49 | // 构建方法 50 | Container.prototype.init = function () { 51 | this.element = document.createElement('ul'); 52 | this.element.id = this.id; 53 | this.element.className = 'new-container'; 54 | } 55 | // 添加子元素方法 56 | Container.prototype.add = function (child) { 57 | this.children.push(child); 58 | this.element.appendChild(child.getElement()); 59 | return this; 60 | } 61 | // 获取当前元素方法 62 | Container.prototype.getElement = function () { 63 | return this.element; 64 | } 65 | // 显示方法 66 | Container.prototype.show = function () { 67 | this.parent.appendChild(this.element); 68 | } 69 | 70 | // 容器类构造函数 71 | var Item = function (classname) { 72 | News.call(this); 73 | this.classname = classname || ''; 74 | this.init(); 75 | } 76 | // 寄生式继承父类原型方法 77 | inheritPrototype(Item, News); 78 | // 构建方法 79 | Item.prototype.init = function () { 80 | this.element = document.createElement('li'); 81 | this.element.className = this.classname; 82 | } 83 | // 添加子元素方法 84 | Item.prototype.add = function (child) { 85 | // 在子元素容器中插入子元素 86 | this.children.push(child); 87 | // 插入当前组件元素树中 88 | this.element.appendChild(child.getElement()); 89 | return this; 90 | } 91 | // 获取当前元素方法 92 | Item.prototype.getElement = function () { 93 | return this.element; 94 | } 95 | 96 | var NewsGroup = function (classname) { 97 | News.call(this); 98 | this.classname = classname || ''; 99 | this.init(); 100 | } 101 | inheritPrototype(NewsGroup, News); 102 | // 构建方法 103 | NewsGroup.prototype.init = function () { 104 | this.element = document.createElement('div'); 105 | this.element.className = this.classname; 106 | } 107 | NewsGroup.prototype.add = function (child) { 108 | // 在子元素容器中插入子元素 109 | this.children.push(child); 110 | // 插入当前组件元素树中 111 | this.element.appendChild(child.getElement()); 112 | return this; 113 | } 114 | NewsGroup.prototype.getElement = function () { 115 | return this.element; 116 | } -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_14组合模式/14.5创建一个新闻类.js: -------------------------------------------------------------------------------- 1 | var ImageNews = function (url, href, classname) { 2 | News.call(this); 3 | this.url = url || ''; 4 | this.href = href || '#'; 5 | this.className = classname || 'normal'; 6 | this.init(); 7 | } 8 | inheritPrototype(ImageNews, News); 9 | ImageNews.prototype.init = function () { 10 | this.element = document.createElement('a'); 11 | var img = new Image(); 12 | img.src = this.url; 13 | this.element.appendChild(img); 14 | this.element.className = 'image-news' + this.classname; 15 | this.element.href = this.href; 16 | } 17 | ImageNews.prototype.add = function () {} 18 | ImageNews.prototype.getElement = function () { 19 | return this.element; 20 | } 21 | 22 | var IconNews = function (text, href, type) { 23 | News.call(this); 24 | this.text = text || ''; 25 | this.href = href || '#'; 26 | this.type = type || 'video'; 27 | this.init(); 28 | } 29 | inheritPrototype(IconNews, News); 30 | IconNews.prototype.init = function () { 31 | this.element = document.createElement('a'); 32 | this.element.innerHTML = this.text; 33 | this.element.href = this.href; 34 | this.element.className = 'icon' + this.type; 35 | } 36 | IconNews.prototype.add = function () {} 37 | IconNews.prototype.getElement = function () { 38 | return this.element; 39 | } 40 | 41 | var EasyNews = function (text, href) { 42 | News.call(this); 43 | this.text = text || ''; 44 | this.href = href || '#'; 45 | this.init(); 46 | } 47 | inheritPrototype(EasyNews, News); 48 | EasyNews.prototype.init = function () { 49 | this.element = document.createElement('a'); 50 | this.element.innerHTML = this.text; 51 | this.element.href = this.href; 52 | this.element.className = 'text'; 53 | } 54 | EasyNews.prototype.add = function () {} 55 | EasyNews.prototype.getElement = function () { 56 | return this.element; 57 | } 58 | 59 | var TypeNews = function (text, href, type, pos) { 60 | News.call(this); 61 | this.text = text || ''; 62 | this.href = href || '#'; 63 | this.type = type || ''; 64 | this.pos = pos || 'left'; 65 | this.init(); 66 | } 67 | inheritPrototype(TypeNews, News); 68 | TypeNews.prototype.init = function () { 69 | this.element = document.createElement('a'); 70 | if (this.pos === 'left') { 71 | this.element.innerHTML = '[' + this.type + ']' + this.text; 72 | } else { 73 | this.element.innerHTML = this.text + '[' + this.type + ']'; 74 | } 75 | this.element.href = this.href; 76 | this.element.className = 'text'; 77 | } 78 | TypeNews.prototype.add = function () {} 79 | TypeNews.prototype.getElement = function () { 80 | return this.element; 81 | } -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_14组合模式/14.6把新闻模块创建出来.js: -------------------------------------------------------------------------------- 1 | var news1 = new Container('news', document.body); 2 | news1.add( 3 | new Item('normal').add( 4 | new IconNews('梅西不拿金球奖也很伟大', '#', 'video') 5 | ) 6 | ).add( 7 | new Item('normal').add( 8 | new IconNews('两岸关系紧张', '#', 'live') 9 | ) 10 | ).add( 11 | new Item('normal').add( 12 | new NewsGroup('has-img').add( 13 | new ImageNews('1.jpg', '#', 'small') 14 | ).add( 15 | new EasyNews('从240斤到型男', '#') 16 | ).add( 17 | new EasyNews('五大雷人跑步机', '#') 18 | ) 19 | ) 20 | ).add( 21 | new Item('normal').add( 22 | new TypeNews('AK47不愿为费城打球', '#', 'NBA', 'left') 23 | ) 24 | ).add( 25 | new Item('normal').add( 26 | new TypeNews('火炮飚6三分创新高', '#', 'CBA', 'right') 27 | ) 28 | ).show(); 29 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_14组合模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_15享元模式/15.3享元对象.js: -------------------------------------------------------------------------------- 1 | var Flyweight = (function () { 2 | // 已创建的元素 3 | var created = []; 4 | // 创建一个新闻列表容器 5 | function create() { 6 | var dom = document.createElement('div'); 7 | // 将容器插入新闻列表容器中 8 | document.getElementById('container').appendChild(dom); 9 | // 缓存新创建的元素 10 | created.push(dom); 11 | // 返回创建的新元素 12 | return dom; 13 | } 14 | return { 15 | // 获取创建新闻元素方法 16 | getDiv : function () { 17 | // 如果已创建的元素小于当前页元素总个数,则创建 18 | if (created.length < 5) { 19 | return create(); 20 | } else { 21 | // 获取第一个元素,并插入最后面 22 | var div = created.shift(); 23 | created.push(div); 24 | return div; 25 | } 26 | } 27 | } 28 | })(); 29 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_15享元模式/15.4实现需求.js: -------------------------------------------------------------------------------- 1 | var paper = 0, 2 | num = 5, 3 | len = article.length; 4 | // 添加5条新闻 5 | for(var i = 0; i < 5; i++ ){ 6 | if(article[i]) 7 | // 通过享元类获取创建的元素并写入新闻内容 8 | Flyweight.getDiv().innerHTML = article[i]; 9 | } 10 | // 下一页按钮绑定事件 11 | document.getElementById('next_page').onclick = function() { 12 | // 如果新闻内容不足5条则返回 13 | if (article.length < 5) 14 | return ; 15 | var n = ++paper * num % len, // 获取当前页的第一条新闻索引 16 | j = 0; // 循环变量 17 | // 插入5条新闻 18 | for(;j < 5; j++) { 19 | // 如果存在第n+j条则插入 20 | if(article[n + j]){ 21 | Flyweight.getDiv().innerHTML = article[n + j]; 22 | // 否则插入起始位置第 n + j -len 条 23 | } else if (article[n + j -len]) { 24 | Flyweight.getDiv().innerHTML = article[n + j - len]; 25 | } else { 26 | Flyweight.getDiv().innerHTML = ""; 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_15享元模式/15.5享元动作.js: -------------------------------------------------------------------------------- 1 | var Flyweight = { 2 | moveX : function (x) { 3 | this.x = x; 4 | }, 5 | moveY : function (y) { 6 | this.y = y; 7 | } 8 | } 9 | var Player = function (x, y, c) { 10 | this.x = x; 11 | this.y = y; 12 | this.color = c; 13 | } 14 | Player.prototype = Flyweight; 15 | Player.prototype.changeC = function (c) { 16 | this.color = c; 17 | } 18 | 19 | var Spirit = function (x, y, r) { 20 | this.x = x; 21 | this.y = y; 22 | this.r = r; 23 | } 24 | Spirit.prototype = Flyweight; 25 | Spirit.prototype.changeR = function (r) { 26 | this.r = r; 27 | } 28 | // 创建一个人 29 | var player1 = new Player(5, 6, 'red'); 30 | console.log(player1); 31 | 32 | // 让人移动 33 | player1.moveX(6); 34 | player1.moveY(7); 35 | player1.changeC('pink'); 36 | console.log( player1 ); 37 | 38 | // 创建一个精灵 39 | var spirit1 = new Spirit(2, 3, 4); 40 | console.log( spirit1 ); 41 | 42 | // 让精灵移动 43 | spirit1.moveX(3); 44 | spirit1.moveY(4); 45 | spirit1.changeC(5); 46 | console.log( spirit1 ); 47 | -------------------------------------------------------------------------------- /3-结构性设计模式/chapter_15享元模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 | 11 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_16模板方法模式/16.3创建基本提示框.js: -------------------------------------------------------------------------------- 1 | // 模板类 基础提示框 data 渲染数据 2 | var Alert = function (data) { 3 | // 没有数据则返回 4 | if (!data) return ; 5 | // 设置内容 6 | this.content = data.content; 7 | // 创建面板、内容、确定按钮、关闭按钮 8 | this.panel = document.createElement('div'); 9 | this.contentNode = document.createElement('p'); 10 | this.confirmBtn = document.createElement('span'); 11 | this.closeBtn = document.createElement('b'); 12 | // 添加样式类 13 | this.panel.className = 'alert'; 14 | this.confirmBtn.className = 'a-close'; 15 | this.closeBtn.className = 'a-confirm'; 16 | // 为确定按钮添加文案 17 | this.confirmBtn.innerHTML = data.confirm || '确认'; 18 | // 为提示内容添加文本 19 | this.contentNode.innerHTML = this.content; 20 | // 点击确定按钮执行方法,如果data中有success方法则为success方法,否则为空函数 21 | this.success = data.success || function(){}; 22 | // 点击关闭按钮执行方法 23 | this.fail = data.fail || function(){}; 24 | } 25 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_16模板方法模式/16.4模板的原型方法.js: -------------------------------------------------------------------------------- 1 | // 提示框原型方法 2 | Alert.prototype = { 3 | init : function () { 4 | // 生成提示框 5 | this.panel.appendChild(this.closeBtn); 6 | this.panel.appendChild(this.contentNode); 7 | this.panel.appendChild(this.confirmBtn); 8 | // 插入页面中 9 | document.body.appendChild(this.panel); 10 | // 绑定事件 11 | this.bindEvent(); 12 | // 显示提示框 13 | this.show(); 14 | }, 15 | bindEvent : function () { 16 | var me = this; 17 | // 关闭按钮点击事件 18 | this.closeBtn.onclick = function () { 19 | // 执行关闭取消方法 20 | me.fail(); 21 | // 隐藏弹出层 22 | me.hide(); 23 | } 24 | // 确定按钮点击事件 25 | this.confirmBtn.onclick = function () { 26 | // 执行关闭确认方法 27 | me.success(); 28 | // 隐藏弹出层 29 | me.hide(); 30 | } 31 | }, 32 | show : function () { 33 | this.panel.style.display = 'none'; 34 | }, 35 | hide : function () { 36 | this.panel.style.display = 'block'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_16模板方法模式/16.5根据模板类创建类.js: -------------------------------------------------------------------------------- 1 | // 右侧按钮提示框 2 | var RightAlert = function (data) { 3 | // 继承基本提示框构造函数 4 | Alert.call(this, data); 5 | // 为确认按钮添加right类设置位置居右 6 | this.confirmBtn.className = this.confirmBtn.className + 'right'; 7 | } 8 | // 继承基础提示框方法 9 | RightAlert.prototype = new Alert(); 10 | 11 | // 标题提示框 12 | var TitleAlert = function (data) { 13 | // 继承基本提示框构造函数 14 | Alert.call(this, data); 15 | // 设置标题内容 16 | this.title = data.title; 17 | // 创建标题组件 18 | this.titleNode = document.createElement('h3'); 19 | // 标题组件中写入标题内容 20 | this.titleNode.innerHTML = this.title; 21 | } 22 | // 继承基本提示框方法 23 | TitleAlert.prototype = new Alert(); 24 | // 对基本提示框创建方法拓展 25 | TitleAlert.prototype.init = function () { 26 | // 插入主题 27 | this.panel.insertBefore(this.titleNode, this.panel.firstChild); 28 | // 继承基本提示框init方法 29 | Alert.prototype.init.call(this); 30 | } -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_16模板方法模式/16.6继承类也可作为模板类.js: -------------------------------------------------------------------------------- 1 | // 带有取消按钮的弹出框 2 | var CancelAlert = function (data) { 3 | // 继承标题提示框构造函数 4 | TitleAlert.call(this, data); 5 | // 取消按钮文案 6 | this.cancel = data.cancel; 7 | // 创建取消按钮 8 | this.cancelBtn = document.createElement('span'); 9 | // 为取消按钮添加类 10 | this.cancelBtn.className = 'cancel'; 11 | // 设置取消按钮内容 12 | this.cancelBtn.innerHTML = this.cancel || '取消'; 13 | } 14 | // 继承标题提示框原型方法 15 | CancelAlert.prototype = new Alert(); 16 | CancelAlert.prototype.init = function () { 17 | // 继承标题提示框创建方法 18 | TitleAlert.prototype.init.call(this); 19 | // 由于取消按钮要添加在末尾,所以在创建完其他组价后添加 20 | this.panel.appendChild(this.cancelBtn); 21 | } 22 | CancelAlert.prototype.bindEvent = function () { 23 | var me = this; 24 | // 标题提示框绑定事件方法继承 25 | TitleAlert.prototype.bindEvent.call(me); 26 | this.cancelBtn.onclick = function () { 27 | // 执行取消回调函数 28 | me.fail(); 29 | // 隐藏弹出层 30 | me.hide(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_16模板方法模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 26 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_17观察者模式/17.3 创建一个观察者.js: -------------------------------------------------------------------------------- 1 | // 观察者闭包,页面加载立即执行 2 | var Observer = (function () { 3 | // 防止消息队列暴露而被篡改,故将消息容器作为静态私有变量保存 4 | var _messages = []; 5 | return { 6 | // 注册信息接口 7 | regist : function (type, fn) { 8 | // 如果此消息不存在则应该创建一个该消息类型 9 | if (typeof _messages[type] === 'undefined') { 10 | // 将动作推入到该信息对应的动作执行队列中 11 | _messages[type] = [fn]; 12 | // 如果不存在 13 | } else { 14 | // 将动作方法推入该消息对应的动作执行序列中 15 | _messages[type].push(fn); 16 | } 17 | }, 18 | // 发布信息接口 19 | fire : function (type, args) { 20 | // 如果该消息没有被注册,则返回 21 | if (!_messages[type]) { 22 | return ; 23 | } 24 | // 定义消息信息 25 | var events = { 26 | type : type, // 消息类型 27 | args : args || {} // 消息携带数据 28 | }, 29 | i = 0, 30 | len = _messages[type].length; 31 | // 遍历消息动作 32 | for(; i < len; i++){ 33 | // 依次执行注册的消息对应的动作序列 34 | _messages[type][i].call(this, events); 35 | } 36 | }, 37 | // 移除信息接口 38 | remove : function (type, fn) { 39 | // 如果消息动作队列存在 40 | if (_messages[type] instanceof Array) { 41 | // 从最后一个消息动作遍历 42 | var i = _messages[type].length - 1; 43 | for(;i >= 0; i--){ 44 | // 如果存在该动作则在消息动作序列中移除相应动作 45 | _messages[type][i] === fn && _messages[type].splice(i, 1); 46 | } 47 | } 48 | } 49 | } 50 | })(); -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_17观察者模式/17.6大显身手.js: -------------------------------------------------------------------------------- 1 | // 外观模式 简化获取元素 2 | function $(id){ 3 | return document.getElementById(id); 4 | } 5 | 6 | //工程师A 7 | (function () { 8 | // 追加一则消息 9 | function addMsgItem(e) { 10 | var text = e.args.text, 11 | ul = $('msg'), 12 | li = document.createElement('li'), 13 | span = document.createElement('span'); 14 | li.innerHTML = text; 15 | // 关闭按钮 16 | span.onclick = function () { 17 | ul.removeChild(li); 18 | // 发布删除留言信息 19 | Observer.fire('removeCommentMessage', { 20 | num : -1 21 | }); 22 | } 23 | // 添加删除按钮 24 | li.appendChild(span); 25 | // 添加留言节点 26 | ul.appendChild(li); 27 | } 28 | // 注册添加评论信息 29 | Observer.regist('addCommentMessage', addMsgItem); 30 | })(); 31 | 32 | //工程师B 33 | (function () { 34 | // 更改用户信息数目 35 | function changeMsgNum(e) { 36 | // 获取需要增加的用户信息数目 37 | var num = e.args.num; 38 | // 增加用户消息数目并写入页面中 39 | $('msg_num').innerHTML = parseInt($('msg_num').innerHTML) + num; 40 | } 41 | // 注册添加评论信息 42 | Observer.regist('addCommentMessage', changeMsgNum); 43 | Observer.regist('removeCommentMessage', changeMsgNum); 44 | })(); 45 | 46 | //工程师C 47 | (function () { 48 | // 用户点击提交按钮 49 | $('user_submit').onclick = function () { 50 | // 获取用户输入框中输入的信息 51 | var text = $('user_input'); 52 | // 如果消息为空则提交失败 53 | if (text.value === '') { 54 | return ; 55 | } 56 | // 发布一则评论消息 57 | Observer.regist('addCommentMessage', { 58 | text : text.value, // 消息评论内容 59 | num : 1 // 消息评论数目 60 | }); 61 | text.value = ''; //输入框置空 62 | } 63 | })(); -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_17观察者模式/17.7对象间解耦.js: -------------------------------------------------------------------------------- 1 | // 学生类 2 | var Student = function (result) { 3 | var that = this; 4 | // 学生回答结果 5 | that.result = result; 6 | // 学生回答问题动作 7 | that.say = function () { 8 | console.log( that.result ); 9 | }; 10 | } 11 | // 回答问题方法 12 | Student.prototype.answer = function (question) { 13 | // 注册参数问题 14 | Observer.regist(question, this.say); 15 | } 16 | // 学生睡觉,此时不能回答问题 17 | Student.prototype.sleep = function (question) { 18 | console.log( this.result + ' ' + question + ' 已被注销' ); 19 | // 取消对老师问题的监听 20 | Observer.remove(question, this.say); 21 | } 22 | 23 | // 教师类 24 | var Teacher = function(){}; 25 | // 教师提问问题的方法 26 | Teacher.prototype.ask = function (question) { 27 | console.log( '问题是:' + question ); 28 | // 发布提问消息 29 | Observer.fire(question); 30 | } 31 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_17观察者模式/17.8演练.js: -------------------------------------------------------------------------------- 1 | var student1 = new Student('学生1回答问题'); 2 | var student2 = new Student('学生2回答问题'); 3 | var student3 = new Student('学生3回答问题'); 4 | 5 | student1.answer('什么是设计模式'); 6 | student1.answer('简述观察者模式'); 7 | student2.answer('什么是设计模式'); 8 | student3.answer('什么是设计模式'); 9 | student3.answer('简述观察者模式'); 10 | 11 | student3.sleep('简述观察者模式'); 12 | 13 | var teacher = new Teacher(); 14 | teacher.ask('什么是设计模式'); 15 | teacher.ask('简述观察者模式'); -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_17观察者模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_18状态模式/18.6状态优化.js: -------------------------------------------------------------------------------- 1 | // 创建超级玛丽状态类 2 | var MarryState = function () { 3 | // 内部状态私有变量 4 | var _currentState = {}, 5 | // 动作与状态方法映射 6 | states = { 7 | jump : function () { 8 | // 跳跃 9 | console.log( 'jump' ); 10 | }, 11 | move : function () { 12 | // 移动 13 | console.log( 'move' ); 14 | }, 15 | shoot : function () { 16 | // 射击 17 | console.log( 'shoot' ); 18 | }, 19 | squat : function () { 20 | // 蹲下 21 | console.log( 'squat' ); 22 | } 23 | }; 24 | // 动作控制类 25 | var Action = { 26 | // 改变状态方法 27 | changeState : function () { 28 | // 组合动作通过传递多个参数实现 29 | var arg = arguments; 30 | // 重置内部状态 31 | _currentState = {}; 32 | // 如果有动作则添加动作 33 | if (arg.length) { 34 | for (var i = 0, len = arg.length; i < len; i++){ 35 | // 在内部状态添加动作 36 | _currentState[arg[i]] = true; 37 | } 38 | } 39 | // 返回动作控制类 40 | return this; 41 | }, 42 | // 执行动作 43 | goes : function () { 44 | console.log( '触发一次动作' ); 45 | // 遍历内部状态保存的动作 46 | for(var i in _currentState){ 47 | // 如果该动作存在则执行 48 | states[i] && states[i](); 49 | } 50 | return this; 51 | } 52 | } 53 | // 返回接口方法 change、goes 54 | return { 55 | change : Action.changeState, 56 | goes : Action.goes 57 | } 58 | }; 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_18状态模式/18.7两种使用方式.js: -------------------------------------------------------------------------------- 1 | MarryState() 2 | .change('jump', 'shoot') 3 | .goes() 4 | .goes() 5 | .change('shoot') 6 | .goes(); 7 | 8 | // 创建一个超级玛丽 9 | var marry = new MarryState(); 10 | marry 11 | .change('jump', 'shoot') 12 | .goes() 13 | .goes() 14 | .change('shoot') 15 | .goes(); -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_18状态模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_19策略模式/19.3策略对象.js: -------------------------------------------------------------------------------- 1 | // 价格策略对象 2 | var PriceStrategy = function () { 3 | // 内部算法对象 4 | var strategy = { 5 | // 100返30 6 | back30 : function (price) { 7 | // +price转化为数字类型 8 | return +price + parseInt(price / 100) * 30; 9 | }, 10 | // 100返50 11 | back50 : function (price) { 12 | return +price + parseInt(price / 100) * 50; 13 | }, 14 | // 9折 15 | percent90 : function (price) { 16 | // JavaScript处理小数乘除法有缺陷bug,故运算前转化为整数 17 | return price * 100 * 90 / 10000; 18 | }, 19 | // 8折 20 | percent80 : function (price) { 21 | return price * 100 * 80 / 10000; 22 | }, 23 | // 5折 24 | percent50 : function (price) { 25 | return price * 100 * 50 / 10000; 26 | } 27 | } 28 | // 策略算法调用接口 29 | return function (algorighm, price) { 30 | // 如果算法存在,则调用算法,否则返回false 31 | return strategy[algorighm] && strategy[algorighm](price); 32 | } 33 | }() 34 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_19策略模式/19.6表单验证.js: -------------------------------------------------------------------------------- 1 | // 表单正则验证策略对象 2 | var InputStrategy = function () { 3 | var strategy = { 4 | // 是否为空 5 | notNull : function (value) { 6 | return /\s+/.test(value) ? '请输入内容' : ''; 7 | }, 8 | // 是否是一个数字 9 | number : function (value) { 10 | return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '请输入数字'; 11 | }, 12 | // 是否是本地电话 13 | phone : function (value) { 14 | return /^\d{3}\-\d{8}$|\d{4}\-\d{7}$/.test(value) ? '' : '请输入正确的电话号码格式,如:010-12345678 或 0418-1234567'; 15 | } 16 | } 17 | return { 18 | // 验证接口type算法value表单值 19 | check : function (type, value) { 20 | // 去除收尾空白符 21 | value = value.replace(/^\s+|\s+$/g, ''); 22 | return strategy[type] ? strategy[type][value] : '没有该类型的检测方法' 23 | }, 24 | // 添加策略 25 | addStrategy : function (type, fn) { 26 | strategy[type] = fn; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_19策略模式/19.7拓展与调用.js: -------------------------------------------------------------------------------- 1 | // 拓展 可以延伸算法 2 | InputStrategy.addStrategy('nickname', function (value) { 3 | return /^[a-zA-Z]\w{3,7}$/.test(value) ? '' : '请输入4-8位昵称,如YYQH'; 4 | }); 5 | 6 | // 外观模式简化元素的获取 7 | function $tag(tag, context){ 8 | context = context || document; 9 | return context.getElementsByTagName(tag); 10 | } 11 | // 提交按钮点击 12 | $tag('input')[1].onclick = function () { 13 | // 获取输入框内容 14 | var value = $tag('input')[0].value; 15 | // 获取日期格式验证结果 16 | $tag('span')[0].innerHTML = InputStrategy.check('nickname', value); 17 | } 18 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_19策略模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_20职责链模式/20.3第一站-请求模式.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 异步请求对象(简化版) 3 | * 参数data 请求数据 4 | * 参数dataType 响应数据处理对象 5 | * 参数dom 事件源 6 | */ 7 | 8 | var sendData = function (data, dealType, dom) { 9 | // XHR对象 简化版IE另行处理 10 | var xhr = new XMLHttpRequest(), 11 | // 请求路径 12 | url = 'getData.php?mod=userInfo'; 13 | // 请求返回事件 14 | xhr.onload = function (event) { 15 | // 请求成功 16 | if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { 17 | dealData(xhr.responseText, dealType, dom); 18 | } else { 19 | // 请求失败 20 | } 21 | }; 22 | for (var i in data){ 23 | url += '&' + i + '=' + data[i]; 24 | } 25 | // 发送异步请求 26 | xhr.open('get', url, true); 27 | xhr.send(null); 28 | }; -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_20职责链模式/20.4下一站-响应数据适配模块.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 处理响应数据 3 | * 参数data 请求数据 4 | * 参数dataType 响应数据处理对象 5 | * 参数dom 事件源 6 | */ 7 | var dealData = function (data, dealType, dom) { 8 | // 对象toString方法简化引用 9 | var dataType = Object.prototype.toString.call(data); 10 | // 判断相应数据处理对象 11 | switch(dealType){ 12 | // 输入框提示功能 13 | case 'sug': 14 | // 如果数据为数组 15 | if (dataType === "[object Array]") { 16 | // 创建提示框组件 17 | return createSug(data, dom); 18 | } 19 | // 将响应的对象数据转化为数组 20 | if (dataType === "[object Object]") { 21 | var newData = []; 22 | for(var i in data){ 23 | newData.push(data[i]); 24 | } 25 | // 创建提示框组件 26 | return createSug(data, dom); 27 | } 28 | // 将响应的其他数据转化为数组 29 | return createSug([data], dom); 30 | break; 31 | case 'validate': 32 | // 创建校验组件 33 | return createValidataResult(data, dom); 34 | break; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_20职责链模式/20.5终点站-创建组件模块.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 创建提示框组件 3 | * 参数data 响应适配数据 4 | * 参数dom 事件源 5 | */ 6 | var createSug = function (data, dom) { 7 | var i = 0, 8 | len = data.length, 9 | html = ''; 10 | // 拼接每一条提示语句 11 | for(; i < len; i++){ 12 | html += '
  • ' + data[i] + '
  • '; 13 | } 14 | // 显示提示框 15 | dom.parentNode.getElementsByTagName('ul')[0].innerHTML = html; 16 | } 17 | 18 | /** 19 | * 创建校验组件 20 | * 参数data 响应适配数据 21 | * 参数dom 事件源 22 | */ 23 | var createValidataResult = function (data, dom) { 24 | // 显示校验结果 25 | dom.parentNode.getElementsByTagName('span')[0].innerHTML = data; 26 | } 27 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_20职责链模式/20.6单元测试.js: -------------------------------------------------------------------------------- 1 | dealData('用户名不正确', 'validate', input[0]); 2 | dealData(123, 'sug', input[1]); 3 | dealData(['爱奇艺', '阿里巴巴', '爱漫画'], 'sug', input[1]); 4 | dealData({ 5 | 'iqy' : '爱奇艺', 6 | 'albb' : '阿里巴巴', 7 | 'imh' : '爱漫画' 8 | }, 'sug', input[1]); 9 | 10 | var createSug = function (data, dom) { 11 | console.log(data, dom, 'createSug'); 12 | } 13 | var createValidataResult = function (data, dom) { 14 | console.log( data, dom, 'createValidataResult' ); 15 | } -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_21命令模式/21.2命令对象.js: -------------------------------------------------------------------------------- 1 | // 模块实现模块 2 | var viewCommand = (function () { 3 | // 方法集合 4 | var Action = { 5 | // 创建方法 6 | create : function(){}, 7 | // 展示方法 8 | display : function(){} 9 | } 10 | // 命令接口 11 | return function excute(){}; 12 | })(); 13 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_21命令模式/21.3视图创建.js: -------------------------------------------------------------------------------- 1 | // 模块实现模块 2 | var viewCommand = (function () { 3 | var tpl = { 4 | // 展示图片结构模板 5 | product : [ 6 | '
    ', 7 | '', 8 | '

    {#text#}

    ', 9 | '
    ' 10 | ].join(''), 11 | // 展示标题结构模板 12 | title : [ 13 | '
    ', 14 | '
    ', 15 | '

    {#title#}

    ', 16 | '

    {#tips#}

    ', 17 | '
    ', 18 | '
    ' 19 | ].join('') 20 | }, 21 | // 格式化字符串缓存字符串 22 | html = ''; 23 | //格式化字符串 24 | function formateString(str, obj){ 25 | // 替换'{#与#}'之间的字符串 26 | return str.replace(/\{#(\w+)#\}/g, function (match, key) { 27 | return obj[key]; 28 | }) 29 | } 30 | // 方法集合 31 | var Action = { 32 | // 创建方法 33 | create : function(data, view){ 34 | // 解析数据 如果数据时一个数组 35 | if (data.length) { 36 | // 遍历数组 37 | for(var i = 0, len = data.length; i < len; i++){ 38 | // 将格式化之后的字符串缓存到html中 39 | html += formateString(tpl[view], data[i]); 40 | } 41 | } else { 42 | // 直接格式化字符串缓存到html中 43 | html += formateString(tpl[view], data); 44 | } 45 | }, 46 | // 展示方法 47 | display : function(container, data, view){ 48 | // 如果传入数据 49 | if (data) { 50 | // 根据给定数据创建视图 51 | this.create(data, view); 52 | } 53 | // 展示模块 54 | document.getElementById(container).innerHTML = html; 55 | // 展示后清空缓存的字符串 56 | html = ''; 57 | } 58 | } 59 | // 命令接口 60 | return function excute(msg){ 61 | // 解析命令,如果msg.param不是数组则将转化为数组(apply方法要求第二个参数为数组) 62 | msg.param = Object.prototype.toString.call(msg.param) === "[object Array]" ? msg.param : [msg.param]; 63 | // Action内部调用的方法引用this,所以此处为保证作用域this执行传入Action 64 | Action[msg.command].apply(Action, msg.param); 65 | }; 66 | })(); 67 | 68 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_22访问者模式/22.4事件自定义数据.js: -------------------------------------------------------------------------------- 1 | function bindIEEvent(dom, type, fn, data) { 2 | var data = data || {}; 3 | dom.attachEvent('on' + type, function (e) { 4 | fn.call(dom, e, data); 5 | }); 6 | } 7 | 8 | function $(id) { 9 | return document.getElementById(id); 10 | } 11 | 12 | bindIEEvent($('btn'), 'click', function (e, d) { 13 | $('test').innerHTML = e.type + d.text + this.tagName; 14 | }, {text : 'test demo'}); -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_22访问者模式/22.5对象访问器.js: -------------------------------------------------------------------------------- 1 | // 访问器 2 | var Visitor = (function () { 3 | return { 4 | // 截取方法 5 | splice : function () { 6 | // splice方法参数,从原参数的第二个参数开始算起 7 | var args = Array.prototype.splice.call(arguments, 1); 8 | // 对第一个参数对象执行splice方法 9 | return Array.prototype.splice.apply(arguments[0], args); 10 | }, 11 | // 追加数据方法 12 | push : function () { 13 | // 强化类数组对象,使他拥有length属性 14 | var len = arguments[0].length || 0; 15 | // 添加的数据从原参数的第二个参数算起 16 | var args = this.splice(arguments, 1); 17 | // 校正length属性 18 | arguments[0].length = len + arguments.length - 1; 19 | // 对第一个参数对象执行push方法 20 | return Array.prototype.push.apply(arguments[0], args); 21 | }, 22 | // 弹出最后一次添加的元素 23 | pop : function () { 24 | // 对第一个参数对象执行pop方法 25 | return Array.prototype.pop.apply(arguments[0]); 26 | } 27 | } 28 | })() -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_22访问者模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | 27 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_23中介者模式/23.2创建中介者对象.js: -------------------------------------------------------------------------------- 1 | // 中介者对象 2 | var Mediator = function () { 3 | // 消息对象 4 | var _msg = {}; 5 | return { 6 | /*** 7 | * 订阅消息方法 8 | * 参数type 消息名称 9 | * 参数action 消息回调函数 10 | */ 11 | register : function (type, action) { 12 | // 如果该消息存在 13 | if (_msg[type]) { 14 | // 存入回调函数 15 | _msg[type].push(action); 16 | } else { 17 | // 不存在 则建立该消息容器 18 | _msg[type] = []; 19 | // 存入新小心回调函数 20 | _msg[type].push(action); 21 | } 22 | }, 23 | /*** 24 | * 发布消息方法 25 | * 参数type 消息名称 26 | */ 27 | send : function (type) { 28 | // 如果该消息已经被订阅 29 | if (_msg[type]) { 30 | // 遍历已存储的消息回调函数 31 | for(var i = 0, len = _msg[type].length; i < len; i++){ 32 | // 执行该回调函数 33 | _msg[type][i] && _msg[type][i](); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_23中介者模式/23.5订阅消息.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 显隐导航小组件 3 | * 参数mod 模块 4 | * 参数tag 处理的标签(消息提醒b,网址span) 5 | * 参数showOrHide 显示还是隐藏 6 | */ 7 | var showHideNavWidget = function (mod, tag, showOrHide) { 8 | // 获取导航模块 9 | var mod = document.getElementById(mod), 10 | // 获取下面的标签名为tag的元素 11 | tag = mod.getElementsByTagName(tag), 12 | // 如果设置为false或者为hide则值为hidden,否则为visible 13 | showOrHide = (!showOrHide || showOrHide == 'hide') ? 'hidden' : 'visible'; 14 | // 占位隐藏这些标签 15 | for(var i = tag.length - 1; i >= 0; i--){ 16 | tag.style.visibility = showOrHide; 17 | } 18 | } 19 | 20 | // 用户收藏导航模块 21 | (function () { 22 | // ..其他交互逻辑 23 | // 订阅隐藏用户收藏导航消息提醒消息 24 | Mediator.regist('hideAllNavNum', function () { 25 | showHideNavWidget('collection_nav', 'b', false); 26 | }); 27 | // 订阅显示用户收藏导航消息提醒消息 28 | Mediator.regist('hideAllNavNum', function () { 29 | showHideNavWidget('collection_nav', 'b', true); 30 | }); 31 | // 订阅隐藏用户收藏导航网址消息 32 | Mediator.regist('hideAllNavUrl', function () { 33 | showHideNavWidget('collection_nav', 'span', false); 34 | }); 35 | // 订阅显示用户收藏导航网址消息 36 | Mediator.regist('hideAllNavUrl', function () { 37 | showHideNavWidget('collection_nav', 'span', true); 38 | }); 39 | })(); 40 | 41 | // 推荐用户导航 42 | (function () { 43 | // ..其他交互逻辑 44 | // 订阅隐藏推荐用户导航消息提醒消息 45 | Mediator.regist('hideAllNavNum', function () { 46 | showHideNavWidget('recommend_nav', 'b', false); 47 | }); 48 | // 订阅显示推荐用户导航消息提醒消息 49 | Mediator.regist('hideAllNavNum', function () { 50 | showHideNavWidget('recommend_nav', 'b', true); 51 | }); 52 | })() 53 | 54 | // 最近常用导航 55 | (function () { 56 | // ..其他交互逻辑 57 | // 订阅隐藏用户收藏导航网址消息 58 | Mediator.regist('hideAllNavUrl', function () { 59 | showHideNavWidget('recently_nav', 'span', false); 60 | }); 61 | // 订阅显示用户收藏导航网址消息 62 | Mediator.regist('hideAllNavNum', function () { 63 | showHideNavWidget('recently_nav', 'span', true); 64 | }); 65 | })() -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_23中介者模式/23.6发布消息.js: -------------------------------------------------------------------------------- 1 | // 设置层模块 2 | (function () { 3 | // 消息提醒选框 4 | var hideNum = document.getElementById('hide_num'), 5 | // 网址选框 6 | hideUrl = document.getElementById('hide_url'); 7 | // 消息提醒选框事件 8 | hideNum.onchange = function () { 9 | // 如果勾选 10 | if (hideNum.checked) { 11 | // 中介者发布隐藏消息提醒功能消息 12 | Mediator.send('hideAllNavNum'); 13 | } else { 14 | // 中介者发布显示消息提醒功能消息 15 | Mediator.send('showAllNavNum'); 16 | } 17 | }; 18 | // 网址选框事件 19 | hideUrl.onchange = function () { 20 | // 如果勾选 21 | if (hideUrl.checked) { 22 | // 中介者发布隐藏所有网址功能消息 23 | Mediator.send('hideAllNavUrl'); 24 | } else { 25 | // 中介者发布显示所有网址功能消息 26 | Mediator.send('showAllNavUrl'); 27 | } 28 | }; 29 | })() 30 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_24备忘录模式/24.3新闻缓存器.js: -------------------------------------------------------------------------------- 1 | // 显示某页逻辑 2 | function showPage(page, data) { 3 | } 4 | 5 | // Page备忘录类 6 | var Page = function () { 7 | // 信息缓存对象 8 | var cache = {}; 9 | /** 10 | * 主函数 11 | * 参数page页码 12 | * 参数fn成功回调函数 13 | */ 14 | return function (page, fn) { 15 | // 判断该页数据是否在缓存中 16 | if (cache[page]) { 17 | // 恢复到该页状态,显示该页内容 18 | showPage(page, cache[page]); 19 | // 执行成功回调函数 20 | fn && fn(); 21 | } else { 22 | // 若缓存Cache中无该页数据 23 | $.post('./data/getNewsData.php', { 24 | // 请求携带的参数 25 | page : page 26 | }, function (res) { 27 | // 成功返回 28 | if (res.errNo == 0) { 29 | // 显示该页数据 30 | showPage(page, res.data); 31 | // 将该页数据种入缓存中 32 | cache[page] = res.data; 33 | // 执行回调 34 | fn && fn(); 35 | } else { 36 | // 处理异常 37 | } 38 | }) 39 | 40 | } 41 | } 42 | }(); 43 | 44 | // 下一页按钮点击事件 45 | $('#next_page').click(function () { 46 | // 获取新闻内容元素 47 | var $news = $('#news_content'), 48 | //获取新闻内容元素当前页数据 49 | page = $news.data('page'); 50 | // 获取并显示新闻 51 | Page(page, function () { 52 | // 修正新闻内容元素当前页内容 53 | $news.data('page', page + 1); 54 | }) 55 | }); 56 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_25迭代器模式/25.2迭代器.js: -------------------------------------------------------------------------------- 1 | // 迭代器 2 | var Iterator = function (items, container) { 3 | // 获取父容器,若container参数存在,并且可以获取该元素则获取,否则获取document 4 | var container = container && document.getElementById(container) || document, 5 | // 获取元素 6 | items = container.getElementsByTagName(items), 7 | // 获取元素长度 8 | length = items.length, 9 | // 当前索引值,默认:0 10 | index = 0, 11 | // 缓存源生数组splice方法 12 | splice = [].splice; 13 | return { 14 | // 获取第一个元素 15 | first : function () { 16 | index = 0; // 校正当前索引 17 | return items[index]; //获取第一个元素 18 | }, 19 | // 获取最后一个元素 20 | second : function () { 21 | index = length -1; 22 | return items[index]; 23 | }, 24 | // 获取前一个元素 25 | pre : function () { 26 | if (--index > 0) { 27 | return items[index]; 28 | } else { 29 | index = 0; 30 | return null; 31 | } 32 | }, 33 | // 获取后一个元素 34 | next : function () { 35 | if (++index < length) { 36 | return items[index]; 37 | } else { 38 | index = length -1; 39 | return null; 40 | } 41 | }, 42 | // 获取某一个元素 43 | get : function (num) { 44 | // 如果num大于等于0再获取正向获取,否则逆向获取 45 | index = num >= 0 ? num % length : num % length + length; 46 | // 返回对应元素 47 | return items[index]; 48 | }, 49 | // 对每一个元素执行某一个方法 50 | dealEach : function (fn) { 51 | // 第二个参数开始为回调函数中参数 52 | var args = splice.call(arguments, 1); 53 | // 遍历元素 54 | for(var i = 0; i < length; i++){ 55 | // 对元素执行回调函数 56 | fn.apply(items[i], args); 57 | } 58 | }, 59 | // 对某一个元素执行某一个方法 60 | dealItem : function (num, fn) { 61 | // 对元素执行回调函数,注:1第三个参数开始为回调函数中参数 2通过this.get方法设置index索引值 62 | fn.apply(this.get(num), splice.call(arguments, 2)) 63 | }, 64 | // 排他方式处理某一个元素 65 | exclusive : function (num, allFn, numFn) { 66 | // 对所有元素执行回调函数 67 | this.dealEach(allFn); 68 | // 如果num类型为数组 69 | if (Object.prototype.toString.call(num) === '[object Array]') { 70 | // 遍历数组 71 | for(var i = 0, len = num.length; i < len; i++){ 72 | // 分别处理数组中每一个元素 73 | this.dealItem(num[i], numFn); 74 | } 75 | } else { 76 | // 处理第num个元素 77 | this.dealItem(num, numFn); 78 | } 79 | } 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_26解释器模式/26.4同级兄弟元素遍历.js: -------------------------------------------------------------------------------- 1 | // 获取兄弟元素名称 2 | function getSublingName(node) { 3 | // 如果存在兄弟元素 4 | if (node.previousSibling) { 5 | var name = '', 6 | count = 1, 7 | nodeName = node.nodeName, 8 | sibling = node.previousSibling; 9 | // 如果存在前一个兄弟元素 10 | while (sibling){ 11 | // 如果节点为元素 并且节点类型与前一个兄弟元素类型相同,并且前一个兄弟元素名称存在 12 | if (sibling.nodeType == 1 && sibling.nodeType === node.nodeType && sibling.nodeName) { 13 | // 如果节点名称和前一个兄弟元素名称相同 14 | if (nodeName == sibling.nodeName) { 15 | // 节点名称后面添加计数 16 | name += ++count; 17 | } else { 18 | // 重置相同紧邻几点名称节点个数 19 | count = 1; 20 | // 追加新的节点名称 21 | name += '|' + sibling.nodeName.toUpperCase(); 22 | } 23 | } 24 | // 向前获取前一个兄弟元素 25 | sibling = sibling.previousSibling; 26 | } 27 | return name; 28 | } else { 29 | return ''; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_26解释器模式/26.5遍历文档树.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /4-行为型设计模式/chapter_26解释器模式/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $Title$ 6 | 7 | 8 | $END$ 9 | 10 | -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_28委托模式/28.4内存外泄.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_29数据访问对象模式/29.10连接MongoDB.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_29数据访问对象模式/29.11操作集合.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_29数据访问对象模式/29.2数据访问对象类.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_29数据访问对象模式/29.9node配置项.js: -------------------------------------------------------------------------------- 1 | 2 | // config.js 3 | // 将配置数据输出 4 | module.exports = { 5 | // 数据库相关配置数据 6 | DB : { 7 | db : 'demo', // 数据库名称 8 | host : 'localhost', // 主机名 9 | port : 27017 // 端口号 10 | } 11 | } -------------------------------------------------------------------------------- /5-技巧型设计模式/chapter_30节流模式/30.2节流器.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 《javascript设计模式》--张容铭(源码和学习总结) 2 | 3 | 参考资料:《javascript设计模式》--张容铭 4 | 内容主要包含本书的全部源码,并包含了书内知识点的摘录和总结 5 | 6 | ####第一篇 面向对象编程 7 | 8 | - 第1章 灵活的语言-介绍JS语言 9 | 10 | - 第2章 写的都是看到的-面向对象编程 11 | 类、闭包、安全模式、类式继承、构造函数继承、原型继承、寄生继承、寄生组合式继承、单继承、多态 12 | 13 | ####第二篇 创建型设计模式 14 | 15 | - 第3章 神奇的魔术师-简单工厂模式 16 | 17 | - 第4章 给我一张名片-工厂方法模式 18 | 安全工厂模式 19 | 20 | - 第5章 出现的都是幻觉-抽象工厂模式 21 | 抽象出公共方法,在公共方法中return new Error() 22 | 23 | - 第6章 分即是合-建造者模式-简历模块 24 | 根据传参在构造函数中使用switch判断进行相应的处理 25 | 26 | - 第7章 语言之魂-原型模式-焦点图 27 | 用原型实例指向创建对象的类,使用于创建新的对象的类共享原型对象的属性以及方法 28 | 29 | - 第8章 一个人的寂寞-单例模式-滑动模块命名空间 30 | 只允许实例化一次的对象类 31 | 第三篇结构型设计模式 32 | 33 | ####第三篇 结构型设计模式 34 | - 第9章 套餐服务-外观模式-绑定事件 35 | 为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。在JavaScript中有时也会用于对底层结构兼容性做统一封装来简化用户作用 36 | 37 | - 第10章 水管弯弯-适配器模式 38 | 将一个类(对象)的接口转化成另外一个接口,以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决 39 | 40 | - 第11章 牛郎织女-代理模式-图片跨域 41 | 由于一个对象不能直接饮用另一个对象,所以需要通过代理对象在这两个对象之间起到中介的作用 42 | 43 | - 第12章 房子装修-装饰者模式-输入框 44 | 在不改变原对象的基础上,通过对其惊醒包装拓展(添加属性或方法)使原有对象可以满足用户的更复杂需求 45 | 46 | - 第13章 城市间的公路-桥接模式-用户信息模块 47 | 在系统沿着多个维度变化的同时,又不增加其复杂度并已达到解耦 48 | 49 | - 第14章 超值午餐-组合模式-新闻模块 50 | 又称整体模式,将对象组合成树形结构以表示“部分整体”的层次机构,组合模式使得用户对单个对象和组合对象的使用具有一致性 51 | 52 | - 第15章 城市公交车-享元模式-分页 53 | 运用共享技术有效地支持大量的细粒度的对象,避免对象间拥有相同内容造成多余的开销 54 | 55 | ####第四篇 行为型设计模式 56 | 57 | 58 | - 第16章 照猫画虎-模板方法模式-提示框 59 | 父类中定义一组操作算法骨架,而将一些实现步骤延迟到子类中,使得子类可以不改变父类的算法结构的同时可重新定义算法中的某些实现步骤 60 | 61 | - 第17章 通信卫星-观察者模式-留言模块 62 | 又称作发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间的功能的耦合 63 | (17.6源码编写有问题,应该html部分有没写到的地方) 64 | 65 | - 第18章 超级玛丽-状态模式-多种状态判断 66 | 当一个对象的内部状态发生改变时,会导致其行为的改变 67 | 68 | - 第19章 活诸葛-策略模式-状态模式的升级、表单验证 69 | 将定义的一组算法封装起来,使其相互之间可以替换 70 | 71 | - 第20章 有序车站-职责链模式-请求相应操作分开 72 | 解决请求的发送者与请求的接收者之间的耦合,通过职责链上的多个对象对分解请求 流程,实现请求在多个对象之间的传递,知道一个对象完成请求的处理 73 | 74 | - 第21章 命令模式-图片展示 -将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数化 75 | 76 | - 第22章 驻华大使-访问者模式-ie绑定事件,类数组对象有序操作属性 77 | 针对于对象的结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法 78 | 79 | - 第23章 媒婆-中介者模式-导航模块设置层样式 80 | 通过中介者对象封装一系列对象之间的交互,使对象之间不相互作用,降低他们之间的耦合。有时中介者对象也可改变对象之间的交互 81 | 82 | - 第24章 做好笔录-备忘录模式-对请求之前的数据进行缓存 83 | 在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态 84 | 85 | - 第25章 点钞机-迭代器模式-编写循环DOM节点函数,获取DOM 86 | 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素 87 | 88 | - 第26章 语言翻译-解释器模式-Xpath解析器 89 | 对于一种语言,给出其文法表示形式,并定义一种解释器,通过使用这种解释器来解释语言中定义的句子 90 | 91 | ####第五篇 技巧型设计模式 92 | 93 | - 第27章 永无尽头-链模式-jquery链式编程 94 | 通过在对象方法中将当前对象返回,实现对统一个对象多个方法的链式调用。从而简化对该对象的多个方法的多次调用时,对该对象的多次引用 95 | //jquery链式编程的实现,就不写代码了 96 | 97 | - 第28章 未来预言家-委托模式-事件委托 98 | 多个对象接收并处理同一请求,他们将请求委托给另一个对象同一处理请求 99 | 100 | - 第29章 数据管理器-数据访问对象模式-LocalStorage本地存储数据管理 101 | 抽离和封装对数据源的访问与存储,DAO通过对数据源链接的管理方便对数据的访问与存储 102 | 103 | - 第30章 执行控制-节流模式-滚动事件只执行第一次 104 | 对重复的业务逻辑进行节流控制,执行最后一次操作并取消其他操作,以提高性能 105 | 106 | - 第31章 卡片拼图-简单模板模式 107 | 108 | - 第32章 机器学习-惰性模式 109 | 110 | - 第33章 异国战场-参与者模式 111 | 112 | - 第34章 入场仪式-等待者模式 113 | 114 | - 第六篇架构型设计模式 115 | 116 | - 第35章 死心眼-同步模块模式 117 | 118 | - 第36章 大心脏-异步模块模式 119 | 120 | - 第37章 分而治之-Widget模式 121 | 122 | - 第38章 三人行-MVC模式 123 | 124 | - 第39章 三军统帅-MVP模式 125 | 126 | - 第40章 视图的逆袭-MVVM模式 127 | 128 | ##常用的设计模式 129 | [腾讯团队常用设计模式](http://www.alloyteam.com/2012/10/common-javascript-design-patterns/) 130 | 131 | - 单例模式 132 | - 简单工厂模式 133 | - 观察者模式 134 | - 适配器模式 135 | - 代理模式 136 | - 桥接模式 137 | - 外观模式 138 | - 访问者模式 139 | - 策略模式 140 | - 模版方法模式 141 | - 中介者模式 142 | - 迭代器模式 143 | - 组合模式 144 | - 备忘录模式 145 | - 职责链模式 146 | - 享元模式 147 | - 状态模式 148 | 149 | [Tom大叔的博客设计模式](http://www.cnblogs.com/TomXu/tag/JavaScript/default.html?page=1) --------------------------------------------------------------------------------