系列目錄:javascript
適配器模式主要用來解決兩個已有接口之間不匹配的問題,它不考慮這些接口是怎麼實現的,也不考慮他們未來會如何演化。適配器模式不須要改變當前已有的接口,就能讓他們協同做用。前端
適配器的別名也叫包裝器(wrapper),這是一個並不複雜的模式,在平常開發中有許多這樣的場景:例如當咱們試圖調用某個模塊或者某個對象的接口時,卻發現這個接口的格式並不符合目前的需求,這時就有兩種解決方法,第一種使咱們直接修改原來的接口實現,但若是原來的模塊或者對象很複雜,亦或是咱們拿到的已是已壓縮過的代碼,那麼去修改原接口就顯得不現實了。第二種方法就是咱們要講到的適配器,將原接口轉換成你但願拿到的接口,而你只須要經過適配器便可獲得,並不須要去修改原模塊或對象。java
舉一個抽象的例子,例如當咱們有兩臺電腦須要充電:git
class ThinkPad {
charge() {
console.log('ThinkPad 開始充電');
}
}
class MacBook {
charge() {
console.log('MacBook 開始充電')
}
}
// 電源充電
function PowerToCharge(laptop) {
if(laptop.charge instanceof Function) {
laptop.charge()
}
}
PowerToCharge(new ThinkPad()) // ThinkPad開始充電
PowerToCharge(new MacBook()) // MacBook開始充電
複製代碼
可是若是MacBook不能直接用一種電源接口充電,可能咱們就須要一種轉接器,這裏也就使用的適配器模式,咱們不能直接更改電腦上的接口,但咱們能夠經過一層轉接(封裝),來實現充電github
class ThinkPad {
charge() {
console.log('ThinkPad 開始充電');
}
}
class MacBook {
type_cCharge() {
console.log('MacBook 開始充電')
}
}
// 定義適配器類,來實現對MacBook的轉接
class TypeCToDp {
charge() {
let macbook = new MacBook();
return macbook.type_cCharge()
}
}
// 電源充電
function PowerToCharge(laptop) {
if(laptop.charge instanceof Function) {
laptop.charge()
}
}
PowerToCharge(new ThinkPad()) // ThinkPad開始充電
PowerToCharge(new TypeCToDp()) // MacBook開始充電
複製代碼
代理模式是爲一個對象提供一個代用品或者佔位符,以便控制對它的訪問。chrome
代理模式是一種極爲有趣的模式,生活中咱們能夠找到不少代理模式的場景。好比明星的經紀人,通常的商業活動不會直接跟明星接觸,而是和經紀人談,經紀人會把工做內容和報酬談好以後在交給明星。設計模式
下面咱們用一個明星買包的例子來解釋下代理bash
當明星沒有經濟人 本身買包網絡
// 定義一個包類
class Bags {
constructor(props) {
this.name = props;
}
getName() {
return this.name;
}
}
// 定義一個明星對象
class Star {
buyBag(bag) {
console.log(`買到了一個${bag.getName()}包`);
}
}
// 建立一個明星實例
let star = new Star();
star.buyBag(new Bags('Coach')); //買到了一個Coach包
複製代碼
當明星讓本身的助理去買包app
// 定義一個包類
class Bags {
constructor(props) {
this.name = props;
}
getName() {
return this.name;
}
}
// 定義一個助理對象
class Assistant {
constructor(props) {
this.star = props;
}
buyBag(bag) {
this.star.buyBag(bag);
}
}
// 定義一個明星對象
class Star {
buyBag(bag) {
console.log(`買到了一個${bag.getName()}包`);
}
}
// 建立一個明星實例
let star = new Star();
let assistant = new Assistant(star);
assistant.buyBag(new Bags('Coach')); //買到了一個Coach包
複製代碼
此時咱們就實現了一個簡單的代理模式,但通常咱們不會在這麼簡單的場景使用代理,反而徒增了代碼的複雜度。
圖片的懶加載是前端中比較會用到代理模式的場景,當網絡很差的時候,圖片的加載須要一段時間,這就會產生空白,影響用戶體驗,這時候在圖片真正加載完以前,使用一張loading佔位圖片,等圖片真正加載完在設置src
屬性,來實現圖片的懶加載。
class ABigImage {
constructor() {
this.img = new Image();
document.body.appendChild(this.img);
}
setSrc(src) {
this.img.src = src;
}
}
class ProxyImage {
constructor() {
this.proxyImage = new Image();
}
setSrc(src) {
let bigImageObj = new ABigImage();
bigImageObj.img.src = './local.png'; // 低清晰度圖片url 或者本地圖片
this.proxyImage.src = src;
this.proxyImage.onload = function() {
bigImageObj.img.src = src;
}
}
}
var proxyImage = new ProxyImage();
proxyImage.setSrc('圖片Url')
複製代碼
在演示中咱們能夠感覺到 (啓用chrome的 Network 中的 Disable cache 並設置網速爲 slow 3G 會讓咱們有更直觀的感覺)
到這裏圖片的預加載已經實現,而且當咱們的網速很是好,已經達到能夠取消圖片預加載的一些問題,那麼咱們能夠直接使用ABigImage
的setSrc
方法,而且刪除代理類,這樣咱們根本就不準要改動本體代碼,這是易於維護的。
// 網速很快時
let aImage = new ABigImage();
aImage.setSrc('圖片url')
複製代碼
代理模式中全部的例子都可在 Demo查看
倉庫源代碼: JavaScript-DesignPatterns