【精選】面試官:聊下常見設(shè)計(jì)模式有哪些?
單例模式解決的是如何在整個(gè)項(xiàng)目中創(chuàng)建唯一對(duì)象實(shí)例的問題,避免重復(fù)創(chuàng)建(實(shí)例化)
對(duì)象,已經(jīng)有現(xiàn)成的實(shí)例就用現(xiàn)成的。減少資源的浪費(fèi)(因?yàn)閯?chuàng)建多個(gè)實(shí)例,浪費(fèi)內(nèi)存,
完全沒必要),單件模式保證了每時(shí)每刻引用的都是同一個(gè)實(shí)例。最常用的地方是數(shù)據(jù)庫連接。
工廠模式 是一種類,它具有為您創(chuàng)建對(duì)象的某些方法。工廠模式解決的是如何不通過 new建立實(shí)例對(duì)象的方法,您可以使用工廠類創(chuàng)建對(duì)象,而不直接使用 new。這樣,如 果您想要更改所創(chuàng)建的對(duì)象類型,只需更改該工廠即可。使用該工廠的所有代碼會(huì)自動(dòng) 更改。
適配器模式:將各種截然不同的函數(shù)接口封裝成統(tǒng)一的API,首先定義一個(gè)接口(有幾個(gè) 方法,以及相應(yīng)的參數(shù))。然后,有幾種不同的情況,就寫幾個(gè)類實(shí)現(xiàn)該接口。將完成相 似功能的函數(shù),統(tǒng)一成一致的方法。
策略模式:將一組特定的行為和算法封裝成類,以適應(yīng)某些特定的上下文環(huán)境,用意是 對(duì)一組算法的封裝。動(dòng)態(tài)的選擇需要的算法并使用。
實(shí)現(xiàn)單例模式的要點(diǎn):
三私一公:私有化靜態(tài)屬性,私有化構(gòu)造方法,私有化克隆方法,公有化靜態(tài)方法。
//(1).?需要一個(gè)保存類的唯一實(shí)例的靜態(tài)成員變量:
private??static?$instance;?//私有化靜態(tài)屬性
//(2).?構(gòu)造函數(shù)和克隆函數(shù)必須聲明為私有的,防止外部程序new類從而失去單例模式?的意義:
private?function?__construct()?//私有化構(gòu)造方法
{
????$this->_db?=?pg_connect('xxxx');
}
private?function?__clone()?//私有化克隆方法,禁止克隆
{
}
//(3).?必須提供一個(gè)訪問這個(gè)實(shí)例的公共的靜態(tài)方法(通常為getInstance方法),從?而返回唯一實(shí)例的一個(gè)引用
public?static?function?getInstance()
{
????if?(!(self::$_instance?instanceof?self))?{
//公有化靜態(tài)方法
????????self::$_instance?=?new?self();
????}
????return?self::$_instance;
}
$node?=?new?Node();
$node->set(0,?2);
$node->setAll(3);
return?$node->get(0);
class?Node
{
????private?static?int?$counter?=?0;?//?計(jì)數(shù)器,記錄是否被修改過?private?static?array?$array;?//?數(shù)組存儲(chǔ)
????private?static?int?$globalValue;?//?全局的值
????public?function?set($index,?$value)
????{
????????self::$array[$index]?=?[self::$counter,?$value];
????}
????public?function?get($index)
????{
????????$tmp?=?self::$array[$index][0];
????????$value?=?self::$array[$index][1];
????????if?($tmp?==?self::$counter)?return?$value;
????????return?self::$globalValue;
????}
????public?function?setAll($value)
????{
????????self::$counter++;
????????self::$globalValue?=?$value;
????}
}
3.Redis 緩存擊穿,緩存穿透,緩存雪崩區(qū)別及解決方案
緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),而用戶不斷發(fā)起請(qǐng)求,造成了類似攻擊行
為
緩存擊穿是大批量的請(qǐng)求在訪問一個(gè)key,這個(gè)key失效的瞬間,請(qǐng)求打到了數(shù)據(jù)庫?
緩存雪崩是大批量的請(qǐng)求在訪問大批量的key,這些key同時(shí)失效,所有請(qǐng)求打到數(shù)據(jù) 庫,造成數(shù)據(jù)庫無法響應(yīng)。
避免雪崩是給key加一個(gè)隨機(jī)生存時(shí)間,例如都是 3分鐘,給他們加一個(gè)random_int(1,30) 這樣的時(shí)間,不會(huì)同時(shí)失效,或者熱點(diǎn)數(shù)據(jù)長(zhǎng)期有效,至少過完高并 發(fā)的這幾天再失效。
避免穿透是接口層增加校驗(yàn),比如用戶鑒權(quán)校驗(yàn),參數(shù)做校驗(yàn),不合法的參數(shù)直接代碼
return,同時(shí)nginx層面限制ip請(qǐng)求頻率。也可以借助布隆過濾器,從其中判斷key存不
存在,不存在直接return ;
避免擊穿最簡(jiǎn)單是讓key長(zhǎng)期有效。
4.PHP 查找兩個(gè)有序數(shù)組的相同元素 還是雙指針的經(jīng)典妙用
public?function?findTheSameItems($arr1,$arr2)?{
????$size1?=?count($arr1);
????$size2?=?count($arr2);
????$i?=?$j?=?0;
????$result?=?[];
????while?(true)?{//移動(dòng)值較小的
????????if?($arr1[$i]?>?$arr2[$j])
????????????$j++;
????????elseif?($arr1[$i]?$arr2[$j])
????????????$i++;?else?{
????????????$result[]?=?$arr1[$i];
????????????$j++;?}
????????if?($i?==?$size1?||?$j?==?$size2)
????????????break;
????}
????return?$result;
}
配上二分查找的套路:
#?二分查找
function?binarySearch(array?$arr,?$target)
{
????$low?=?0;
????$high?=?count($arr)?-?1;
????while?($low?<=?$high)?{
????????$mid?=?floor(($low?+?$high)?/?2);?#?找到元素
????????if?($arr[$mid]?==?$target)?return?$mid;?#?中間元素比目標(biāo)大,查找左邊
????????if?($arr[$mid]?>?$target)?$high?=?$mid?-?1;
????#?中間元素比右邊小,查找右邊
????????if?($arr[$mid]?$target)?$low?=?$mid?+?1;
????}
????#查找失敗
????return?false;
}
借助二分查找實(shí)現(xiàn)開根號(hào)計(jì)算:
function?mySqrt($x)
{
????if?($x?<=?1)?return?$x;
????$left?=?1;
????$right?=?$x?-?1;
????while?($left?<=?$right)?{
????????$mid?=?$left?+?(($right?-?$left)?>>?1);
????????if?($mid?>?$x?/?$mid)?{
????????????$right?=?$mid?-?1;
????????}?else?if?($mid?$x?/?$mid)?{
????????????if?($mid?+?1?>?$x?/?($mid?+?1))?return?$mid;
????????????$left?=?$mid?+?1;
????????}?else?{
????????????return?$mid;
????????}
????}
????return?-1;?//?only?for?return?a?value
}在聊天對(duì)話框內(nèi)回復(fù)【激活碼】
即可獲取最新idea激活碼(實(shí)時(shí)更新)
-END-
右下角,您點(diǎn)贊和在看
小編工資漲2毛

