工業轉型與綠色振興聲明 就政策、技術、金融三個領域提出建言

文:台大風險政策中心 RSPRC;林怡均翻譯;趙家緯審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

海洋最大謎團——沒人看過鯨鯊生小孩 科學家取得腹部超音波仍無果

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

亞馬遜6月毀林創紀錄 巴西太空署總督導下台

摘錄自2020年7月14日中央社報導

巴西政府免去國家太空署(INPE)地球觀測站總督導溫海斯(Lubia Vinhas)的職位,免職書由科技部長龐特斯(Marcos Pontes)簽署,刊登在今(13日)的國家公報。

溫海斯接受環球電視(TV Globo)訪問時說,她通過高考進入國家太空署服務23年了,所以就算被免去管理職位,也將繼續待在機關。溫海斯也表示不曉得為何被免職,說自己是通過國家公報才知道被調職。

上週巴西國家太空署公布報告,今年6月份的毀林警報數量創下2015年以來當月最高紀錄。今年上半年累計的警報顯示,亞馬遜遭破壞面積達3069.57平方公里,與2019年上半年相比增加25%。僅6月的毀林警報範圍就達1034.4平方公里。

溫海斯遭免職後,國際環保團體綠色和平組織(Greenpeace)發表聲明表示,基於巴西總統波索納洛(Jair Bolsonaro)政府先前的決定,溫海斯被免職並不意外,只是再次顯示「巴西政府是真理的敵人」。

巴西經濟部長葛德斯(Paulo Guedes)今天在經濟合作暨發展組織(OECD)線上會議中表示,巴西願意配合和幫助保護環境;如果巴西的環境政策出現錯誤或過度行為,也將予以糾正。

生物多樣性
國際新聞
巴西
亞馬遜雨林
森林

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準

俄羅斯計畫2032年前清除七艘廢棄核潛艦

摘錄自2020年7月14日自由時報報導

為解決海域核污染問題,俄羅斯正在設計建造能夠打撈沉沒在大海中的核動力潛艦,整個工作預計要進行到2032年。

《Defense World》報導,在第23屆俄羅斯-挪威聯合委員會會議中,改善核能與輻射安全成為主要議題。俄羅斯計畫清除七艘沉沒在北極海域的核潛艇,「K-159」和「K-27」從打撈到拆解預計各自花費四年時間,分別為2025至2028年、2028至2031年,另外5艘則在2029至2032年完成。

報導指出,在1990年代,超過100艘除役的核潛艇被放置在九個不同地點,目前有兩個地點的核潛艇已被清除,自2004年起,放射性廢料減少了一半以上,從1110萬居禮下降至509萬居禮。

能源轉型
國際新聞
俄羅斯
核子潛艦
核污染
核能

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

※回頭車貨運收費標準

邁向碳中合歐盟 擬設統一能源部門

摘錄自2020年7月13日台灣醒報報導

歐洲議會推設立「統一能源部門」,促歐盟各國實現碳中合目標!奧地利的歐洲議員嘉夢日前在一場會議中,提出設立「歐洲統一能源部門」,將協助整合各國現有的能源法規、打造歐盟再生能源中心及促進工業及交通運輸轉型為使用綠色能源,獲得多數議員支持。

歐盟許多成員國包括芬蘭、丹麥已設下2050年以前要實現「碳中合」的目標,即便是將脫歐的英國也曾承諾跟進。根據歐盟調查,為了實現碳中合目標,歐盟整體的用電量將從25%提升到50%,嘉夢說:「實現碳中合,非常需要各國政府機關朝使用綠色能源邁進,因此,我們需要一個部門負責協調整合。」

除了統一各國現有的能源政策及法規外,該部門也將負責打造歐盟再生能源中心、提升各國的太陽能、生物能發電等基礎設施的普及率、研究並部署綠色能源科技,以及協助將乾淨能源的使用範圍擴張到傳統上依賴化石燃料的領域中,例如提倡綠色建築、工業和交通運輸。

能源議題
再生能源
能源轉型
國際新聞
歐盟
碳中和

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

疫情害到孤兒象 動保組織難自保

摘錄自2020年7月13日台灣醒報報導

從1977年成立至今的肯亞大象保護組織「雪德瑞克基金會」,因收入短缺,已停止派員保護孤兒象。

根據「世界自然基金會」2019年的報告指出,非洲在地的動保組織重要性極高,他們預估,如果放任盜獵行為或讓大象繼續闖入人類地盤與人發生衝突,以這樣的速率發展,非洲大象將滅在2040年完全滅絕。

據《獨立報》報導,無獨有偶,泰國觀光景點的大象也面臨生死存亡的處境。儘管近幾年來泰國一再有虐待大象的事情發生,也被抨擊利用大象賺錢不人道,但據當地業者表示,現在讓動物們吃飽已成為當務之急。每天餵食一頭大象的成本可高達40美元,是泰國人每日基本薪資的3倍以上,大象聯盟協會主席舂布拉干表示,除非政府伸出援手,否則這些大象將被迫重回街頭,或進行非法砍伐。

物種保育
生物多樣性
土地利用
國際新聞
非洲
泰國
武漢肺炎
動物與大環境變遷
大象
大象盜獵
動物保護組織
貧窮

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

重學 Java 設計模式:實戰裝飾器模式(SSO單點登錄功能擴展,增加攔截用戶訪問方法範圍場景)

作者:小傅哥
博客:https://bugstack.cn

沉澱、分享、成長,讓自己和他人都能有所收穫!

一、前言

對於代碼你有編程感覺嗎

很多人寫代碼往往是沒有編程感覺的,也就是除了可以把功能按照固定的流程編寫出流水式的代碼外,很難去思考整套功能服務的擴展性和可維護性。尤其是在一些較大型的功能搭建上,比較缺失一些駕馭能力,從而導致最終的代碼相對來說不能做到盡善盡美。

江洋大盜與江洋大偷

兩個本想描述一樣的意思的詞,只因一字只差就讓人覺得一個是好牛,一個好搞笑。往往我們去開發編程寫代碼時也經常將一些不恰當的用法用於業務需求實現中,當卻不能意識到。一方面是由於編碼不多缺少較大型項目的實踐,另一方面是不思進取的總在以完成需求為目標缺少精益求精的工匠精神。

書從來不是看的而是用的

在這個學習資料幾乎爆炸的時代,甚至你可以輕易就獲取幾個T的視頻,小手輕輕一點就收藏一堆文章,但卻很少去看。學習的過程從不只是簡單的看一遍就可以,對於一些實操性的技術書籍,如果真的希望學習到知識,那麼一定是把這本書用起來而絕對不是看起來。

二、開發環境

  1. JDK 1.8
  2. Idea + Maven
  3. 涉及工程三個,可以通過關注公眾號bugstack蟲洞棧,回復源碼下載獲取(打開獲取的鏈接,找到序號18)
工程 描述
itstack-demo-design-9-00 場景模擬工程;模擬單點登錄類
itstack-demo-design-9-01 使用一坨代碼實現業務需求
itstack-demo-design-9-02 通過設計模式優化改造代碼,產生對比性從而學習

三、裝飾器模式介紹

初看上圖感覺裝飾器模式有點像俄羅斯套娃、某眾汽車,而裝飾器的核心就是再不改原有類的基礎上給類新增功能。不改變原有類,可能有的小夥伴會想到繼承、AOP切面,當然這些方式都可以實現,但是使用裝飾器模式會是另外一種思路更為靈活,可以避免繼承導致的子類過多,也可以避免AOP帶來的複雜性。

你熟悉的場景很多用到裝飾器模式

new BufferedReader(new FileReader(""));,這段代碼你是否熟悉,相信學習java開發到字節流、字符流、文件流的內容時都見到了這樣的代碼,一層嵌套一層,一層嵌套一層,字節流轉字符流等等,而這樣方式的使用就是裝飾器模式的一種體現。

四、案例場景模擬

在本案例中我們模擬一個單點登錄功能擴充的場景

一般在業務開發的初期,往往內部的ERP使用只需要判斷賬戶驗證即可,驗證通過後即可訪問ERP的所有資源。但隨着業務的不斷髮展,團隊里開始出現專門的運營人員、營銷人員、數據人員,每個人員對於ERP的使用需求不同,有些需要創建活動,有些只是查看數據。同時為了保證數據的安全性,不會讓每個用戶都有最高的權限。

那麼以往使用的SSO是一個組件化通用的服務,不能在裏面添加需要的用戶訪問驗證功能。這個時候我們就可以使用裝飾器模式,擴充原有的單點登錄服務。但同時也保證原有功能不受破壞,可以繼續使用。

1. 場景模擬工程

itstack-demo-design-9-00
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                ├── HandlerInterceptor.java
                └── SsoInterceptor.java
  • 這裏模擬的是spring中的類:HandlerInterceptor,實現起接口功能SsoInterceptor模擬的單點登錄攔截服務。
  • 為了避免引入太多spring的內容影響對設計模式的閱讀,這裏使用了同名的類和方法,盡可能減少外部的依賴。

2. 場景簡述

2.1 模擬Spring的HandlerInterceptor

public interface HandlerInterceptor {

    boolean preHandle(String request, String response, Object handler);

}
  • 實際的單點登錄開發會基於;org.springframework.web.servlet.HandlerInterceptor 實現。

2.2 模擬單點登錄功能

public class SsoInterceptor implements HandlerInterceptor{

    public boolean preHandle(String request, String response, Object handler) {
        // 模擬獲取cookie
        String ticket = request.substring(1, 8);
        // 模擬校驗
        return ticket.equals("success");
    }

}
  • 這裏的模擬實現非常簡單隻是截取字符串,實際使用需要從HttpServletRequest request對象中獲取cookie信息,解析ticket值做校驗。
  • 在返回的裏面也非常簡單,只要獲取到了success就認為是允許登錄。

五、用一坨坨代碼實現

此場景大多數實現的方式都會採用繼承類

繼承類的實現方式也是一個比較通用的方式,通過繼承后重寫方法,併發將自己的邏輯覆蓋進去。如果是一些簡單的場景且不需要不斷維護和擴展的,此類實現並不會有什麼,也不會導致子類過多。

1. 工程結構

itstack-demo-design-9-01
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                └── LoginSsoDecorator.java
  • 以上工程結構非常簡單,只是通過 LoginSsoDecorator 繼承 SsoInterceptor,重寫方法功能。

2. 代碼實現

public class LoginSsoDecorator extends SsoInterceptor {

    private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();

    static {
        authMap.put("huahua", "queryUserInfo");
        authMap.put("doudou", "queryUserInfo");
    }

    @Override
    public boolean preHandle(String request, String response, Object handler) {
        // 模擬獲取cookie
        String ticket = request.substring(1, 8);
        // 模擬校驗
        boolean success = ticket.equals("success");

        if (!success) return false;

        String userId = request.substring(9);
        String method = authMap.get(userId);

        // 模擬方法校驗
        return "queryUserInfo".equals(method);
    }

}
  • 以上這部分通過繼承重寫方法,將個人可訪問哪些方法的功能添加到方法中。
  • 以上看着代碼還算比較清晰,但如果是比較複雜的業務流程代碼,就會很混亂。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_LoginSsoDecorator() {
    LoginSsoDecorator ssoDecorator = new LoginSsoDecorator();
    String request = "1successhuahua";
    boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
    System.out.println("登錄校驗:" + request + (success ? " 放行" : " 攔截"));
}
  • 這裏模擬的相當於登錄過程中的校驗操作,判斷用戶是否可登錄以及是否可訪問方法。

3.2 測試結果

登錄校驗:1successhuahua 攔截

Process finished with exit code 0
  • 從測試結果來看滿足我們的預期,已經做了攔截。如果你在學習的過程中,可以嘗試模擬單點登錄並繼承擴展功能。

六、裝飾器模式重構代碼

接下來使用裝飾器模式來進行代碼優化,也算是一次很小的重構。

裝飾器主要解決的是直接繼承下因功能的不斷橫向擴展導致子類膨脹的問題,而是用裝飾器模式后就會比直接繼承顯得更加靈活同時這樣也就不再需要考慮子類的維護。

在裝飾器模式中有四個比較重要點抽象出來的點;

  1. 抽象構件角色(Component) – 定義抽象接口
  2. 具體構件角色(ConcreteComponent) – 實現抽象接口,可以是一組
  3. 裝飾角色(Decorator) – 定義抽象類並繼承接口中的方法,保證一致性
  4. 具體裝飾角色(ConcreteDecorator) – 擴展裝飾具體的實現邏輯

通過以上這四項來實現裝飾器模式,主要核心內容會體現在抽象類的定義和實現上。

1. 工程結構

itstack-demo-design-9-02
└── src
    └── main
        └── java
            └── org.itstack.demo.design
                ├── LoginSsoDecorator.java
                └── SsoDecorator.java

裝飾器模式模型結構

  • 以上是一個裝飾器實現的類圖結構,重點的類是SsoDecorator,這個類是一個抽象類主要完成了對接口HandlerInterceptor繼承。
  • 當裝飾角色繼承接口後會提供構造函數,入參就是繼承的接口實現類即可,這樣就可以很方便的擴展出不同功能組件。

2. 代碼實現

2.1 抽象類裝飾角色

public abstract class SsoDecorator implements HandlerInterceptor {

    private HandlerInterceptor handlerInterceptor;

    private SsoDecorator(){}

    public SsoDecorator(HandlerInterceptor handlerInterceptor) {
        this.handlerInterceptor = handlerInterceptor;
    }

    public boolean preHandle(String request, String response, Object handler) {
        return handlerInterceptor.preHandle(request, response, handler);
    }

}
  • 在裝飾類中有兩個重點的地方是;1)繼承了處理接口、2)提供了構造函數、3)覆蓋了方法preHandle
  • 以上三個點是裝飾器模式的核心處理部分,這樣可以踢掉對子類繼承的方式實現邏輯功能擴展。

2.2 裝飾角色邏輯實現

public class LoginSsoDecorator extends SsoDecorator {

    private Logger logger = LoggerFactory.getLogger(LoginSsoDecorator.class);

    private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();

    static {
        authMap.put("huahua", "queryUserInfo");
        authMap.put("doudou", "queryUserInfo");
    }

    public LoginSsoDecorator(HandlerInterceptor handlerInterceptor) {
        super(handlerInterceptor);
    }

    @Override
    public boolean preHandle(String request, String response, Object handler) {
        boolean success = super.preHandle(request, response, handler);
        if (!success) return false;
        String userId = request.substring(8);
        String method = authMap.get(userId);
        logger.info("模擬單點登錄方法訪問攔截校驗:{} {}", userId, method);
        // 模擬方法校驗
        return "queryUserInfo".equals(method);
    }
}
  • 在具體的裝飾類實現中,繼承了裝飾類SsoDecorator,那麼現在就可以擴展方法;preHandle
  • preHandle的實現中可以看到,這裏只關心擴展部分的功能,同時不會影響原有類的核心服務,也不會因為使用繼承方式而導致的多餘子類,增加了整體的靈活性。

3. 測試驗證

3.1 編寫測試類

@Test
public void test_LoginSsoDecorator() {
    LoginSsoDecorator ssoDecorator = new LoginSsoDecorator(new SsoInterceptor());
    String request = "1successhuahua";
    boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
    System.out.println("登錄校驗:" + request + (success ? " 放行" : " 攔截"));
}
  • 這裏測試了對裝飾器模式的使用,通過透傳原有單點登錄類new SsoInterceptor(),傳遞給裝飾器,讓裝飾器可以執行擴充的功能。
  • 同時對於傳遞者和裝飾器都可以是多組的,在一些實際的業務開發中,往往也是由於太多類型的子類實現而導致不易於維護,從而使用裝飾器模式替代。

3.2 測試結果

23:50:50.796 [main] INFO  o.i.demo.design.LoginSsoDecorator - 模擬單點登錄方法訪問攔截校驗:huahua queryUserInfo
登錄校驗:1successhuahua 放行

Process finished with exit code 0
  • 結果符合預期,擴展了對方法攔截的校驗性。
  • 如果你在學習的過程中有用到過單點登陸,那麼可以適當在裏面進行擴展裝飾器模式進行學習使用。
  • 另外,還有一種場景也可以使用裝飾器。例如;你之前使用某個實現某個接口接收單個消息,但由於外部的升級變為發送list集合消息,但你又不希望所有的代碼類都去修改這部分邏輯。那麼可以使用裝飾器模式進行適配list集合,給使用者依然是for循環后的單個消息。

七、總結

  • 使用裝飾器模式滿足單一職責原則,你可以在自己的裝飾類中完成功能邏輯的擴展,而不影響主類,同時可以按需在運行時添加和刪除這部分邏輯。另外裝飾器模式與繼承父類重寫方法,在某些時候需要按需選擇,並不一定某一個就是最好。
  • 裝飾器實現的重點是對抽象類繼承接口方式的使用,同時設定被繼承的接口可以通過構造函數傳遞其實現類,由此增加擴展性並重寫方法里可以實現此部分父類實現的功能。
  • 就像夏天熱你穿短褲,冬天冷你穿棉褲,雨天挨澆你穿雨衣一樣,你的根本本身沒有被改變,而你的需求卻被不同的裝飾而實現。生活中往往比比皆是設計,當你可以融合這部分活靈活現的例子到代碼實現中,往往會創造出更加優雅的實現方式。

八、推薦閱讀

  • 1. 重學 Java 設計模式:實戰工廠方法模式(多種類型商品發獎場景)
  • 2. 重學 Java 設計模式:實戰抽象工廠模式(替換Redis雙集群升級場景)
  • 3. 重學 Java 設計模式:實戰建造者模式(裝修物料組合套餐選配場景)
  • 4. 重學 Java 設計模式:實戰原型模式(多套試每人題目和答案亂序場景)
  • 5. 重學 Java 設計模式:實戰橋接模式(多支付渠道「微信、支付寶」與多支付模式「刷臉、指紋」場景)
  • 6. 重學 Java 設計模式:實戰組合模式(營銷差異化人群發券,決策樹引擎搭建場景)

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※回頭車貨運收費標準

給女朋友講解什麼是Git

前言

在周六發現了Linus去Google演講的一個視頻,當時還發了一條朋友圈:

有興趣的同學也可以去看看,一點兒也不無聊,在線看Linus大佬懟人

https://www.bilibili.com/video/BV1xb411A7ac?from=search&seid=4239535088233137638

朋友圈的評論有幾個人問我女朋友

我又恰好給我女朋友科普過什麼是Git,所以這篇文章就有了。

Git介紹

Git是幹啥用的?它是一個版本控制軟件。

Git這個玩意三歪曾經還給女朋友給科普過(三歪會經常給女朋友說點技術的東西,我也不知道她到底聽懂了沒有,反正她每次都說好像有點懂了)。

當時情況是這樣的,某一天她跟三歪說:我做的Excel還沒保存,電腦藍屏死機了,東西全丟了。

於是三歪說:這…我也沒怎麼用過Excel這類的軟件,要不看看你用的WPS或者Office?有沒有相關的備份功能或者說是自動保存?

三歪順手找了一下WPS是有備份(自動保存)功能的,時間什麼的要自己定義一下。

三歪還補了一句:這種情況要是在程序員的手上感覺發生的概率會低一點,程序員習慣會按ctrl+s。甚至有的時候,看着看着網頁還會按ctrl+s。不過像我們寫代碼的工具(IDEA)都不用自己手動保存了….

過了一會,她說藍屏之前做的東西找不回來了,沒設置自動保存。

三歪又感嘆一句:我們寫代碼還有版本控制的軟件,在這個過程中會記錄每次修改的內容,誰改了什麼東西。誰改錯了,誰要背鍋,一個都不能跑

女朋友聽着三歪一頓亂吹,貌似也有點感興趣:“版本控制是什麼東西?這麼厲害的嗎?會計就經常要背鍋”

三歪:“其實也沒啥,就是我們一般寫代碼往往都是多人協作的。你們會計可能是每個人負責一張表(Excel),然後把已完成好的表傳給下一個人。而寫代碼的不一樣,我們都是在同一個項目裡邊編寫的,不會單獨等着某個人做完了,其他的人再開始動手”

女朋友:“嗯?然後呢”

三歪:“你可以理解成,我們多個人會在同一個目錄下編寫代碼,裡邊可能會做更改或者添加文件的操作。項目組裡的所有人都可以對這個目錄修改,改完了我們會提交,然後發布上線系統。”

女朋友:“啥?你是不是偏題了?這跟發布上線系統有啥關係?”

三歪:“哦,我還是舉個例子吧。就比如我們寫論文的時候可能要對論文不斷修改,我們的修改是基於原有的基礎上改的”

三歪繼續補充:”因為我們怕在原來的基礎改錯了東西,沒法恢復,所以,我們可能會有多個「畢業論文」的文件。而我們寫代碼的時候本身就是「多人協作」的,修改是無法避免的,我們不希望有多個文件的產生,又希望能夠記錄每次更改的內容。“

三歪:”更改的內容指的就是:基於原有的基礎上更改了什麼,以及提交者是誰。這樣子,我們就沒法甩鍋了。說白了就是,我們能知道的文件被改了什麼,以及誰改了“。

三歪:“到這裏,有問題嗎?”

女朋友:“嗯,沒問題,你繼續”

三歪:“「每一次的修改」我們稱為一個版本,它能夠實現版本與版本之間的來回穿梭。打個比方,我有篇文章寫了一周,這期間有10個版本,我能隨意回到我想要的版本。所以它叫做版本控制軟件”

女朋友:“我大致聽懂了,大概就是每一次修改都會被記錄下來,然後你們就可以知道每一次版本修改了什麼,是誰改的,如果做錯了,可以通過這個軟件回到想要的版本”

三歪:“嗯,就是這個意思”

女朋友:“那我想問個問題,你一直提到的「多人協作」是在同一個目錄下對文件修改的,然後可以看到彼此改了什麼。那你是在你的電腦上改,你的同事是在他的電腦上改的,你們是怎麼看到彼此改了什麼?這現在有這麼厲害的東西了嗎?“

三歪:”哦~你的意思大概就是:我們又不聯網,怎麼知道對方改了什麼,是這個意思吧?“

女朋友:“嗯,是的”

三歪:“你的理解是沒錯的,我們之間不聯網,是沒辦法知道對方改了什麼的。我漏了一點沒說,我們在改到一定程度下(比如說這個功能我們做完了、也可能做得差不多了),我們會把當前版本提交到遠程倉庫上”

三歪繼續補充:“可以發現的是,提交到遠程倉庫后,即便我們電腦壞了,我們可以從遠程倉庫再把這份數據拉取下來。”

女朋友:“所以呢?遠程倉庫到我這聽起來就是一個備份的功能吧?你們怎麼知道對方改了什麼?”

三歪:“是這樣的,我們從遠程倉庫拉取代碼的時候除了會把有變動的代碼同步到自己的電腦上,還會把所有修改的記錄也同步到自己的電腦上。所以說,我們會知道彼此修改的內容。”

女朋友:”聽着很有用啊,我平時用的word和excel可以用這個軟件嗎?即便我電腦壞了,我還可以去『遠程倉庫』拿到上一次我提交的數據,並且還有你所說的『版本控制』功能。又能備份,又能知道每次修改了什麼,很好用啊!“

三歪:”很可惜,像你們那種工作場景,可能用不上,也可以說不太適合用“

女朋友:”為什麼?“

三歪:”之前我也想要用定時任務+GitHub的方式去保存我在本地寫的文章,發出來之後,被一頓噴。GitHub你可以簡單理解為就是那個遠程倉庫,定時任務我就是讓它隔一段時間就保存一次“

女朋友:”我聽明白了,你想要的是備份功能,對吧?為什麼被噴的呢?“

三歪:”他們說我瞎整,這每隔一段時間就提交到GitHub,網絡開銷可多大啊。然後給我列出一系列的產品,比如說:「堅果雲」「Dropbox」「OneDrive」等等“

女朋友:”那你怎麼不用?“

三歪:”我哪知道啊,有信息差的呢。反正當時覺得自己寫個定時任務實現了,就沒多想了。“

女朋友:”那你是真的菜“

三歪:”哦“

三歪:”除了上面說的自動同步,你們的word、excel在用我們的工具也沒法查到歷史的版本記錄“

女朋友:”為啥?你不是說你們寫代碼都可以的嗎?為什麼word和excel就沒法查?“

三歪:”我們寫代碼的文件類型都是屬於文本文件,而你的word、excel本質上屬於二進制文件,很難去比對每次修改的差異,所以不支持“

女朋友:”那聽你這樣說,在我的場景里這個「版本控制軟件」沒啥用啊,它不能記錄像Word、Excel這種文件每次版本的差異,要想用它做備份,還不如現有的雲產品。“

三歪:”嗯,是的。其實現在雲產品也能提供版本控制的功能了,你用它們就足夠了。還有一點很重要的是,它有學習成本,可不是每個人都會用的。“

女朋友:”聽你說了這麼多,好像雲產品就很行啊,為啥你們還要「偏執」去用你說的那東西?“

三歪:“主要是我們寫代碼時遇到的問題會更多,我們用的「版本控制軟件」會更加靈活,它支持的功能會更多。”

女朋友:“對了,你都說了這麼久了,你們用的那個軟件叫啥啊?”

三歪:“Git

三歪瞎扯

