Поиск…


Вступление

Шаблоны проектирования - хороший способ сохранить ваш код читаемым и сухим. DRY означает, что вы не повторяетесь . Ниже вы можете найти больше примеров наиболее важных шаблонов дизайна.

замечания

В разработке программного обеспечения шаблон разработки программного обеспечения является общим многоразовым решением общей проблемы в рамках данного контекста при разработке программного обеспечения.

Шаблон Singleton

Шаблон Singleton представляет собой шаблон проектирования, который ограничивает создание экземпляра класса одним объектом. После того, как первый объект будет создан, он вернет ссылку на тот же самый, когда вызывается для объекта.

var Singleton = (function () {
        // instance stores a reference to the Singleton
        var instance;
    
        function createInstance() {
            // private variables and methods
            var _privateVariable = 'I am a private variable';
            function _privateMethod() {
                console.log('I am a private method');
            }

            return {
                // public methods and variables
                publicMethod: function() {
                    console.log('I am a public method');
                },
                publicVariable: 'I am a public variable'
            };
        }
         
        return {
            // Get the Singleton instance if it exists
            // or create one if doesn't
            getInstance: function () {
                if (!instance) {
                    instance = createInstance();
                }
                return instance;
            }
        };
    })();

Использование:

// there is no existing instance of Singleton, so it will create one
var instance1 = Singleton.getInstance();
// there is an instance of Singleton, so it will return the reference to this one
var instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

Модуль и раскрытие шаблонов модулей

Схема модуля

Шаблон модуля представляет собой шаблон создания и структурного проектирования, который обеспечивает способ инкапсуляции частных членов при создании публичного API. Это достигается путем создания IIFE, который позволяет нам определять переменные, доступные только в своей области (через закрытие ) при возврате объекта, который содержит открытый API.

Это дает нам чистое решение для скрытия основной логики и только разоблачения интерфейса, который мы хотим использовать в других частях нашего приложения.

var Module = (function(/* pass initialization data if necessary */) {
  // Private data is stored within the closure
  var privateData = 1;

  // Because the function is immediately invoked,
  // the return value becomes the public API
  var api = {
    getPrivateData: function() {
      return privateData;
    },
    
    getDoublePrivateData: function() {
      return api.getPrivateData() * 2;
    }
  };
  return api;
})(/* pass initialization data if necessary */);

Выявление шаблона модуля

Шаблон раскрывающего модуля является вариантом в шаблоне модуля. Ключевыми отличиями являются то, что все члены (частные и общедоступные) определены в закрытии, возвращаемое значение - это литерал объекта, не содержащий определения функций, и все ссылки на данные членов выполняются посредством прямых ссылок, а не через возвращаемый объект.

var Module = (function(/* pass initialization data if necessary */) {
  // Private data is stored just like before
  var privateData = 1;

  // All functions must be declared outside of the returned object
  var getPrivateData = function() {
    return privateData;
  };

  var getDoublePrivateData = function() {
    // Refer directly to enclosed members rather than through the returned object
    return getPrivateData() * 2;
  };

  // Return an object literal with no function definitions
  return {
    getPrivateData: getPrivateData,
    getDoublePrivateData: getDoublePrivateData
  };
})(/* pass initialization data if necessary */);

Выявление шаблона прототипа

Этот вариант шаблона раскрытия используется для разделения конструктора на методы. Этот шаблон позволяет нам использовать язык JavaScript, как объектно ориентированный язык:

//Namespace setting
var NavigationNs = NavigationNs || {};

// This is used as a class constructor 
NavigationNs.active = function(current, length) {        
    this.current = current;
    this.length = length;
}

// The prototype is used to separate the construct and the methods    
NavigationNs.active.prototype = function() {
    // It is a example of a public method because is revealed in the return statement
    var setCurrent = function() {
        //Here the variables current and length are used as private class properties  
        for (var i = 0; i < this.length; i++) {                
                $(this.current).addClass('active');                 
        }
    }
    return { setCurrent: setCurrent };
}();

// Example of parameterless constructor  
NavigationNs.pagination = function() {}

NavigationNs.pagination.prototype = function() {
// It is a example of a private method because is not revealed in the return statement
    var reload = function(data) {
        // do something
    },
    // It the only public method, because it the only function referenced in the return statement
     getPage = function(link) {
        var a = $(link);

        var options = {url: a.attr('href'), type: 'get'}
        $.ajax(options).done(function(data) {            
           // after the the ajax call is done, it calls private method
           reload(data);
        });

        return false;
    }
    return {getPage : getPage}
}();

Этот код, приведенный выше, должен находиться в отдельном файле .js для ссылки на любой требуемой странице. Его можно использовать следующим образом:

var menuActive = new NavigationNs.active('ul.sidebar-menu li', 5);
menuActive.setCurrent();

Шаблон прототипа

Шаблон прототипа фокусируется на создании объекта, который может использоваться в качестве чертежа для других объектов посредством прототипального наследования. Этот шаблон по своей сути легко работать в JavaScript из-за собственной поддержки прототипного наследования в JS, что означает, что нам не нужно тратить время или усилия, имитируя эту топологию.


Создание методов на прототипе

function Welcome(name) {
  this.name = name;
}
Welcome.prototype.sayHello = function() {
  return 'Hello, ' + this.name + '!';
}

var welcome = new Welcome('John');

welcome.sayHello();
// => Hello, John!

Прототипное наследование

Наследование от «родительского объекта» относительно просто с помощью следующего шаблона

