├── Command ├── Command-ES6.js ├── Command.js ├── index-ES6.html └── index.html ├── Constructor ├── Constructor.js └── index.html ├── Decorator ├── Decorator-ES6.js ├── Decorator.js ├── index-ES6.html └── index.html ├── Facade ├── Facade-ES6.js ├── Facade.js └── index-ES6.html ├── Factory ├── Factory-ES6.js ├── Factory.js ├── index-ES6.html └── index.html ├── Flyweight ├── Flyweight-ES6.js ├── Flyweight.js ├── flyweight-in-jquery.html └── index.html ├── Mediator └── Mediator.js ├── Mixin ├── Mixin-ES6.js ├── Mixin.js ├── index-ES6.html └── index.html ├── Module ├── Module-ES6.js ├── Module.js ├── index.html └── module-in-jquery.html ├── Observer ├── Observer-ES6.js ├── Observer.js ├── Publish-Subscribe-ES6.js ├── Publish-Subscribe.js ├── index.html └── publish-subcribe.html ├── README.md ├── Revealing ├── Revealing.js └── index.html ├── Singleton ├── SingLeton.js ├── Singleton-ES6.js └── index.html └── jqueryPlugin ├── Lightweight-Start.js ├── WidgetFactory.js └── index.html /Command/Command-ES6.js: -------------------------------------------------------------------------------- 1 | //命令行模式 2 | class CarManager { 3 | requestInfo(model, id) { 4 | return "The information for " + model + " with ID " + id + " is foobar"; 5 | } 6 | 7 | // purchase the car 8 | buyVehicle(model, id) { 9 | return "You have successfully purchased Item " + id + ", a " + model; 10 | } 11 | 12 | // arrange a viewing 13 | arrangeViewing(model, id) { 14 | return "You have successfully booked a viewing of " + model + " ( " + id + ") "; 15 | } 16 | execute(name) { 17 | let carManager = new CarManager(); 18 | return carManager[name] && carManager[name].apply(carManager, [].slice.call(arguments, 1)); 19 | } 20 | } 21 | 22 | let carManager = new CarManager(); 23 | 24 | console.log(carManager.execute("arrangeViewing", "Ferrari", "14523")); 25 | 26 | console.log(carManager.execute("requestInfo", "Ford Mondeo", "54323")); 27 | 28 | console.log(carManager.execute("requestInfo", "Ford Escort", "34232")); 29 | -------------------------------------------------------------------------------- /Command/Command.js: -------------------------------------------------------------------------------- 1 | //命令行模式 2 | 3 | (function() { 4 | var CarManager = { 5 | // request information 6 | requestInfo: function(model, id) { 7 | return "The information for " + model + " with ID " + id + " is foobar"; 8 | }, 9 | 10 | // purchase the car 11 | buyVehicle: function(model, id) { 12 | return "You have successfully purchased Item " + id + ", a " + model; 13 | }, 14 | 15 | // arrange a viewing 16 | arrangeViewing: function(model, id) { 17 | return "You have successfully booked a viewing of " + model + " ( " + id + ") "; 18 | } 19 | 20 | }; 21 | 22 | CarManager.execute = function(name) { 23 | return CarManager[name] && CarManager[name].apply(CarManager, [].slice.call(arguments, 1)); 24 | }; 25 | 26 | console.log(CarManager.execute("arrangeViewing", "Ferrari", "14523")); 27 | console.log(CarManager.execute("requestInfo", "Ford Mondeo", "54323")); 28 | console.log(CarManager.execute("requestInfo", "Ford Escort", "34232")); 29 | console.log(CarManager.execute("buyVehicle", "Ford Escort", "34232")); 30 | })(); 31 | -------------------------------------------------------------------------------- /Command/index-ES6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Command/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Constructor/Constructor.js: -------------------------------------------------------------------------------- 1 | //构造器模式 2 | 3 | //============================================================================== 4 | // Each of the following options will create a new empty object: 5 | // 构造空对象 6 | var newObject = {}; 7 | // or 8 | var newObject = Object.create(null); 9 | // or 10 | var newObject = new Object(); 11 | 12 | /******************ES 3******************************/ 13 | // 1. Dot syntax 14 | 15 | // Set properties 16 | newObject.someKey = "Hello World"; 17 | // Get properties 18 | var key = newObject.someKey; 19 | 20 | // 2. Square bracket syntax 21 | 22 | // Set properties 23 | newObject["someKey"] = "Hello World"; 24 | // Get properties 25 | var key = newObject["someKey"]; 26 | 27 | /******************ES 5******************************/ 28 | // 3.Object.defineProperty 29 | Object.defineProperty(newObject, "someKey", { 30 | value: "for more control of the property's behavior", 31 | wirtable: true, 32 | enumerable: true, 33 | configurable: true 34 | }); 35 | 36 | // 4.Object.defineProperties 37 | // 设置属性 38 | Object.defineProperties(newObject, { 39 | "someKey": { 40 | value: "Hello World", 41 | writable: true 42 | }, 43 | "anotherKey": { 44 | value: "Foo bar", 45 | writable: false 46 | } 47 | }); 48 | 49 | 50 | console.log(newObject); 51 | //============================================================================== 52 | // 1.基本的Constructor 53 | function Car(model, year, miles) { 54 | this.model = model; 55 | this.year = year; 56 | this.miles = miles; 57 | 58 | this.toString = function() { 59 | return this.model + " has done " + this.miles + " miles"; 60 | }; 61 | } 62 | // Usage: 63 | // We can create new instances of the car 64 | var civic = new Car("Honda Civic", 2009, 20000); 65 | var mondeo = new Car("Ford Mondeo", 2010, 5000); 66 | 67 | console.log(civic.toString()); 68 | console.log(mondeo.toString()); 69 | //继承比较困难 70 | 71 | // 2.带原型的Constructor 72 | function Car1(model, year, miles) { 73 | this.model = model; 74 | this.year = year; 75 | this.miles = miles; 76 | } 77 | 78 | // Note here that we are using Object.prototype.newMethod rather than 79 | // Object.prototype so as to avoid redefining the prototype object 80 | Car1.prototype.toString = function() { 81 | return this.model + " has done " + this.miles + " miles"; 82 | }; 83 | // Usage: 84 | var civic = new Car1( "Honda Civic", 2009, 20000 ); 85 | var mondeo = new Car1( "Ford Mondeo", 2010, 5000 ); 86 | console.log( civic.toString() ); 87 | console.log( mondeo.toString() ); 88 | 89 | -------------------------------------------------------------------------------- /Constructor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Decorator/Decorator-ES6.js: -------------------------------------------------------------------------------- 1 | //装饰者模式 2 | 3 | class MacBook { 4 | cost() { 5 | return 997; 6 | } 7 | screenSize() { 8 | return 11.6; 9 | } 10 | } 11 | 12 | function Memory(macbook) { 13 | 14 | let v = macbook.cost(); 15 | macbook.cost = function() { 16 | return v + 75; 17 | }; 18 | 19 | } 20 | 21 | // Decorator 2 22 | function Engraving(macbook) { 23 | 24 | let v = macbook.cost(); 25 | macbook.cost = function() { 26 | return v + 200; 27 | }; 28 | 29 | } 30 | 31 | // Decorator 3 32 | function Insurance(macbook) { 33 | 34 | let v = macbook.cost(); 35 | macbook.cost = function() { 36 | return v + 250; 37 | }; 38 | 39 | } 40 | 41 | let mb = new MacBook(); 42 | Memory(mb); 43 | Engraving(mb); 44 | Insurance(mb); 45 | 46 | // Outputs: 1522 47 | console.log(mb.cost()); 48 | // Outputs: 11.6 49 | console.log(mb.screenSize()); -------------------------------------------------------------------------------- /Decorator/Decorator.js: -------------------------------------------------------------------------------- 1 | //装饰者模式 2 | 3 | // A vehicle constructor 4 | function vehicle(vehicleType) { 5 | 6 | // some sane defaults 7 | this.vehicleType = vehicleType || "car"; 8 | this.model = "default"; 9 | this.license = "00000‐000"; 10 | 11 | } 12 | 13 | // Test instance for a basic vehicle 14 | var testInstance = new vehicle("car"); 15 | console.log(testInstance); 16 | 17 | // Outputs: 18 | // vehicle: car, model:default, license: 00000‐000 19 | 20 | // Lets create a new instance of vehicle, to be decorated 21 | var truck = new vehicle("truck"); 22 | 23 | // New functionality we're decorating vehicle with 24 | truck.setModel = function(modelName) { 25 | this.model = modelName; 26 | }; 27 | 28 | truck.setColor = function(color) { 29 | this.color = color; 30 | }; 31 | 32 | // Test the value setters and value assignment works correctly 33 | truck.setModel("CAT"); 34 | truck.setColor("blue"); 35 | 36 | console.log(truck); 37 | 38 | // Outputs: 39 | // vehicle:truck, model:CAT, color: blue 40 | 41 | // Demonstrate "vehicle" is still unaltered 42 | var secondInstance = new vehicle("car"); 43 | console.log(secondInstance); 44 | 45 | // Outputs: 46 | // vehicle: car, model:default, license: 00000‐000 47 | 48 | //===================================================================== 49 | console.log("==================================="); 50 | // The constructor to decorate 51 | function MacBook() { 52 | 53 | this.cost = function() { 54 | return 997; }; 55 | this.screenSize = function() { 56 | return 11.6; }; 57 | 58 | } 59 | 60 | // Decorator 1 61 | function Memory(macbook) { 62 | 63 | var v = macbook.cost(); 64 | macbook.cost = function() { 65 | return v + 75; 66 | }; 67 | 68 | } 69 | 70 | // Decorator 2 71 | function Engraving(macbook) { 72 | 73 | var v = macbook.cost(); 74 | macbook.cost = function() { 75 | return v + 200; 76 | }; 77 | 78 | } 79 | 80 | // Decorator 3 81 | function Insurance(macbook) { 82 | 83 | var v = macbook.cost(); 84 | macbook.cost = function() { 85 | return v + 250; 86 | }; 87 | 88 | } 89 | 90 | var mb = new MacBook(); 91 | Memory(mb); 92 | Engraving(mb); 93 | Insurance(mb); 94 | 95 | // Outputs: 1522 96 | console.log(mb.cost()); 97 | 98 | // Outputs: 11.6 99 | console.log(mb.screenSize()); 100 | -------------------------------------------------------------------------------- /Decorator/index-ES6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Decorator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Facade/Facade-ES6.js: -------------------------------------------------------------------------------- 1 | //装饰者模式 2 | class Facade { 3 | _get() { 4 | console.log("current value:" + this.i); 5 | } 6 | _set(val) { 7 | this.i = val; 8 | } 9 | _run() { 10 | console.log("running"); 11 | } 12 | _jump() { 13 | console.log("jumping"); 14 | } 15 | 16 | facade(args) { 17 | this._set(args.val); 18 | this._get(); 19 | if (args._run) { 20 | this._run(); 21 | } 22 | } 23 | } 24 | 25 | let fa = new Facade(); 26 | fa.facade({ run: true, val: 10 }); 27 | -------------------------------------------------------------------------------- /Facade/Facade.js: -------------------------------------------------------------------------------- 1 | var module = (function() { 2 | 3 | var _private = { 4 | i: 5, 5 | get: function() { 6 | console.log("current value:" + this.i); 7 | }, 8 | set: function(val) { 9 | this.i = val; 10 | }, 11 | run: function() { 12 | console.log("running"); 13 | }, 14 | jump: function() { 15 | console.log("jumping"); 16 | } 17 | }; 18 | 19 | return { 20 | 21 | facade: function(args) { 22 | _private.set(args.val); 23 | _private.get(); 24 | if (args.run) { 25 | _private.run(); 26 | } 27 | } 28 | }; 29 | }()); 30 | 31 | 32 | // Outputs: "current value: 10" and "running" 33 | module.facade({ run: true, val: 10 }); 34 | -------------------------------------------------------------------------------- /Facade/index-ES6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Facade 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Factory/Factory-ES6.js: -------------------------------------------------------------------------------- 1 | //工厂模式使用ES6实现 2 | 3 | //工厂 4 | class VehicleFactory { 5 | constructor() { 6 | this.vehicleClass = Car; 7 | } 8 | createVehicle(options) { 9 | if (options.vehicleType === "car") { 10 | this.vehicleClass = Car; 11 | } else { 12 | this.vehicleClass = Truck; 13 | } 14 | return new this.vehicleClass(options); 15 | } 16 | } 17 | 18 | class Car { 19 | constructor(options) { 20 | // some defaults 21 | options = options || ""; 22 | this.doors = options.doors || 4; 23 | this.state = options.state || "brand new"; 24 | this.color = options.color || "silver"; 25 | } 26 | } 27 | 28 | 29 | class Truck { 30 | constructor(options) { 31 | this.state = options.state || "used"; 32 | this.wheelSize = options.wheelSize || "large"; 33 | this.color = options.color || "blue"; 34 | } 35 | } 36 | 37 | //usage 38 | let carFactory = new VehicleFactory(); 39 | let car = carFactory.createVehicle({ 40 | vehicleType: "car", 41 | color: "yellow", 42 | doors: 6 43 | }); 44 | 45 | // Test to confirm our car was created using the vehicleClass/prototype Car 46 | 47 | // Outputs: true 48 | console.log(car instanceof Car); 49 | 50 | // Outputs: Car object of color "yellow", doors: 6 in a "brand new" state 51 | console.log(car); 52 | 53 | 54 | 55 | //=================================================================== 56 | //抽象工厂 57 | class AbstractVehicleFactory { 58 | constructor() { 59 | this.types = {}; //存储对象 60 | } 61 | getVehicle(type, customizations) { 62 | let Vehicle = this.types[type]; 63 | return (Vehicle ? new Vehicle(customizations) : null); 64 | } 65 | 66 | registerVehicle(type, Vehicle) { 67 | let proto = Vehicle.prototype; 68 | // only register classes that fulfill the vehicle contract 69 | // if (proto.drive && proto.breakDown) { 70 | this.types[type] = Vehicle; 71 | // } 72 | 73 | return AbstractVehicleFactory; 74 | } 75 | } 76 | let abstractVehicleFactory = new AbstractVehicleFactory(); 77 | 78 | abstractVehicleFactory.registerVehicle("car", Car); 79 | abstractVehicleFactory.registerVehicle("truck", Truck); 80 | 81 | // Instantiate a new car based on the abstract vehicle type 82 | var car2 = abstractVehicleFactory.getVehicle("car", { 83 | color: "lime green", 84 | state: "like new" 85 | }); 86 | 87 | // Instantiate a new truck in a similar manner 88 | var truck2 = abstractVehicleFactory.getVehicle("truck", { 89 | wheelSize: "medium", 90 | color: "neon yellow" 91 | }); 92 | 93 | 94 | 95 | console.log(car2,truck2); 96 | 97 | console.log(abstractVehicleFactory); 98 | console.log(Object.getPrototypeOf(abstractVehicleFactory)); -------------------------------------------------------------------------------- /Factory/Factory.js: -------------------------------------------------------------------------------- 1 | // 工厂模式 2 | // Types.js ‐ Constructors used behind the scenes 3 | 4 | // A constructor for defining new cars 5 | function Car(options) { 6 | // some defaults 7 | this.doors = options.doors || 4; 8 | this.state = options.state || "brand new"; 9 | this.color = options.color || "silver"; 10 | 11 | } 12 | 13 | // A constructor for defining new trucks 14 | function Truck(options) { 15 | this.state = options.state || "used"; 16 | this.wheelSize = options.wheelSize || "large"; 17 | this.color = options.color || "blue"; 18 | } 19 | 20 | 21 | // FactoryExample.js 22 | 23 | // Define a skeleton vehicle factory 24 | function VehicleFactory() {} 25 | 26 | // Define the prototypes and utilities for this factory 27 | 28 | // Our default vehicleClass is Car 29 | VehicleFactory.prototype.vehicleClass = Car; 30 | 31 | // Our Factory method for creating new Vehicle instances 32 | VehicleFactory.prototype.createVehicle = function(options) { 33 | 34 | if (options.vehicleType === "car") { 35 | this.vehicleClass = Car; 36 | } else { 37 | this.vehicleClass = Truck; 38 | } 39 | 40 | return new this.vehicleClass(options); 41 | 42 | }; 43 | 44 | // Create an instance of our factory that makes cars 45 | var carFactory = new VehicleFactory(); 46 | var car = carFactory.createVehicle({ 47 | vehicleType: "car", 48 | color: "yellow", 49 | doors: 6 50 | }); 51 | 52 | // Test to confirm our car was created using the vehicleClass/prototype Car 53 | 54 | // Outputs: true 55 | console.log(car instanceof Car); 56 | 57 | // Outputs: Car object of color "yellow", doors: 6 in a "brand new" state 58 | console.log(car); 59 | 60 | 61 | //================================================================================ 62 | //抽象工厂 63 | var AbstractVehicleFactory = (function() { 64 | 65 | // Storage for our vehicle types 66 | var types = {}; 67 | 68 | return { 69 | getVehicle: function(type, customizations) { 70 | var Vehicle = types[type]; 71 | return (Vehicle ? new Vehicle(customizations) : null); 72 | }, 73 | 74 | registerVehicle: function(type, Vehicle) { 75 | var proto = Vehicle.prototype; 76 | // only register classes that fulfill the vehicle contract 77 | if (proto.drive && proto.breakDown) { 78 | types[type] = Vehicle; 79 | } 80 | 81 | return AbstractVehicleFactory; 82 | } 83 | }; 84 | })(); 85 | 86 | Car.prototype.drive = function(){} 87 | Truck.prototype.drive = function(){} 88 | Car.prototype.breakDown = function(){} 89 | Truck.prototype.breakDown = function(){} 90 | 91 | // Usage: 92 | 93 | AbstractVehicleFactory.registerVehicle("car", Car); 94 | AbstractVehicleFactory.registerVehicle("truck", Truck); 95 | 96 | // Instantiate a new car based on the abstract vehicle type 97 | var car2 = AbstractVehicleFactory.getVehicle("car", { 98 | color: "lime green", 99 | state: "like new" 100 | }); 101 | 102 | // Instantiate a new truck in a similar manner 103 | var truck2 = AbstractVehicleFactory.getVehicle("truck", { 104 | wheelSize: "medium", 105 | color: "neon yellow" 106 | }); 107 | 108 | console.log(car2,truck2); -------------------------------------------------------------------------------- /Factory/index-ES6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Factory/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Flyweight/Flyweight-ES6.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zrysmt/javascript-design-pattern/ecb4288cb8bce7b4ba00dd4bd56f5d36e3971085/Flyweight/Flyweight-ES6.js -------------------------------------------------------------------------------- /Flyweight/Flyweight.js: -------------------------------------------------------------------------------- 1 | //享元模式 2 | 3 | //在js模拟存虚拟的继承,类似java中的implements 4 | Function.prototype.implementsFor = function(parentClassOrObject) { 5 | if (parentClassOrObject.constructor === Function) { 6 | this.prototype = new parentClassOrObject(); 7 | this.prototype.consturctor = this; 8 | this.prototype.parent = parentClassOrObject.prototype; 9 | }else { 10 | //纯虚拟继承 11 | this.prototype = parentClassOrObject; 12 | this.prototype.constructor = this; 13 | this.prototype.parent = parentClassOrObject; 14 | } 15 | } 16 | 17 | // Flyweight object 享元对象 18 | var CoffeeOrder = { 19 | // Interfaces 接口 20 | serveCoffee: function(context) {}, 21 | getFlavor: function() {} 22 | }; 23 | 24 | 25 | // ConcreteFlyweight object that creates ConcreteFlyweight 具体享元对象 26 | // Implements CoffeeOrder 27 | function CoffeeFlavor(newFlavor) { 28 | 29 | var flavor = newFlavor; 30 | 31 | // If an interface has been defined for a feature 32 | // implement the feature 33 | if (typeof this.getFlavor === "function") { 34 | this.getFlavor = function() { 35 | return flavor; 36 | }; 37 | } 38 | 39 | if (typeof this.serveCoffee === "function") { 40 | this.serveCoffee = function(context) { 41 | console.log("Serving Coffee flavor " + flavor + " to table number " + context.getTable()); 42 | }; 43 | } 44 | 45 | } 46 | 47 | 48 | // Implement interface for CoffeeOrder 实现接口 49 | CoffeeFlavor.implementsFor(CoffeeOrder); 50 | 51 | 52 | // Handle table numbers for a coffee order 53 | // tableNumber 订单数 辅助器 54 | function CoffeeOrderContext(tableNumber) { 55 | return { 56 | getTable: function() { 57 | return tableNumber; 58 | } 59 | }; 60 | } 61 | 62 | //享元工厂对象 63 | //创建并管理flyweight对象 64 | function CoffeeFlavorFactory() { 65 | var flavors = {}, 66 | length = 0; 67 | 68 | return { 69 | getCoffeeFlavor: function(flavorName) { 70 | //这是个单例模式 71 | var flavor = flavors[flavorName]; 72 | if (flavor === undefined) { 73 | flavor = new CoffeeFlavor(flavorName);//创建flyweight对象 74 | flavors[flavorName] = flavor; 75 | length++; 76 | } 77 | return flavor; 78 | }, 79 | 80 | getTotalCoffeeFlavorsMade: function() { 81 | return length; 82 | } 83 | }; 84 | } 85 | 86 | // Sample usage: 测试 87 | testFlyweight() 88 | 89 | function testFlyweight() { 90 | // The flavors ordered. 已订购的flavors 91 | var flavors = new CoffeeFlavor(), 92 | // The tables for the orders. 93 | tables = new CoffeeOrderContext(), 94 | // Number of orders made 订单数量 95 | ordersMade = 0, 96 | // The CoffeeFlavorFactory instance 97 | flavorFactory; 98 | //flavorIn 订单物的名称 99 | function takeOrders(flavorIn, table) { 100 | flavors[ordersMade] = flavorFactory.getCoffeeFlavor(flavorIn); 101 | //flavorFactory管理者创建好后(管理者也做了处理)返回给CoffeeFlavor 102 | tables[ordersMade++] = new CoffeeOrderContext(table); 103 | } 104 | 105 | flavorFactory = new CoffeeFlavorFactory(); 106 | 107 | takeOrders("Cappuccino", 2); 108 | takeOrders("Cappuccino", 2); 109 | takeOrders("Frappe", 1); 110 | takeOrders("Frappe", 1); 111 | takeOrders("Xpresso", 1); 112 | takeOrders("Frappe", 897); 113 | takeOrders("Cappuccino", 97); 114 | takeOrders("Cappuccino", 97); 115 | takeOrders("Frappe", 3); 116 | takeOrders("Xpresso", 3); 117 | takeOrders("Cappuccino", 3); 118 | takeOrders("Xpresso", 96); 119 | takeOrders("Frappe", 552); 120 | takeOrders("Cappuccino", 121); 121 | takeOrders("Xpresso", 121); 122 | 123 | for (var i = 0; i < ordersMade; ++i) { 124 | flavors[i].serveCoffee(tables[i]); 125 | } 126 | console.log(" "); 127 | console.log("total CoffeeFlavor objects made: " + flavorFactory.getTotalCoffeeFlavorsMade()); 128 | } 129 | -------------------------------------------------------------------------------- /Flyweight/flyweight-in-jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | click me 11 |
hello
12 | 13 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Flyweight/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Mediator/Mediator.js: -------------------------------------------------------------------------------- 1 | //中介者模式 2 | //类似观察者模式 3 | 4 | var mediator = (function() { 5 | // Storage for topics that can be broadcast or listened to 6 | var topics = {}; 7 | 8 | // Subscribe to a topic, supply a callback to be executed 9 | // when that topic is broadcast to 10 | var subscribe = function(topic, fn) { 11 | 12 | if (!topics[topic]) { 13 | topics[topic] = []; 14 | } 15 | 16 | topics[topic].push({ context: this, callback: fn }); 17 | 18 | return this; 19 | }; 20 | 21 | // Publish/broadcast an event to the rest of the application 22 | var publish = function(topic) { 23 | 24 | var args; 25 | 26 | if (!topics[topic]) { 27 | return false; 28 | } 29 | 30 | args = Array.prototype.slice.call(arguments, 1); 31 | for (var i = 0, l = topics[topic].length; i < l; i++) { 32 | 33 | var subscription = topics[topic][i]; 34 | subscription.callback.apply(subscription.context, args); 35 | } 36 | return this; 37 | }; 38 | 39 | return { 40 | publish: publish, 41 | subscribe: subscribe, 42 | installTo: function(obj) { 43 | obj.subscribe = subscribe; 44 | obj.publish = publish; 45 | } 46 | }; 47 | 48 | }()); 49 | -------------------------------------------------------------------------------- /Mixin/Mixin-ES6.js: -------------------------------------------------------------------------------- 1 | // 混入模式 2 | //http://es6.ruanyifeng.com/#docs/class#Mixin模式的实现 3 | 4 | function mix(...mixins) { 5 | class Mix {} 6 | 7 | for (let mixin of mixins) { 8 | copyProperties(Mix, mixin); 9 | copyProperties(Mix.prototype, mixin.prototype); 10 | } 11 | 12 | return Mix; 13 | } 14 | 15 | function copyProperties(target, source) { 16 | for (let key of Reflect.ownKeys(source)) { 17 | if ( key !== "constructor" 18 | && key !== "prototype" 19 | && key !== "name" 20 | ) { 21 | let desc = Object.getOwnPropertyDescriptor(source, key); 22 | Object.defineProperty(target, key, desc); 23 | } 24 | } 25 | } 26 | 27 | //使用-继承即可 28 | class DistributedEdit extends mix(Loggable, Serializable) { 29 | // ... 30 | } -------------------------------------------------------------------------------- /Mixin/Mixin.js: -------------------------------------------------------------------------------- 1 | // 混入模式 2 | // Define a simple Car constructor 3 | var Car = function(settings) { 4 | 5 | this.model = settings.model || "no model provided"; 6 | this.color = settings.color || "no colour provided"; 7 | 8 | }; 9 | 10 | // Mixin 11 | var Mixin = function() {}; 12 | 13 | Mixin.prototype = { 14 | 15 | driveForward: function() { 16 | console.log("drive forward"); 17 | }, 18 | 19 | driveBackward: function() { 20 | console.log("drive backward"); 21 | }, 22 | 23 | driveSideways: function() { 24 | console.log("drive sideways"); 25 | } 26 | 27 | }; 28 | 29 | 30 | // Extend an existing object with a method from another 31 | function augment(receivingClass, givingClass) { 32 | 33 | // only provide certain methods 34 | if (arguments[2]) { 35 | for (var i = 2, len = arguments.length; i < len; i++) { 36 | receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; 37 | } 38 | } 39 | // provide all methods 40 | else { 41 | for (var methodName in givingClass.prototype) { 42 | 43 | // check to make sure the receiving class doesn't 44 | // have a method of the same name as the one currently 45 | // being processed 46 | if (!Object.hasOwnProperty(receivingClass.prototype, methodName)) { 47 | receivingClass.prototype[methodName] = givingClass.prototype[methodName]; 48 | } 49 | 50 | // Alternatively: 51 | // if ( !receivingClass.prototype[methodName] ) { 52 | // receivingClass.prototype[methodName] =givingClass.prototype[methodName]; 53 | // } 54 | } 55 | } 56 | } 57 | 58 | 59 | // Augment the Car constructor to include "driveForward" and "driveBackward" 60 | // 只混入两个方法 61 | augment(Car, Mixin, "driveForward", "driveBackward"); 62 | 63 | // Create a new Car 64 | var myCar = new Car({ 65 | model: "Ford Escort", 66 | color: "blue" 67 | }); 68 | 69 | // Test to make sure we now have access to the methods 70 | myCar.driveForward(); 71 | myCar.driveBackward(); 72 | 73 | // Outputs: 74 | // drive forward 75 | // drive backward 76 | 77 | // We can also augment Car to include all functions from our mixin 78 | // by not explicitly listing a selection of them 79 | augment(Car, Mixin); 80 | 81 | var mySportsCar = new Car({ 82 | model: "Porsche", 83 | color: "red" 84 | }); 85 | mySportsCar.driveSideways(); 86 | 87 | // Outputs: 88 | // drive sideways 89 | -------------------------------------------------------------------------------- /Mixin/index-ES6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Mixin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Module/Module-ES6.js: -------------------------------------------------------------------------------- 1 | function Module(container) { 2 | return new class { 3 | get container() { 4 | return container; 5 | } 6 | 7 | init() { 8 | this.container.innerHTML = 'ES6 module'; 9 | } 10 | } 11 | } 12 | 13 | export default Module; 14 | 15 | /*********************************************************/ 16 | let privateName = Symbol('privateName');//利用Symbol做成私有的变量 17 | //直接用class类 18 | class MyModule { 19 | 20 | set container(value) { 21 | this.value = value; 22 | } 23 | 24 | get container() { 25 | return this.value; 26 | } 27 | 28 | init() { 29 | this.value = 'ES6 module'; 30 | } 31 | 32 | [privateName](){ 33 | console.log("hi"); 34 | } 35 | } 36 | 37 | 38 | //usage 39 | let m = new MyModule(); 40 | m.container = "hello"; 41 | console.log(m.container); 42 | m.privateName(); 43 | -------------------------------------------------------------------------------- /Module/Module.js: -------------------------------------------------------------------------------- 1 | //模块模式 2 | 3 | /* 4 | The Module pattern Module模式 5 | Object literal notation 对象字面量表示法 6 | AMD modules 7 | CommonJS modules 8 | ECMAScript Harmony modules 9 | */ 10 | /*********************************************************/ 11 | //1.对象字面量表示法 12 | var myModule = { 13 | myProperty: "someValue", 14 | // object literals can contain properties and methods 15 | // e.g we can define a further object for module configuration: 16 | myConfig: { 17 | useCaching: true, 18 | language: "en" 19 | }, 20 | // a very basic method 21 | myMethod: function() { 22 | console.log("Where in the world is Paul Irish today?"); 23 | }, 24 | // output a value based on the current configuration 25 | myMethod2: function() { 26 | console.log("Caching is:" + (this.myConfig.useCaching) ? "enabled" : "disabled"); 27 | }, 28 | // override the current configuration 29 | myMethod3: function(newConfig) { 30 | if (typeof newConfig === "object") { 31 | this.myConfig = newConfig; 32 | console.log(this.myConfig.language); 33 | } 34 | } 35 | }; 36 | // Outputs: Where in the world is Paul Irish today? 37 | myModule.myMethod(); 38 | // Outputs: enabled 39 | myModule.myMethod2(); 40 | // Outputs: fr 41 | myModule.myMethod3({ 42 | language: "fr", 43 | useCaching: false 44 | }); 45 | /*********************************************************/ 46 | //2.Module(模块)模式 47 | //私有--IIFE模拟 48 | var testModule = (function() { 49 | var counter = 0; 50 | return { 51 | 52 | incrementCounter: function() { 53 | return counter++; 54 | }, 55 | 56 | resetCounter: function() { 57 | console.log("counter value prior to reset: " + counter); 58 | counter = 0; 59 | } 60 | }; 61 | 62 | })(); 63 | 64 | // Usage: 65 | 66 | // Increment our counter 67 | testModule.incrementCounter(); 68 | 69 | // Check the counter value and reset 70 | // Outputs: 1 71 | testModule.resetCounter(); 72 | /*********************************************************/ 73 | //3.Module(模块)模式变化 74 | // 3.1 混入 75 | // Global module 76 | var myModule = (function(jQ, _) { 77 | function privateMethod1() { 78 | jQ(".container").html("test"); 79 | } 80 | 81 | function privateMethod2() { 82 | console.log(_.min([10, 5, 100, 2, 1000])); 83 | } 84 | 85 | return { 86 | publicMethod: function() { 87 | privateMethod1(); 88 | } 89 | }; 90 | 91 | // Pull in jQuery and Underscore 92 | }(jQuery, _)); 93 | 94 | myModule.publicMethod(); 95 | // 3.2 引出 96 | // Global module对象 97 | var myModule = (function() { 98 | // Module object 99 | var module = {}, 100 | privateVariable = "Hello World"; 101 | 102 | function privateMethod() { 103 | // ... 104 | } 105 | 106 | module.publicProperty = "Foobar"; 107 | module.publicMethod = function() { 108 | console.log(privateVariable); 109 | }; 110 | 111 | return module; 112 | }()); 113 | 114 | /*********************************************************/ 115 | -------------------------------------------------------------------------------- /Module/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Module/module-in-jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | module in jquery 7 | 8 | 9 | 10 | 11 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Observer/Observer-ES6.js: -------------------------------------------------------------------------------- 1 | /*Subject 目标*/ 2 | class Subject { 3 | addObserver() { 4 | throw new Error("This method must be overwritten!"); 5 | } 6 | removeObserver() { 7 | throw new Error("This method must be overwritten!"); 8 | } 9 | notify() { 10 | throw new Error("This method must be overwritten!"); 11 | } 12 | } 13 | 14 | class Observer { 15 | update() { 16 | throw new Error("This method must be overwritten!"); 17 | } 18 | } 19 | 20 | 21 | //=============================================================================== 22 | //具体的对象 23 | class ControlCheckbox extends Subject { 24 | constructor() { 25 | super(); 26 | this.observers = []; 27 | } 28 | addObserver(observer){ 29 | this.observers.push(observer); 30 | } 31 | notify(context) { 32 | let observerCount = this.observers.length; 33 | for (let i = 0; i < observerCount; i++) { 34 | this.observers[i].update(context); 35 | } 36 | } 37 | } 38 | 39 | 40 | //具体的观察者 41 | class AddedCheckboxs extends Observer{ 42 | constructor(subject){ 43 | super(); 44 | console.log(subject); 45 | this.subject = subject; 46 | // this.subject.addObserver(this); 47 | } 48 | update(context){ 49 | this.checked = context; 50 | } 51 | } 52 | 53 | //main test 54 | let addBtn = document.getElementById("addNewObserver"), 55 | container = document.getElementById("observersContainer"), 56 | controlCheckboxDom = document.getElementById("mainCheckbox"); 57 | 58 | let controlCheckbox = new ControlCheckbox(); 59 | 60 | controlCheckboxDom.onclick = function(){ 61 | controlCheckbox.notify(controlCheckboxDom.checked);//通知了变化 62 | } 63 | 64 | addBtn.onclick = function(){ 65 | var check = document.createElement("input"); 66 | check.type = "checkbox"; 67 | //新增的每一个都应该实现观察者 68 | console.info(controlCheckbox.observers);//查看是否添加上 69 | 70 | check.update = AddedCheckboxs.prototype.update; 71 | 72 | controlCheckbox.addObserver(check);//添加到观察者列表上去 73 | 74 | container.appendChild(check); 75 | } 76 | -------------------------------------------------------------------------------- /Observer/Observer.js: -------------------------------------------------------------------------------- 1 | //观察者模式 2 | /** 3 | * Subject: maintains a list of observers, facilitates adding or removing observers 4 | * Observer: provides a update interface for objects that need to be notified of a Subject's changes of state 5 | * ConcreteSubject: broadcasts notifications to observers on changes of state, stores the state of ConcreteObservers 6 | * ConcreteObserver: stores a reference to the ConcreteSubject, implements an update interface for the Observer to 7 | * ensure state is consistent with the Subject's 8 | */ 9 | 10 | function ObserverList() { 11 | this.observerList = []; 12 | } 13 | 14 | ObserverList.prototype.Add = function(obj) { 15 | return this.observerList.push(obj); 16 | }; 17 | ObserverList.prototype.Empty = function() { 18 | this.observerList = []; 19 | }; 20 | ObserverList.prototype.Count = function() { 21 | return this.observerList.length; 22 | }; 23 | ObserverList.prototype.Get = function(index) { 24 | if (index > -1 && index < this.observerList.length) { 25 | return this.observerList[index]; 26 | } 27 | }; 28 | ObserverList.prototype.Insert = function(obj, index) { 29 | var pointer = -1; 30 | if (index === 0) { 31 | this.observerList.unshift(obj); 32 | pointer = index; 33 | } else if (index === this.observerList.length) { 34 | this.observerList.push(obj); 35 | pointer = index; 36 | } 37 | 38 | return pointer; 39 | }; 40 | ObserverList.prototype.IndexOf = function(obj, startIndex) { 41 | var i = startIndex, 42 | pointer = -1; 43 | 44 | while (i < this.observerList.length) { 45 | if (this.observerList[i] === obj) { 46 | pointer = i; 47 | } 48 | i++; 49 | } 50 | 51 | return pointer; 52 | }; 53 | ObserverList.prototype.RemoveAt = function(index) { 54 | if (index === 0) { 55 | this.observerList.shift(); 56 | } else if (index === this.observerList.length - 1) { 57 | this.observerList.pop(); 58 | } 59 | }; 60 | // Extend an object with an extension 61 | function extend(extension, obj) { 62 | for (var key in extension) { 63 | obj[key] = extension[key]; 64 | } 65 | } 66 | 67 | /*******************************************************************/ 68 | //开始模拟 69 | //Subject 目标 70 | function Subject() { 71 | this.observers = new ObserverList(); 72 | } 73 | 74 | Subject.prototype.AddObserver = function(observer) { 75 | this.observers.Add(observer); 76 | }; 77 | 78 | Subject.prototype.RemoveObserver = function(observer) { 79 | this.observers.RemoveAt(this.observers.IndexOf(observer, 0)); 80 | }; 81 | Subject.prototype.Notify = function(context) { 82 | var observerCount = this.observers.Count(); 83 | for (var i = 0; i < observerCount; i++) { 84 | this.observers.Get(i).Update(context); 85 | } 86 | }; 87 | 88 | //test 89 | function Observer(){ 90 | this.Update = function(context){ 91 | this.checked = context; 92 | } 93 | } 94 | // References to our DOM elements 95 | 96 | var controlCheckbox = document.getElementById("mainCheckbox"), 97 | addBtn = document.getElementById("addNewObserver"), 98 | container = document.getElementById("observersContainer"); 99 | 100 | // Concrete Subject 具体目标,状态改变时候,向Observer发送状态 checked是true或者false 101 | 102 | // Extend the controlling checkbox with the Subject class 103 | extend(new Subject(), controlCheckbox);//目标 104 | 105 | // Clicking the checkbox will trigger notifications to its observers 106 | controlCheckbox["onclick"] = new Function("controlCheckbox.Notify(controlCheckbox.checked)"); 107 | 108 | 109 | addBtn["onclick"] = AddNewObserver; 110 | 111 | // Concrete Observer 具体观察者(实现Observer的更新接口,以使自己的状态和目标状态一致) 112 | 113 | function AddNewObserver() { 114 | 115 | // Create a new checkbox to be added 116 | var check = document.createElement("input"); 117 | check.type = "checkbox"; 118 | 119 | // Extend the checkbox with the Observer class 120 | extend(new Observer(), check);//观察者 121 | 122 | // Override with custom update behaviour 123 | check.Update = function(value) { 124 | this.checked = value; 125 | }; 126 | 127 | // Add the new observer to our list of observers 128 | // for our main subject 129 | controlCheckbox.AddObserver(check); 130 | 131 | // Append the item to the container 132 | container.appendChild(check); 133 | } 134 | -------------------------------------------------------------------------------- /Observer/Publish-Subscribe-ES6.js: -------------------------------------------------------------------------------- 1 | //发布-订阅模式 2 | /* 3 | topics = {}, 4 | subUid = -1; 5 | */ 6 | class Pubsub { 7 | constructor(){ 8 | this.subUid = 0; //订阅的id值 9 | this.topics = {};//存放所有订阅者 10 | } 11 | publish(topic, args) { 12 | if (!this.topics[topic]) { 13 | return false; 14 | } 15 | 16 | let subscribers = this.topics[topic], 17 | len = subscribers ? subscribers.length : 0; 18 | 19 | while (len--) { 20 | subscribers[len].func(topic, args); 21 | } 22 | 23 | return this; 24 | } 25 | 26 | subscribe(topic, func) { 27 | if (!this.topics[topic]) { 28 | this.topics[topic] = []; 29 | } 30 | 31 | let token = (++this.subUid).toString(); 32 | this.topics[topic].push({ 33 | token: token, 34 | func: func 35 | }); 36 | return token; 37 | } 38 | unsubscribe(token) { 39 | for (let m in this.topics) { 40 | if (this.topics[m]) { 41 | for (let i = 0, j = this.topics[m].length; i < j; i++) { 42 | if (this.topics[m][i].token === token) { 43 | this.topics[m].splice(i, 1); 44 | return token; 45 | } 46 | } 47 | } 48 | } 49 | return this; 50 | } 51 | } 52 | 53 | 54 | //usage 55 | let messageLogger = function(topics, data) { 56 | console.log("Logging: " + topics + ": " + data); 57 | }; 58 | let pubsub = new Pubsub(); 59 | 60 | let subscription = pubsub.subscribe("inbox/newMessage", messageLogger); 61 | 62 | // Publishers are in charge of publishing topics or notifications of 63 | // interest to the application. e.g: 64 | 65 | pubsub.publish("inbox/newMessage", "hello world!"); -------------------------------------------------------------------------------- /Observer/Publish-Subscribe.js: -------------------------------------------------------------------------------- 1 | //订阅-发布模式 2 | 3 | var pubsub = {}; 4 | (function(q) { 5 | var topics = {},//存放所有订阅者 6 | subUid = -1; 7 | 8 | // Publish or broadcast events of interest 9 | // with a specific topic name and arguments 10 | // such as the data to pass along 11 | q.publish = function(topic, args) { 12 | 13 | if (!topics[topic]) { 14 | return false; 15 | } 16 | 17 | var subscribers = topics[topic], 18 | len = subscribers ? subscribers.length : 0; 19 | 20 | while (len--) { 21 | subscribers[len].func(topic, args); 22 | } 23 | 24 | return this; 25 | }; 26 | 27 | // Subscribe to events of interest 28 | // with a specific topic name and a 29 | // callback function, to be executed 30 | // when the topic/event is observed 31 | q.subscribe = function(topic, func) { 32 | if (!topics[topic]) { 33 | topics[topic] = []; 34 | } 35 | 36 | var token = (++subUid).toString(); 37 | topics[topic].push({ 38 | token: token, 39 | func: func 40 | }); 41 | return token; 42 | }; 43 | 44 | // Unsubscribe from a specific 45 | // topic, based on a tokenized reference 46 | // to the subscription 47 | q.unsubscribe = function(token) { 48 | for (var m in topics) { 49 | if (topics[m]) { 50 | for (var i = 0, j = topics[m].length; i < j; i++) { 51 | if (topics[m][i].token === token) { 52 | topics[m].splice(i, 1); 53 | return token; 54 | } 55 | } 56 | } 57 | } 58 | return this; 59 | }; 60 | }(pubsub)); 61 | 62 | // A simple message logger that logs any topics and data received through our 63 | // subscriber 64 | var messageLogger = function(topics, data) { 65 | console.log("Logging: " + topics + ": " + data); 66 | }; 67 | 68 | // Subscribers listen for topics they have subscribed to and 69 | // invoke a callback function (e.g messageLogger) once a new 70 | // notification is broadcast on that topic 71 | var subscription = pubsub.subscribe("inbox/newMessage", messageLogger); 72 | 73 | // Publishers are in charge of publishing topics or notifications of 74 | // interest to the application. e.g: 75 | 76 | pubsub.publish("inbox/newMessage", "hello world!"); 77 | 78 | // or 79 | pubsub.publish("inbox/newMessage", ["test", "a", "b", "c"]); 80 | 81 | // or 82 | pubsub.publish("inbox/newMessage", { 83 | sender: "hello@google.com", 84 | body: "Hey again!" 85 | }); 86 | 87 | // We cab also unsubscribe if we no longer wish for our subscribers 88 | // to be notified 89 | // pubsub.unsubscribe( subscription ); 90 | 91 | // Once unsubscribed, this for example won't result in our 92 | // messageLogger being executed as the subscriber is 93 | // no longer listening 94 | pubsub.publish("inbox/newMessage", "Hello! are you still there?"); 95 | -------------------------------------------------------------------------------- /Observer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 设计模式 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Observer/publish-subcribe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 设计模式 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # javascript-design-pattern 2 | javascript设计模式【ES5和ES6语法】 3 | 4 | 博客地址: 5 | - [javascript设计模式【上】http://blog.csdn.net/future_todo/article/details/53992141](http://blog.csdn.net/future_todo/article/details/53992141) 6 | - [javascript设计模式【下】http://blog.csdn.net/future_todo/article/details/53992145](http://blog.csdn.net/future_todo/article/details/53992145) 7 | - [javascript设计模式 使用ES6语法 http://blog.csdn.net/future_todo/article/details/53992152](http://blog.csdn.net/future_todo/article/details/53992152) 8 | 9 | -------------------------------------------------------------------------------- /Revealing/Revealing.js: -------------------------------------------------------------------------------- 1 | // Revealing Module 揭示模块模式 2 | 3 | var myRevealingModule = function() { 4 | var privateVar = "Ben Cherry", 5 | publicVar = "Hey there!"; 6 | 7 | function privateFunction() { 8 | console.log("Name:" + privateVar); 9 | } 10 | 11 | function publicSetName(strName) { 12 | privateVar = strName; 13 | } 14 | 15 | function publicGetName() { 16 | privateFunction(); 17 | } 18 | 19 | // Reveal public pointers to 20 | // private functions and properties 21 | 22 | return { 23 | setName: publicSetName, 24 | greeting: publicVar, 25 | getName: publicGetName 26 | }; 27 | 28 | }(); 29 | 30 | myRevealingModule.setName("Paul Kinlan"); 31 | -------------------------------------------------------------------------------- /Revealing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Singleton/SingLeton.js: -------------------------------------------------------------------------------- 1 | // 单例模式 2 | var mySingleton = (function() { 3 | // Instance stores a reference to the Singleton 4 | var instance; 5 | 6 | function init() { 7 | 8 | // Singleton 9 | 10 | // Private methods and variables 11 | function privateMethod() { 12 | console.log("I am private"); 13 | } 14 | 15 | var privateVariable = "Im also private"; 16 | 17 | var privateRandomNumber = Math.random(); 18 | 19 | return { 20 | 21 | // Public methods and variables 22 | publicMethod: function() { 23 | console.log("The public can see me!"); 24 | }, 25 | 26 | publicProperty: "I am also public", 27 | 28 | getRandomNumber: function() { 29 | return privateRandomNumber; 30 | } 31 | 32 | }; 33 | 34 | }; 35 | 36 | return { 37 | 38 | // Get the Singleton instance if one exists 39 | // or create one if it doesn't 40 | getInstance: function() { 41 | 42 | if (!instance) { 43 | instance = init(); 44 | } 45 | 46 | return instance; 47 | } 48 | 49 | }; 50 | 51 | })(); 52 | 53 | 54 | //============================================================== 55 | //Singleton 和静态实例 56 | var SingletonTester = (function() { 57 | 58 | // options: an object containing configuration options for the singleton 59 | // e.g var options = { name: "test", pointX: 5}; 60 | function Singleton(options) { 61 | 62 | // set options to the options supplied 63 | // or an empty object if none are provided 64 | options = options || {}; 65 | 66 | // set some properties for our singleton 67 | this.name = "SingletonTester"; 68 | 69 | this.pointX = options.pointX || 6; 70 | 71 | this.pointY = options.pointY || 10; 72 | 73 | } 74 | 75 | // our instance holder 76 | var instance; 77 | 78 | // an emulation of static variables and methods 79 | var _static = { 80 | name: "SingletonTester", 81 | // Method for getting an instance. It returns 82 | // a singleton instance of a singleton object 83 | getInstance: function(options) { 84 | if (instance === undefined) { 85 | instance = new Singleton(options); 86 | } 87 | 88 | return instance; 89 | } 90 | }; 91 | 92 | return _static; 93 | 94 | })(); 95 | 96 | var singletonTest = SingletonTester.getInstance({ 97 | pointX: 5 98 | }); 99 | 100 | // Log the output of pointX just to verify it is correct 101 | // Outputs: 5 102 | console.log(singletonTest.pointX); 103 | -------------------------------------------------------------------------------- /Singleton/Singleton-ES6.js: -------------------------------------------------------------------------------- 1 | let instance = null; 2 | class mySingleton { 3 | constructor() { 4 | if (!instance) instance = this; 5 | return instance; 6 | } 7 | 8 | publicMethod() { 9 | console.log("The public can see me!"); 10 | } 11 | //静态方法 12 | static getRandomNumber() { 13 | return 'hello'; 14 | } 15 | } 16 | 17 | //静态属性 18 | let mySingleton.publicProperty = "I am also public" 19 | 20 | let singleton1 = new mySingleton(); 21 | let singleton2 = new mySingleton(); 22 | 23 | //======================================================================== 24 | class mySingleton { 25 | static getInstance() { 26 | if (!mySingleton.instance) { 27 | mySingleton.instance = new mySingleton(); 28 | } 29 | return mySingleton.instance; 30 | } 31 | publicMethod() { 32 | console.log("The public can see me!"); 33 | } 34 | } 35 | 36 | var cache = mySingleton.getInstance(); 37 | -------------------------------------------------------------------------------- /Singleton/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 设计模式 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /jqueryPlugin/Lightweight-Start.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery lightweight plugin boilerplate 3 | * Original author: @ajpiano 4 | * Further changes, comments: @addyosmani 5 | * Licensed under the MIT license 6 | */ 7 | 8 | // the semi‐colon before the function invocation is a safety 9 | // net against concatenated scripts and/or other plugins 10 | // that are not closed properly. 11 | // 分号为了安全,防止其他的插件没有正常关闭 12 | ; (function($, window, document, undefined) { 13 | 14 | // undefined is used here as the undefined global 15 | // variable in ECMAScript 3 and is mutable (i.e. it can 16 | // be changed by someone else). undefined isn't really 17 | // being passed in so we can ensure that its value is 18 | // truly undefined. In ES5, undefined can no longer be 19 | // modified. 20 | 21 | // window and document are passed through as local 22 | // variables rather than as globals, because this (slightly) 23 | // quickens the resolution process and can be more 24 | // efficiently minified (especially when both are 25 | // regularly referenced in our plugin). 26 | 27 | // Create the defaults once 创建默认值 28 | var pluginName = "defaultPluginName", 29 | defaults = { 30 | propertyName: "value" 31 | }; 32 | 33 | // The actual plugin constructor 34 | function Plugin(element, options) { 35 | this.element = element; 36 | 37 | // jQuery has an extend method that merges the 38 | // contents of two or more objects, storing the 39 | // result in the first object. The first object 40 | // is generally empty because we don't want to alter 41 | // the default options for future instances of the plugin 42 | this.options = $.extend({}, defaults, options); 43 | 44 | this._defaults = defaults; 45 | this._name = pluginName; 46 | 47 | this.init(); 48 | } 49 | 50 | Plugin.prototype.init = function() { 51 | // Place initialization logic here 52 | // We already have access to the DOM element and 53 | // the options via the instance, e.g. this.element 54 | // and this.options 55 | console.log(this.options); 56 | }; 57 | 58 | // A really lightweight plugin wrapper around the constructor, 59 | // preventing against multiple instantiations 60 | $.fn[pluginName] = function(options) { 61 | return this.each(function() { 62 | if (!$.data(this, "plugin_" + pluginName)) { 63 | $.data(this, "plugin_" + pluginName, 64 | new Plugin(this, options)); 65 | } 66 | }); 67 | } 68 | 69 | })(jQuery, window, document); 70 | 71 | 72 | //usage 73 | $("#elem").defaultPluginName({ 74 | propertyName: "a custom value" 75 | }); 76 | -------------------------------------------------------------------------------- /jqueryPlugin/WidgetFactory.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Widget‐factory plugin boilerplate (for 1.8/9+) 3 | * Author: @addyosmani 4 | * Further changes: @peolanha 5 | * Licensed under the MIT license 6 | */ 7 | 8 | ; (function($, window, document, undefined) { 9 | 10 | // define our widget under a namespace of your choice 11 | // with additional parameters e.g. 12 | // $.widget( "namespace.widgetname", (optional) ‐ an 13 | // existing widget prototype to inherit from, an object 14 | // literal to become the widget's prototype ); 15 | //在指定命名空间下创建widget 16 | $.widget("namespace.widgetName", { 17 | //Options to be used as defaults 18 | options: { 19 | someValue: null 20 | }, 21 | 22 | //Setup widget (e.g. element creation, apply theming 23 | // , bind events etc.) 24 | _create: function() { 25 | 26 | // _create will automatically run the first time 27 | // this widget is called. Put the initial widget 28 | // setup code here, then we can access the element 29 | // on which the widget was called via this.element. 30 | // The options defined above can be accessed 31 | // via this.options this.element.addStuff(); 32 | console.log(this); 33 | }, 34 | 35 | // Destroy an instantiated plugin and clean up 36 | // modifications the widget has made to the DOM 37 | destroy: function() { 38 | 39 | // this.element.removeStuff(); 40 | // For UI 1.8, destroy must be invoked from the 41 | // base widget 42 | $.Widget.prototype.destroy.call(this); 43 | // For UI 1.9, define _destroy instead and don't 44 | // worry about 45 | // calling the base widget 46 | }, 47 | 48 | methodB: function(event) { 49 | //_trigger dispatches callbacks the plugin user 50 | // can subscribe to 51 | // signature: _trigger( "callbackName" , [eventObject], 52 | // [uiObject] ) 53 | // e.g. this._trigger( "hover", e /*where e.type == 54 | // "mouseenter"*/, { hovered: $(e.target)}); 55 | this._trigger("methodA", event, { 56 | key: value 57 | }); 58 | }, 59 | 60 | methodA: function(event) { 61 | this._trigger("dataChanged", event, { 62 | key: value 63 | }); 64 | }, 65 | 66 | // Respond to any changes the user makes to the 67 | // option method 68 | _setOption: function(key, value) { 69 | switch (key) { 70 | case "someValue": 71 | this.options.someValue = doSomethingWith( value ); 72 | break; 73 | default: 74 | this.options[ key ] = value; 75 | break; 76 | } 77 | 78 | // For UI 1.8, _setOption must be manually invoked 79 | // from the base widget 80 | $.Widget.prototype._setOption.apply(this, arguments); 81 | // For UI 1.9 the _super method can be used instead 82 | // this._super( "_setOption", key, value ); 83 | } 84 | }); 85 | 86 | })(jQuery, window, document); 87 | 88 | 89 | var collection = $("#elem").widgetName({ 90 | foo: false 91 | }); 92 | 93 | collection.widgetName("methodB"); 94 | -------------------------------------------------------------------------------- /jqueryPlugin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | jquery插件 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------