1. 程式人生 > 實用技巧 >設計模式-裝飾器模式

設計模式-裝飾器模式

// 裝飾器模式(Decorator Pattern)通過包裝一個物件來實現一個具有原物件相同介面的新物件。
// 裝飾器模式可以在不改變原物件結構的情況下新增擴充套件功能。它比通過建立子類來擴充套件功能更靈活。

// 購買汽車的時候,可以要求4S店新增各種配件,比如加裝汽車導航,加裝音響系統等。
// 下面的程式碼是採用子類繼承來實現加裝各種配件的功能。


/** 原型繼承的方法*/
// function extend(subClass, superClass) {
//   var F = function() {}
//   F.prototype = superClass.prototype
//   subClass.prototype = new F()
// subClass.prototype.constructor = subClass // subClass.superClass = superClass.prototype // if (superClass.prototype.constructor == Object.prototype.constructor) { // superClass.prototype.constructor = superClass // } // } // function Car() {} // Car.prototype = { // selfCheck: function() { // return '奧迪A8 2017款 A8L 40 TFSI舒適型'
// }, // drive: function() { // console.log('我有一隻小毛驢,我從來也不騎') // }, // getPrice: function() { // return 878900 // } // } // function CarWithNav() {} // extend(CarWithNav, Car) // CarWithNav.prototype.selfCheck = function() { // return CarWithNav.superClass.selfCheck() + ' 加裝奧迪智慧漢語語音導航系統' // } // CarWithNav.prototype.drive = function() {
// CarWithNav.superClass.drive() // console.log('奧迪智慧漢語語音導航系統開始為您導航') // } // CarWithNav.prototype.getPrice = function() { // return CarWithNav.superClass.getPrice() + 1000 // } // function CarWithAudio() {} // extend(CarWithAudio, Car) // CarWithAudio.prototype.selfCheck = function() { // return CarWithAudio.superClass.selfCheck() + ' 加裝Bang&Olufsen高階音響系統' // } // CarWithAudio.prototype.openAudio = function() { // console.log('Bang&Olufsen高階音響系統已經啟動,開始播放歌曲《小毛驢》...') // } // CarWithAudio.prototype.getPrice = function() { // return CarWithAudio.superClass.getPrice() + 5000 // } // var car1 = new CarWithNav() // console.log(car1.selfCheck()) // console.log(car1.getPrice()) // car1.drive() // var car2 = new CarWithAudio() // console.log(car2.selfCheck()) // console.log(car2.getPrice()) // car2.drive() // car2.openAudio() // 在上面的程式碼中,每一個配件都需要建立一個子類,此外配件之間的組合也要建立子類,n種配件將會有2^n - 1種子類。 // 這顯然是不可接受的。 // 裝飾者模式可以很好的解決這個問題。 // 請利用裝飾者模式完善以下程式碼,確保輸出結果是正確的。 function extend(subClass, superClass) { var F = function() {} F.prototype = superClass.prototype subClass.prototype = new F() subClass.prototype.constructor = subClass subClass.superClass = superClass.prototype if (superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass } } function Car() {} Car.prototype = { selfCheck: function() { return '奧迪A8 2017款 A8L 40 TFSI舒適型' }, drive: function() { console.log('我有一隻小毛驢,我從來也不騎') }, getPrice: function() { return 878900 } } function CarDecorator(car) { // 請完善程式碼 this.car = car; } CarDecorator.prototype = { selfCheck: function() { // 請完善程式碼 this.car.selfCheck(); }, drive: function() { // 請完善程式碼 this.car.drive(); }, getPrice: function() { // 請完善程式碼 this.car.getPrice(); } } var NavDecorator = function(car) { // 請完善程式碼 this.car = car; } extend(NavDecorator, CarDecorator) NavDecorator.prototype.selfCheck = function() { // 請完善程式碼 return this.car.selfCheck() + ' 加裝奧迪智慧漢語語音導航系統'; } NavDecorator.prototype.drive = function() { // 請完善程式碼 this.car.drive() console.log('奧迪智慧漢語語音導航系統開始為您導航') } NavDecorator.prototype.getPrice = function() { return this.car.getPrice() + 2000 } var AudioDecorator = function(car) { // 請完善程式碼 this.car = car; } extend(AudioDecorator, CarDecorator) AudioDecorator.prototype.selfCheck = function() { // 請完善程式碼 return this.car.selfCheck() + ' 加裝Bang&Olufsen高階音響系統' } AudioDecorator.prototype.openAudio = function() { // 請完善程式碼 console.log('Bang&Olufsen高階音響系統已經啟動,開始播放歌曲《小毛驢》...') } AudioDecorator.prototype.getPrice = function() { return this.car.getPrice() + 5000 } var car = new Car() car = new NavDecorator(car) car = new AudioDecorator(car) // 奧迪A8 2017款 A8L 40 TFSI舒適型 加裝奧迪智慧漢語語音導航系統 加裝Bang&Olufsen高階音響系統 console.log(car.selfCheck()) // 885900 console.log(car.getPrice()) // 我有一隻小毛驢,我從來也不騎 // 奧迪智慧漢語語音導航系統開始為您導航 car.drive() // Bang&Olufsen高階音響系統已經啟動,開始播放歌曲《小毛驢》... car.openAudio()