ChildObject.prototype = Object.create(ParentObject.prototype);
ChildObject.prototype.constructor = ChildObject;

Где ParentObject - это объект, который вы хотите наследовать от прототипированных функций, а ChildObject - это новый объект, который вы хотите поместить.

Если родительский объект имеет значения, которые он инициализирует в своем конструкторе, вам нужно вызвать конструктор родителей при инициализации дочернего элемента.

Вы делаете это, используя следующий шаблон в конструкторе ChildObject .

function ChildObject(value) {
    ParentObject.call(this, value);
}

Полный пример, в котором реализовано вышеописанное

function RoomService(name, order) {
  // this.name will be set and made available on the scope of this function
  Welcome.call(this, name);
  this.order = order;
}

// Inherit 'sayHello()' methods from 'Welcome' prototype
RoomService.prototype = Object.create(Welcome.prototype);

// By default prototype object has 'constructor' property. 
// But as we created new object without this property  -  we have to set it manually,
// otherwise 'constructor' property will point to 'Welcome' class
RoomService.prototype.constructor = RoomService;

RoomService.prototype.announceDelivery = function() {
  return 'Your ' + this.order + ' has arrived!';
}
RoomService.prototype.deliverOrder = function() {
  return this.sayHello() + ' ' + this.announceDelivery();
}

var delivery = new RoomService('John', 'pizza');

delivery.sayHello();
// => Hello, John!,

delivery.announceDelivery();
// Your pizza has arrived!

delivery.deliverOrder();
// => Hello, John! Your pizza has arrived!

Заводские функции

Заводская функция - это просто функция, которая возвращает объект.

Фабричные функции не требуют использования new ключевого слова, но все равно могут использоваться для инициализации объекта, например конструктора.

Часто фабричные функции используются как обертки API, например, в случаях jQuery и moment.js , поэтому пользователям не нужно использовать new .

Ниже приведена простейшая форма заводской функции; используя аргументы и используя их для создания нового объекта с литералом объекта:

function cowFactory(name) {
    return {
        name: name,
        talk: function () {
            console.log('Moo, my name is ' + this.name);
        },
    };
}

var daisy = cowFactory('Daisy');  // create a cow named Daisy
daisy.talk();  // "Moo, my name is Daisy"

Легко определить частные свойства и методы на заводе, включив их за пределы возвращаемого объекта. Это предотвращает инкапсуляцию данных реализации, поэтому вы можете публиковать публичный интерфейс только для своего объекта.

function cowFactory(name) {
    function formalName() {
        return name + ' the cow';
    }

    return {
        talk: function () {
            console.log('Moo, my name is ' + formalName());
        },
    };
}

var daisy = cowFactory('Daisy');
daisy.talk();  // "Moo, my name is Daisy the cow"
daisy.formalName();  // ERROR: daisy.formalName is not a function

Последняя строка даст ошибку, потому что функция formalName закрывается внутри функции cowFactory . Это закрытие .

Фабрики также являются отличным способом применения методов функционального программирования в JavaScript, поскольку они являются функциями.

Фабрика с композицией

«Предпочтительная композиция над наследованием» - важный и популярный принцип программирования, используемый для назначения поведения объектам, а не наследования многих часто ненужных действий.

Поведение фабрик

var speaker = function (state) {
    var noise = state.noise || 'grunt';

    return {
        speak: function () {
            console.log(state.name + ' says ' + noise);
        }
    };
};

var mover = function (state) {
    return {
        moveSlowly: function () {
            console.log(state.name + ' is moving slowly');
        },
        moveQuickly: function () {
            console.log(state.name + ' is moving quickly');
        }
    };
};

Объектные заводы

6
var person = function (name, age) {
    var state = {
        name: name,
        age: age,
        noise: 'Hello'
    };

    return Object.assign(     // Merge our 'behaviour' objects
        {},
        speaker(state),
        mover(state)
    );
};

var rabbit = function (name, colour) {
    var state = {
        name: name,
        colour: colour
    };

    return Object.assign(
        {},
        mover(state)
    );
};

использование

var fred = person('Fred', 42);
fred.speak();        // outputs: Fred says Hello
fred.moveSlowly();   // outputs: Fred is moving slowly

var snowy = rabbit('Snowy', 'white');
snowy.moveSlowly();  // outputs: Snowy is moving slowly
snowy.moveQuickly(); // outputs: Snowy is moving quickly
snowy.speak();       // ERROR: snowy.speak is not a function

Абстрактный шаблон завода

Шаблон абстрактного фабрики представляет собой шаблон создания, который можно использовать для определения конкретных экземпляров или классов без указания конкретного объекта, который создается.

function Car() { this.name = "Car"; this.wheels = 4; }
function Truck() { this.name = "Truck"; this.wheels = 6; }
function Bike() { this.name = "Bike"; this.wheels = 2; }

const vehicleFactory = {
    createVehicle: function (type) {
        switch (type.toLowerCase()) {
            case "car":
                return new Car();
            case "truck":
                return new Truck();
            case "bike":
                return new Bike();
            default:
                return null;
        }
    }
};

const car = vehicleFactory.createVehicle("Car"); // Car { name: "Car", wheels: 4 }  
const truck = vehicleFactory.createVehicle("Truck"); // Truck { name: "Truck", wheels: 6 }  
const bike = vehicleFactory.createVehicle("Bike"); // Bike { name: "Bike", wheels: 2 }  
const unknown = vehicleFactory.createVehicle("Boat"); // null ( Vehicle not known )


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow