常用設計模式總結(面試常問)
Singleton(單例模式)
一句話總結:一個類在Java虛擬機器中只有一個物件,並提供一個全域性訪問點。
生活中例子:太陽、月亮、國家主席等。
解決什麼問題:物件的唯一性,效能浪費太多。
專案裡面怎麼用:資料庫連線物件,屬性配置檔案的讀取物件。
模式結構:分為餓漢式和懶漢式(如果考慮效能問題的話,就使用懶漢式,因為懶漢式是在方法裡面進行初始化的),構造器私 有化,對外提供方法加同步關鍵字。
框架裡面使用:Struts1的Action。
JDK裡面使用:java.lang.Runtime#getRuntimejava.awt.Desktop#getDesktop。
餓漢式程式碼:
public class HurgrySingleton { private static HurgrySingleton hurgry=new HurgrySingleton(); private HurgrySingleton(){}; public static HurgrySingleton getSinletonHurgry(){ return hurgry; } }
懶漢式程式碼:
public class LarzySingleton { private static LarzySingleton larzy=null; private LarzySingleton(){}; public static synchronized Larzy getSinletonLarzy(){ if(larzy==null){ larzy=new LarzySingleton(); } return larzy; } }
Factory(簡單的工廠模式)
一句話總結:用一個方法來代替new關鍵字
生活中的例子:製衣廠、麵包廠等生產廠。
解決什麼問題:物件產生過多,或者經常有子類替換生成。
專案裡面怎麼用:對於經常生成的物件,或者父子類替換的物件。
模式結構:寫一個對外宣告的方法,方法裡面使用new關鍵字代替。
框架裡面使用:spring的核心就是工廠模式。
JDK裡面使用:newInstance。
工廠模式程式碼:
public class UserFactory {
public static User createUser(int i){
//如果輸入的是1,就建立它的子類,否則就建立父類
if(i==1){
return new Alices();
}
return new User();
}
}
Proxy(代理模式)
一句話總結:為其他物件提供一個代理,以控制對當前物件的訪問。
生活中的例子:房屋中介、婚姻介紹所。
解決什麼問題:不能直接訪問該物件,或者太大的資源耗費多。
專案裡面怎麼用:許可權,或者大物件的訪問許可權。
模式結構:代理類和被代理類實現同一個介面,使用者訪問的時候先訪問代理物件,然後讓代理物件去訪問被代理物件。
框架裡面使用:Spring裡面的AOP實現。
JDK裡面使用:java.lang.reflect.Proxy。
代理模式程式碼:
建立一個介面:
public interface SellHouse {
void sell(double money);
}
//----
public class Hoster implements SellHouse {
@Override
public void sell(double money) {
System.out.println("祝你居住愉快");
}
}
//----
public class Medium implements SellHouse {
SellHouse hoster=new Hoster();
@Override
public void sell(double money) {
if(money>=1000){
hoster.sell(money);
}else{
System.out.println("你的價格太低了");
}
}
}
//----
public class Renter {
public static void main(String[] args) {
SellHouse renter=new Medium();
renter.sell(500);
}
}
Adapter(介面卡模式)
一句話總結:將兩個原來不相容的類相容起來一起工作。
生活中的例子:變壓器、充電器
解決什麼問題:已經存在的相同功能的程式碼,但是介面不相容,不能直接呼叫。
專案裡面怎麼用:在使用舊的API的時候,沒有原始碼,和新的不能相容。
模式結構:分為類介面卡和物件適配,一般常用的就是物件介面卡,因為組合由於繼承。
框架裡面使用:單元測試裡面的asserEquels。
JDK裡面使用:java.util.Arrays#asListjava.io.InputStreamReader(InputStream) java.io.outputStreamWriter(OutputStream)。
Strategy(策略模式)
一句話總結:定義一系列演算法並可以互相替換。
生活中的例子:圖片的格式,壓縮檔案的格式。
解決什麼問題:做一件事情有很多種方法。
專案裡面怎麼用:購物車裡面的付款方式。
模式結構:宣告一個頂級介面,定義一個策略方法,具體的例項都要實現這個介面。
框架裡面使用:hibernate的主鍵生成策略。
JDK裡面使用:java.util.Comparator#compare。
public interface Person {
void repast();
}
//-----
public class African implements Person {
@Override
public void repast() {
System.out.println("非洲人用手吃飯");
}
}
//------
public class America implements Person {
@Override
public void repast() {
System.out.println("美國人用刀叉吃飯");
}
}
//-----
public class Chinese implements Person {
@Override
public void repast() {
System.out.println("中國人用筷子吃飯");
}
}
//-----
public class Test {
public static void main(String[] args) {
Person chinese=new Chinese();
Person america=new America();
Person african=new African();
chinese.repast();
america.repast();
african.repast();
}
}
Template(模板模式)
一句話總結:父類定義流程,子類實現流程。
生活中的例子:iphone生產有多個國家,但流程只有一個。
解決什麼問題:業務有多種,但都有規定的流程。
專案裡面怎麼用:一般基類的實現都是模板模式,BaseDAO,bBaseService。
模式結構:定義一個抽象父類定義流程,或者常用方法和常量,子類繼承父類,實現具體的細節方法。
框架裡面使用:hibernate裡面的方言,是跨資料庫的基礎。
JDK裡面使用:IO流裡面的InputStream,Writer等。
模板模式程式碼:
public abstract class IPhoneTemplate {
public void createIPhone(){
setupCpu();
setupAll();
check();
box();
}
protected abstract void box();
protected abstract boolean check();
protected abstract void setupAll();
protected abstract void setupCpu();
}
//-------
public class ChinaIPhone extends IPhoneTemplate {
@Override
protected void box() {
System.out.println("box()");
}
@Override
protected boolean check() {
System.out.println("check()");
return true;
}
@Override
protected void setupAll() {
System.out.println("setupAll()");
}
@Override
protected void setupCpu() {
System.out.println("setupCpu()");
}
}
//-------
public class AfricanIPhone extends IPhoneTemplate {
@Override
protected void box() {
System.out.println("box()");
}
@Override
protected boolean check() {
System.out.println("check()");
return true;
}
@Override
protected void setupAll() {
System.out.println("setupAll()");
}
@Override
protected void setupCpu() {
System.out.println("setupCpu()");
}
}