其實本來想着直接講一下在工作中常用到的Git命令,但發現不太好寫(琢磨了很久

看三歪文章的人可能很多都是大學生,對Git本身了解可能就不太清楚,直接上Git的命令可能看不太懂,所以就分開了兩篇。

下一篇講一下三歪在工作中使用Git的糗事以及工作中是怎麼用Git的。

涵蓋Java後端所有知識點的開源項目(已有8K+ star):

  • GitHub
  • Gitee訪問更快

我是三歪,一個想要變強的男人,感謝大家的點贊收藏和轉發,下期見。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

LeetCode 76,一題教會你面試算法時的思考套路

本文始發於個人公眾號:TechFlow,原創不易,求個關注

今天是LeetCode專題的第45篇文章,我們一起來看看LeetCode的76題,最小窗口子串Minimum Window Substring。

這題的官方難度是Hard,通過了也是34.2%,4202人點贊,299人反對。從通過率以及點贊比來看,這題的質量很高,稍稍有些偏難,所以小夥伴們請做好準備,這是一道有點挑戰的問題。

題意和樣例

我們一起來看下題意,這題的題意很短,給定兩個字符串S和T。要求設計一個複雜度為的算法,在S串當中找到一個子串,能夠包含T串當中的所有字符。要求返回合法且長度最小的窗口的內容。

注意:

  • 如果不存在這樣的窗口,返回“”。
  • 如果窗口存在,題目保證有且只有一個。

樣例:

Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"

分析

我們來分析一下這個問題,從題意當中大家應該都能感受到它的難度。因為上來題目當中就限定了我們使用的算法的複雜度必須是,然而我們遍歷字符串的複雜度就已經是了,也就是說我們不能引入額外的計算開銷,否則一定不滿足題目的要求。

可能有些同學會想到傳說中在時間內判斷字符串匹配的KMP算法,如果你不知道這個算法也沒有關係,因為這個算法並不適用。因為我們要找的不是完全相等的子串的位置,而是找的是字符構成一樣的子串,所以並不能通過引入字符串匹配算法來解決。沒有學過KMP算法的同學可以松一口氣了,這題當中並不會引入新的算法。

解題的套路

一般來說當我們面臨一個算法問題的時候,我們常常的思考過程主要有兩種。一種是適配,說白了就是把可能可以用上的算法往問題上套。根據題意先感覺一下,大概會用到什麼樣的算法,然後詳細地推導適配的過程,看看是不是真的適用或者是有什麼坑,或者是會出現什麼新的問題。如果一切OK,能夠推理得通,那麼這個算法就是解。第二種方法是建模,也就是說從題意入手,對題意進行深入的分析,對問題進行建模和抽象,找到問題的核心,從而推導出用什麼樣的算法可以解決。

舉個很簡單的例子,一般來說我們的動態規劃算法都是適配。都是我們先感覺或者是猜測出可以使用動態規劃,然後再去找狀態和轉移,最後建立狀態轉移方程。而一些搜索問題一般是建模,我們先對問題進行分析,然後找出需要搜索的解的存在空間,然後設計算法去搜索和剪枝,最後找到答案。

據說一些頂級高手這兩種方法是一起使用的,所以才可以那麼快速地找到解。當然我不是頂級高手,所以這個也只是我的猜測。這個思考過程非常有用,特別是當我們面試的時候,遇到一個從未見過的問題,如果你什麼套路也沒有,頭腦一片空白或者是苦思冥想不得要領是很常見的事情。當你有了套路之後,你就可以試着慢慢找到答案了。

回到這道題本身,我們剛才已經試過了,拿字符串匹配的算法網上套是不行的。在視野里似乎也沒有其他的算法可以套用,所以我們換一種思路,試試看建模。

首先我們可以肯定一點,我們需要在遍歷的時候找到答案,這樣才可以保證算法的複雜度是。我們的目標是尋找子串,也就是說我們遍歷的過程應該對應一個子串,並且我們有方法可以快速判斷這個子串是否合法。這樣我們才可以做到遍歷的同時判斷答案的可行性。進而可以想到這是一個區間維護的問題,區間維護我們經常使用的方法就是two pointers。所以我們可以試試two pointers能否適用。

實際上這道題的正解就是two pointers。

題解

我們維護了一個區間,我們需要判斷區間里的字符構成,這個很容易想到可以使用dict,維護每一個字符出現的次數。在這個題目當中,我們只需要考慮覆蓋的情況,也就是說字符多了並不會構成非法。所以我們可以維護一個dict,每次讀入一個字符更新它,當dict當中的字符滿足要求的時候,為了使得區間長度盡量短,我們可以試着移動區間的左側,盡量縮短區間的長度。

從區間維護的角度來說,我們每次移動區間右側一個單位,只有當區間內已經滿足題意的時候才會移動左側。通過移動左側彈出元素來獲取能夠滿足題意的最佳區間。

我們來看下主要的流程代碼:

# 存儲區間內的字符
segement = {}
for i in range(n):
    segement[s[i]] += 1
    # 當滿足條件的時候移動區間左側
    while l <= i and satisified(segment):
        # 更新最佳答案
        if i - l + 1 < ans_len:
            ans_len = i - l + 1
            beg, end = l, i + 1
        # 彈出元素
  segement[s[l]] -= 1
        l += 1

到這裏還有一個小問題,就是怎麼樣判斷這個segment是否合法呢?我們可以用一個数字matched來記錄目前已經匹配上的字符的數量。當某個字符在segment當中出現的次數和T中的次數相等的時候,matched加一。當matched的數量和T中字符種類的數量相等的時候,就可以認為已經合法了。

我們把所有的邏輯串起來,就可以通過這題了。

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        from collections import Counter, defaultdict
        # 通過Counter直接獲取T當中的字符構成
        counter = Counter(t)
        n, m = len(s), len(counter)
        l, beg, end = 0, 0, 0
        cur = defaultdict(int)
        matched = 0
        flag = False
        # 記錄合法的字符串的長度
        ans_len = 0x3f3f3f3f
        
        for i in range(n):
            if s[i] not in counter:
                continue
                
            cur[s[i]] += 1
            # 當數量匹配上的時候,matched+1
            if cur[s[i]] == counter[s[i]]:
                matched += 1
                
            # 如果已經找到了合法的區間,嘗試縮短區間的長度
            while l <= i and matched == m:
                if i - l + 1 < ans_len:
                    flag = True
                    beg, end = l, i+1
                    ans_len = i - l + 1
                    
                # 彈出左側元素
                c = s[l]
                if c in counter:
                    cur[c] -= 1
                    if cur[c] < counter[c]:
                        matched -= 1
                        
                l += 1

        
        return "" if not flag else s[beg: end]

總結

到這裏,這道題就算是解決了。很多同學可能會覺得疑惑,為什麼我們用到了兩重循環,但是它依然還是的算法呢?

這個是two pointers算法的常見問題,也是老生常談的話題了。我們在分析複雜度的時候,不能只簡單地看用到了幾層循環,而是要抓住計算的核心。比如在這個問題當中,我們內部的while循環針對的變量是l,l這個變量對於i整體是遞增的。也就是說無論外面這個循環執行多少次,裏面的這個while循環一共最多累加只能執行n次。那麼,當然這是一個的算法。

這題總體來說有些難度,特別是一開始的時候可能會覺得沒有頭緒無從下手。這個時候有一個清晰的頭腦以及靠譜的思考鏈非常重要,希望大家都能學到這個其中思維的過程,這樣以後才可以應付更多的算法問題。

如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。

本文使用 mdnice 排版

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

真慘!連各大編程語言都擺起地攤了!

困難年年有,今年特別多。

公司要做一個新的網站,可預算有限,聽說為了生計,各大編程語言們都擺起了地攤兒,我決定去瞧瞧,看看能不能淘點做網站需要的東西。

選擇靜態web服務器

一進集市,這煙火氣就撲面而來,平時一個個端着架子的C++、Java、Python居然能放下身段,招呼叫賣,我還是頭一回見。

“老哥,需要來點什麼?”,C語言給我打起了招呼。

“我想要建個網站”,我回答到。

“那你可算來對地方了”,C語言攤主起身說到,“建網站總得需要一個Web服務器吧,你看這裏,apacheweb服務器,賣的可好了”

我搖了搖頭,“這個apache,之前有用過,是用的多進程模型,連接多了有些吃力啊?”

“老哥是行家啊,來看這一款我們最新推出的nginx服務器,採用epoll多路復用+事件驅動,性能強勁!上萬連接不在話下”,C語言攤主自豪的說到。

隨後攤主給我展示了這個nginx服務器的能力,果然不錯,我加入了購物車,繼續往前逛。

挑選web應用開發框架

沒走幾步來到 C# 的攤前。

“喲,老哥,你這是要做網站啊?”,C#攤主主動給我打起了招呼。

“你怎麼知道的?”,我好奇的問到。

“你這購物車裡不是裝了一個nginx嘛!既然做網站,可得試試我們家的.NET Framework哦,各種裝備,應有盡有。”,C#熱情的拉着我過去。

不過我還是拒絕了他:“實在不好意思,聽說你們家產品只能在Windows系統上面運行,不支持Linux,還是算了,我再看看別家”

C#攤主不肯放棄,“別呀,我們已經支持Linux了,您再看看,現在搞活動,免費送IIS服務器哦,你把那nginx退了吧,喂,再考慮一下啊·····”

不等他說完,我就溜走了,來到了Python的攤前。

Python攤主也看出了我要做網站,也推銷起他家的產品來。

“大哥,你做網站,肯定不想只做一個靜態的吧,來試試咱們家的Web框架做一個動態網站?咱Python家的產品,簡單、輕量又實惠。”,攤主熱情的說到。

“有哪些推薦的呢?”,我問到。

Python攤主指着攤位上的幾個產品說道:“有DjangoFlaskTornado這三款是現在主打拳頭產品,用了的都說好”

我正想蹲下仔細看看,背後傳來一個聲音:“這位大哥,擱這選Web開發框架吶?快來我這邊看看”

一邊說,一邊硬把我往後面拽。

來到他的攤位上,我一看原來是PHP攤主。

“咱PHP產品琳琅滿目,就是專門為做網站而生的,現在做活動,跳樓價只要9.9,錯過不再有!”

這PHP攤主好生能說,一頓猛誇把我說的暈頭轉向,不知怎的竟然就加入了購物車。

繼續向前,來到了Java的攤位,一個好大的攤位,擺放的東西也是看的人眼花繚亂。

“你這個攤位不錯啊,又寬敞人流又多”

“可不是咋的,剛為了搶這個攤位,跟PHP那傢伙還幹了一架呢。”,Java攤主笑着說到。

看到我購物車裡的東西,Java攤主也開始推銷起來:“大哥,這年頭怎麼還用PHP那傢伙的東西,趕緊去退了吧,咱Java攤里的東西都是大品牌,質量有保障!”

“這,不太好吧,這PHP也是大品牌啊”

Java攤主搖了搖頭,“他一個腳本語言怎麼跟我們比啊?大哥你看,我們有Spring、SpringMVC、SpringBoot、SpringCloud等等明星產品,用戶眾多,售後工作也到位。而且現在搞活動可以送tomcat服務器,你要是用戶量不多都可以把nginx退掉,省一筆錢。”

“看起來很厲害的樣子呢,我考慮一下”,我打算再去別的地方看看比較一下。

Java攤主一把拉住了我,“大哥,不說了,咱今天碰到是緣分,你做網站有很多服務是吧,得用到RPC吧,你今天下單,我再送你一套netty框架,又能幫你省一筆了”

Java攤主盛情難卻,我一時興起,買下了好幾個,購物車都裝滿了一大半了。

挑選數據庫

剛付完錢準備離開,背後又傳來一個聲音:“大哥,做網站你得用數據庫吧,快來這看看”

我尋聲望去,原來是 C++ 攤主在叫我。

“來看看我的MySQL數據庫,做網站必備!”

我看了一下產品說明書,感覺還不錯,看了下錢包,剛才在Java攤主那裡花費不少,有些囊中羞澀了,問到:“能不能優惠一點”

C++攤主一聽,臉上的笑容少了一半,“如果你選個MongoDB組個套餐,可以給你8折優惠”

“MongoDB?我要這個幹嘛”

攤主一聽來了勁頭,開始滔滔不絕:“有些數據啊他不適合存在數據庫里,比如文檔啊,JSON啊,這些東西你要用數據庫存儲,增加字段和查詢,可麻煩了,你用MongoDB就方便都多了······”

被他說了一通,感覺是得要個這個玩意兒。

攤主見我有些心動,又繼續推銷:“大哥看來真是行家,您做網站是不是有圖片音頻視頻需要存儲,我這裏還有一個對象存儲(OSS)系統CEPH,你看看要不要也一併帶上,我還是給您八折,怎麼樣?”

“實在不好意思,我這預算有些吃緊了,這個就算了吧”,我婉拒到。

“哎哎大哥您往這瞧,咱家也有對象存儲minio,現在市場推廣期,免費送了!”,旁邊的Golang攤主招呼了起來。

居然有免費這好事,我倒是想去看看。

C++攤主見狀小聲說到:“免費的你敢用,出了問題都找不到人,還是看看我的吧,直接給你六折,怎麼樣?”

我一想也是,正想下單買下,背後傳來一聲“且慢”!

我回頭一看,原來是剛才的Java攤主,“大哥,咱Java家的ElasticSearch也考慮一下唄。”

我回到Java攤主這邊,問到:“這又是個什麼?我需要用到嗎?”

Java攤主也開始給我掰扯起來:“咱家的ElasticSearch那可是搜索行家,你網站內容多了是不是需要個搜索功能啊,咱家的這個ES,全文搜索不在話下,秒級響應,做網站必備啊。看你是回頭客,給你九折!”

我正想做一個搜索功能,看來這個也是必不可少,也一起拿下了。

緩存服務器

我推着購物車準備回家了,今天真是滿載而歸。

來到集市出口,又碰到了一開始的C語言攤主,攤主一瞧揮着手喊道:“大哥,你還差個內存緩存系統,過來看看,Redis搞活動呢!哎,別走啊,Memcached虧本處理了,過來看看啊”

我一摸錢包,完蛋,嚴重超支了!我加快了步伐,匆忙離開······

彩蛋

看着我採購回來的一堆東西,老闆是氣不打一處來。

“咱們就做一個內網論壇,全公司不過100號人,你給我搞這麼多,幾個意思?”

“老闆,您聽我解釋···”

“解釋個啥,明天不用來了”

哦豁,丟了飯碗,我也去擺地攤了···

往期熱門回顧

因為一個跨域請求,我差點丟了飯碗

一個神秘URL釀大禍,差點讓我背鍋!

就為了一個原子操作,其他CPU核心都罷工了

完了!CPU一味求快出事兒了!

可怕!CPU竟成了黑客的幫凶!

哈希表哪家強?幾大編程語言吵起來了!

震撼!全網第一張源碼分析全景圖揭秘Nginx

一網打盡!每個程序猿都該了解的黑客技術大匯總

DDoS攻擊:無限戰爭

一個Java對象的回憶錄:垃圾回收

誰動了你的HTTPS流量?

路由器里的廣告秘密

一個HTTP數據包的奇幻之旅

我是一個流氓軟件線程

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

網頁設計最專業,超強功能平台可客製化