更新時間:2023-01-28 14:45:58 來源:動力節(jié)點 瀏覽1402次
設(shè)計模式是Java工程師日常工作中非常重要的一個技能,可以使用設(shè)計模式重構(gòu)整體的架構(gòu)代碼、提交代碼復(fù)用性、擴展性等等,如果大家想要成為Java工程師那么這項技能是必須會的,如果大家正處于找工作階段,那么這套戰(zhàn)略性的設(shè)計模式面試題就需要你掌握它。
1.什么是單例模式?
答:單例模式是一種常用的軟件設(shè)計模式,在應(yīng)用這個模式時,單例對象的類必須保證只有一個實例存在,整個系統(tǒng)只能使用一個對象實例。
優(yōu)點:不會頻繁地創(chuàng)建和銷毀對象,浪費系統(tǒng)資源。
使用場景:IO 、數(shù)據(jù)庫連接、Redis 連接等。
單例模式代碼實現(xiàn):
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
單例模式調(diào)用代碼:
public class Lesson7\_3 {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1 == singleton2);
}
}
程序的輸出結(jié)果:true
可以看出以上單例模式是在類加載的時候就創(chuàng)建了,這樣會影響程序的啟動速度,那如何實現(xiàn)單例模式的延遲加載?在使用時再創(chuàng)建?
單例延遲加載代碼:
// 單例模式-延遲加載版
class SingletonLazy {
private static SingletonLazy instance;
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
以上為非線程安全的,單例模式如何支持多線程?
使用 synchronized 來保證,單例模式的線程安全代碼:
class SingletonLazy {
private static SingletonLazy instance;
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
2.什么是簡單工廠模式?
答:簡單工廠模式又叫靜態(tài)工廠方法模式,就是建立一個工廠類,對實現(xiàn)了同一接口的一些類進行實例的創(chuàng)建。比如,一臺咖啡機就可以理解為一個工廠模式,你只需要按下想喝的咖啡品類的按鈕(摩卡或拿鐵),它就會給你生產(chǎn)一杯相應(yīng)的咖啡,你不需要管它內(nèi)部的具體實現(xiàn),只要告訴它你的需求即可。
優(yōu)點:
工廠類含有必要的判斷邏輯,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實例,客戶端可以免除直接創(chuàng)建產(chǎn)品對象的責(zé)任,而僅僅“消費”產(chǎn)品;簡單工廠模式通過這種做法實現(xiàn)了對責(zé)任的分割,它提供了專門的工廠類用于創(chuàng)建對象;
客戶端無須知道所創(chuàng)建的具體產(chǎn)品類的類名,只需要知道具體產(chǎn)品類所對應(yīng)的參數(shù)即可,對于一些復(fù)雜的類名,通過簡單工廠模式可以減少使用者的記憶量;
通過引入配置文件,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類,在一定程度上提高了系統(tǒng)的靈活性。
缺點:
不易拓展,一旦添加新的產(chǎn)品類型,就不得不修改工廠的創(chuàng)建邏輯;
產(chǎn)品類型較多時,工廠的創(chuàng)建邏輯可能過于復(fù)雜,一旦出錯可能造成所有產(chǎn)品的創(chuàng)建失敗,不利于系統(tǒng)的維護。
簡單工廠代碼實現(xiàn):
class Factory {
public static String createProduct(String product) {
String result = null;
switch (product) {
case "Mocca":
result = "摩卡";
break;
case "Latte":
result = "拿鐵";
break;
default:
result = "其他";
break;
}
return result;
}
}
3.什么是抽象工廠模式?
答:抽象工廠模式是在簡單工廠的基礎(chǔ)上將未來可能需要修改的代碼抽象出來,通過繼承的方式讓子類去做決定。
比如,以上面的咖啡工廠為例,某天我的口味突然變了,不想喝咖啡了想喝啤酒,這個時候如果直接修改簡單工廠里面的代碼,這種做法不但不夠優(yōu)雅,也不符合軟件設(shè)計的“開閉原則”,因為每次新增品類都要修改原來的代碼。這個時候就可以使用抽象工廠類了,抽象工廠里只聲明方法,具體的實現(xiàn)交給子類(子工廠)去實現(xiàn),這個時候再有新增品類的需求,只需要新創(chuàng)建代碼即可。
抽象工廠實現(xiàn)代碼如下:
public class AbstractFactoryTest {
public static void main(String[] args) {
// 抽象工廠
String result = (new CoffeeFactory()).createProduct("Latte");
System.out.println(result); // output:拿鐵
}
}
// 抽象工廠
abstract class AbstractFactory{
public abstract String createProduct(String product);
}
// 啤酒工廠
class BeerFactory extends AbstractFactory{
@Override
public String createProduct(String product) {
String result = null;
switch (product) {
case "Hans":
result = "漢斯";
break;
case "Yanjing":
result = "燕京";
break;
default:
result = "其他啤酒";
break;
}
return result;
}
}
/\* \* 咖啡工廠 \*/
class CoffeeFactory extends AbstractFactory{
@Override
public String createProduct(String product) {
String result = null;
switch (product) {
case "Mocca":
result = "摩卡";
break;
case "Latte":
result = "拿鐵";
break;
default:
result = "其他咖啡";
break;
}
return result;
}
}
4.什么是觀察者模式?
觀察者模式是定義對象間的一種一對多依賴關(guān)系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關(guān)依賴對象皆得到通知并被自動更新。觀察者模式又叫做發(fā)布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監(jiān)聽器(Source/Listener)模式或從屬者(Dependents)模式。 優(yōu)點:
缺點:
在觀察者模式中有如下角色:
觀察者模式實現(xiàn)代碼如下。
1)定義觀察者(消息接收方)
/\* \* 觀察者(消息接收方) \*/
interface Observer {
public void update(String message);
}
/\* \* 具體的觀察者(消息接收方) \*/
class ConcrereObserver implements Observer {
private String name;
public ConcrereObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + ":" + message);
}
}
2)定義被觀察者(消息發(fā)送方)
/\* \* 被觀察者(消息發(fā)布方) \*/
interface Subject {
// 增加訂閱者
public void attach(Observer observer);
// 刪除訂閱者
public void detach(Observer observer);
// 通知訂閱者更新消息
public void notify(String message);
}
/\* \* 具體被觀察者(消息發(fā)布方) \*/
class ConcreteSubject implements Subject {
// 訂閱者列表(存儲信息)
private List<Observer> list = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
list.add(observer);
}
@Override
public void detach(Observer observer) {
list.remove(observer);
}
@Override
public void notify(String message) {
for (Observer observer : list) {
observer.update(message);
}
}
}
3)代碼調(diào)用
public class ObserverTest {
public static void main(String[] args) {
// 定義發(fā)布者
ConcreteSubject concreteSubject = new ConcreteSubject();
// 定義訂閱者
ConcrereObserver concrereObserver = new ConcrereObserver("老王");
ConcrereObserver concrereObserver2 = new ConcrereObserver("Java");
// 添加訂閱
concreteSubject.attach(concrereObserver);
concreteSubject.attach(concrereObserver2);
// 發(fā)布信息
concreteSubject.notify("更新了");
}
}
程序執(zhí)行結(jié)果如下:
老王:更新了
Java:更新了
以上就是“極高頻率出現(xiàn)的設(shè)計模式面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關(guān)內(nèi)容,可以關(guān)注動力節(jié)點Java官網(wǎng)。
相關(guān)閱讀