自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:JDK中都用了哪些設(shè)計(jì)模式?

開發(fā) 前端
單例模式保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)。工廠模式提供了一種將對象創(chuàng)建的過程封裝在一個(gè)單獨(dú)的類中的方法,這個(gè)類就是工廠類。

設(shè)計(jì)模式是前輩們經(jīng)過實(shí)踐驗(yàn)證總結(jié)的解決方案,幫助我們構(gòu)建出更具可維護(hù)性、可擴(kuò)展性和可讀性的代碼。當(dāng)然,在面試的過程中,也會或多或少的被問到。那么今天,我們就來看一道設(shè)計(jì)模式中的常見面試問題:JDK 中都用了哪些設(shè)計(jì)模式?

我按照大家比較熟悉且好理解的方式,把  JDK 中使用的設(shè)計(jì)模式總結(jié)了一下,如下圖所示:

那么,接下來我們一個(gè)個(gè)來看。

1.單例模式

單例模式保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)。

Runtime 類使用了單例模式,如下源碼可知:

public class Runtime {
    private static final Runtime currentRuntime = new Runtime();
    private static Version version;
    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class {@code Runtime} are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the {@code Runtime} object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }
    /** Don't let anyone else instantiate this class */
    private Runtime() {}
    // 省略其他源碼
}

從以上源碼可以看出,Runtime 使用的餓漢方式實(shí)現(xiàn)了單例模式。

2.工廠模式

工廠模式提供了一種將對象創(chuàng)建的過程封裝在一個(gè)單獨(dú)的類中的方法,這個(gè)類就是工廠類。

線程池中的所有線程的創(chuàng)建都是通過工廠創(chuàng)建的,使用的就是工廠模式,具體源碼如下:

3.代理模式

代理模式是一種為其他對象提供一種代理以控制對這個(gè)對象的訪問的設(shè)計(jì)模式。代理對象在客戶端和目標(biāo)對象之間起到中介的作用,并且可以去掉客戶不能看到的內(nèi)容和服務(wù)或者添加客戶需要的額外服務(wù)。

JDK 內(nèi)置了動態(tài)代理的功能,動態(tài)代理是代理模式的一種實(shí)現(xiàn),它是由 java.lang.reflect.Proxy 類提供的。

Proxy 使用 Demo 如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 1.接口
interface Subject {
    void doSomething();
}

// 2.目標(biāo)類(被代理類)
class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("RealSubject is doing something");
    }
}

// 3.動態(tài)代理類
class DynamicProxyHandler implements InvocationHandler {
    private Object target;
    DynamicProxyHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before calling method");
        Object result = method.invoke(target, args);
        System.out.println("After calling method");
        return result;
    }
}

public class JDKProxyDemo {
    public static void main(String[] args) {
        // 創(chuàng)建真實(shí)對象
        Subject realSubject = new RealSubject();
        // 創(chuàng)建動態(tài)代理處理器
        InvocationHandler handler = new DynamicProxyHandler(realSubject);
        // 創(chuàng)建代理對象
        Subject proxySubject = (Subject) Proxy.newProxyInstance(
            realSubject.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            handler);
        // 調(diào)用代理對象的方法
        proxySubject.doSomething();
    }
}

4.迭代器模式

迭代器模式能夠提供一種簡單的方法來遍歷容器中的每個(gè)元素。通過迭代器,用戶可以輕松地訪問容器中所有的元素,簡化了編程過程。

Iterable 就是標(biāo)準(zhǔn)的迭代器模式,Collection 就是 Iterator 的子類,它的使用代碼如下:

import java.util.ArrayList;
import java.util.Iterator;

public class IteratorDemo {
    public static void main(String[] args) {
        // 創(chuàng)建一個(gè) ArrayList 并添加元素
        ArrayList<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Orange");

        // 獲取迭代器
        Iterator<String> iterator = list.iterator();

        // 使用迭代器遍歷集合
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            System.out.println("Fruit: " + fruit);
        }
    }
}

5.模版方法模式

模板方法模式(Template Method Pattern)定義了一個(gè)操作中的算法骨架,將一些步驟延遲到子類中實(shí)現(xiàn)。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某些步驟。

在 AQS(AbstractQueuedSynchronizer) 中,acquire 方法和 release 方法使用了模板方法模式。

這些方法之所以被認(rèn)為是模板方法模式,是因?yàn)樗鼈兌x了一個(gè)操作的基本框架或流程,但其中的某些關(guān)鍵步驟被設(shè)計(jì)為抽象方法,留給子類去具體實(shí)現(xiàn)。

以 acquire 方法為例,它大致的流程包括嘗試獲取資源、如果獲取失敗則將當(dāng)前線程加入等待隊(duì)列、阻塞線程等步驟。但是具體如何判斷能否獲取資源(通過調(diào)用 tryAcquire 方法),以及在獲取失敗后的一些處理細(xì)節(jié),是由子類去實(shí)現(xiàn)的,具體源碼如下:

protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}

例如,基于 AQS 實(shí)現(xiàn)的 ReentrantLock 中就重寫了 tryAcquire 方法,實(shí)現(xiàn)源碼如下:

