수색…


소개

디자인 패턴은 코드를 읽기 쉽 도록 유지하는 좋은 방법입니다. DRY는 반복하지 않는다는 의미입니다. 아래에서 가장 중요한 디자인 패턴에 대한 예를 찾을 수 있습니다.

비고

소프트웨어 엔지니어링에서 소프트웨어 설계 패턴은 소프트웨어 설계의 주어진 상황에서 일반적으로 발생하는 문제에 대한 일반적인 재사용 가능한 솔루션입니다.

싱글 톤 패턴

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

모듈 및 모듈 패턴 표시

모듈 패턴

Module 패턴은 공개 API를 생성하는 동안 개인 멤버를 캡슐화하는 방법을 제공하는 창조적이고 구조적인 디자인 패턴 입니다. 이것은 공용 API가 포함 된 객체를 반환하는 동안 ( 클로저를 통해) 해당 범위에서만 사용 가능한 변수를 정의 할 수있는 IIFE 를 작성함으로써 수행됩니다.

이것은 주요 로직을 숨기고 응용 프로그램의 다른 부분이 사용하기를 원하는 인터페이스 만 드러내는 깨끗한 솔루션을 제공합니다.

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 */);

모듈 패턴 공개

계좌 배양 패턴은 모듈 패턴의 변형입니다. 주요 차이점은 모든 멤버 (private 및 public)가 클로저 내에 정의되고 반환 값은 함수 정의가 포함되지 않은 객체 리터럴이며 멤버 데이터에 대한 모든 참조는 반환 된 객체 대신 직접 참조를 통해 수행된다는 것입니다.

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 */);

프로토 타입 패턴 공개

드러내는 패턴의 이러한 변형은 생성자를 메소드로 분리하는 데 사용됩니다. 이 패턴을 통해 객체 지향 언어와 같은 자바 스크립트 언어를 사용할 수 있습니다.

//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();

프로토 타입 패턴

프로토 타입 패턴은 프로토 타입 상속을 통해 다른 객체의 청사진으로 사용될 수있는 객체를 만드는 데 중점을 둡니다. 이 패턴은 자바 스크립트에서 본질적으로 쉽게 사용할 수 있습니다. 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 키워드를 사용할 필요는 없지만 생성자와 같이 객체를 초기화하는 데 계속 사용할 수 있습니다.

팩토리 함수는 jQuerymoment.js 와 같이 API 래퍼로 사용되는 경우가 많으 므로 사용자는 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

cowFactory 함수가 cowFactory 함수 내에서 닫혀 formalName 마지막 행에서 오류가 발생합니다. 이것은 종결 이다.

또한 팩토리는 함수이기 때문에 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