6.裝飾器模式

裝飾器模式是在不修改原對象的基礎(chǔ)上,動態(tài)地給對象添加額外功能的設(shè)計(jì)模式。

BufferedInputStream 就是典型裝飾器模式,當(dāng)使用普通的 InputStream 讀取數(shù)據(jù)時(shí),每次可能都會進(jìn)行實(shí)際的 I/O 操作,而 BufferedInputStream 會先將一部分?jǐn)?shù)據(jù)讀入緩沖區(qū),后續(xù)的讀取操作可以直接從緩沖區(qū)獲取,減少了實(shí)際的 I/O 次數(shù)。

例如以下代碼:

InputStream inputStream = new FileInputStream("file.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

BufferedInputStream 并沒有改變 FileInputStream 的基本結(jié)構(gòu)和接口,只是為其添加了緩沖的特性。

7.策略模式

策略模式定義了一系列可互換的算法,并將每一個(gè)算法封裝起來,使它們可以互相替換。

Comparator 是策略模式的一個(gè)典型例子,Comparator 接口定義了一個(gè)比較兩個(gè)對象的方法 compare(T o1, T o2)。這個(gè)接口允許用戶定義不同的比較策略,使得我們可以靈活地改變排序或比較邏輯。

例如以下示例代碼:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class StrategyPatternExample {
    static class Person {
        private String name;
        private int age;
        // 忽略 Setter、Getter 等方法
    }
    // 按照年齡升序排列
    static class AgeComparator implements Comparator<Person> {
        @Override
        public int compare(Person p1, Person p2) {
            return Integer.compare(p1.getAge(), p2.getAge());
        }
    }
    // 按照姓名降序排列
    static class NameDescendingComparator implements Comparator<Person> {
        @Override
        public int compare(Person p1, Person p2) {
            return p2.getName().compareTo(p1.getName());
        }
    }
    public static void main(String[] args) {
        ArrayList<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        // 使用年齡升序的策略
        Collections.sort(people, new AgeComparator());

        // 使用姓名降序的策略
        Collections.sort(people, new NameDescendingComparator());
    }
}

8.建造者模式

建造者模式是一種創(chuàng)建型設(shè)計(jì)模式,用于通過一系列的步驟來創(chuàng)建復(fù)雜的對象。它將對象的構(gòu)建過程與其表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

在 JDK 中,使用建造者模式的常見例子是 StringBuilder 和 StringBuffer 類。

雖然這兩個(gè)類本身不是傳統(tǒng)意義上的建造者模式實(shí)現(xiàn)(因?yàn)榻ㄔ煺吣J酵ǔS糜跇?gòu)建不同的表示或者不同部分的同一個(gè)對象),它們提供了一種鏈?zhǔn)秸{(diào)用的方式來構(gòu)建和修改字符串,這在某種程度上體現(xiàn)了建造者模式的思想。

例如以下代碼:

public class StringBuilderDemo {  
    public static void main(String[] args) {  
        // 使用 StringBuilder 構(gòu)建和修改字符串  
        StringBuilder builder = new StringBuilder();  
        builder.append("Hello")  
        .append(", ")  
        .append("world")  
        .append("!")  
        .insert(7, "beautiful ")  
        .deleteCharAt(13);  

        // 輸出構(gòu)建和修改后的字符串  
        System.out.println(builder.toString());  
        // 輸出: Hello, beautiful world!  
    }  
}

StringBuilder 通過鏈?zhǔn)秸{(diào)用 append、insert 和 deleteCharAt 方法來逐步構(gòu)建和修改字符串。這種方式使得構(gòu)建和修改字符串的過程更加流暢和易于閱讀。

責(zé)任編輯:姜華 來源: 磊哥和Java
相關(guān)推薦

2019-05-29 17:20:07

Spring設(shè)計(jì)模式Java

2020-03-18 09:43:37

開發(fā)技能代碼

2024-05-30 07:37:30

2023-07-11 08:50:34

2022-11-23 07:41:52

JDKStream關(guān)鍵字

2021-10-29 09:40:21

設(shè)計(jì)模式軟件

2023-02-20 08:08:48

限流算法計(jì)數(shù)器算法令牌桶算法

2021-08-02 17:21:08

設(shè)計(jì)模式訂閱

2025-03-26 01:25:00

MySQL優(yōu)化事務(wù)

2024-03-07 17:21:12

HotSpotJVMHot Code

2021-05-10 08:01:12

BeanFactoryFactoryBean容器

2024-02-26 14:07:18

2024-04-19 00:00:00

計(jì)數(shù)器算法限流算法

2024-03-12 14:36:44

微服務(wù)HTTPRPC

2022-04-29 08:17:38

RPC遠(yuǎn)程代理代理模式

2023-07-05 08:17:38

JDK動態(tài)代理接口

2024-08-19 09:13:02

2024-06-04 07:38:10

2024-02-01 08:08:53

Spring過濾器類型Gateway

2021-08-11 08:53:23

Git命令面試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號