1. 程式人生 > 其它 >解決 Github 打不開或開啟很慢的問題

解決 Github 打不開或開啟很慢的問題

2.模板方法模式

1.基本概念:

定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

1、在造房子的時候,地基、走線、水管都一樣,只有在建築的後期才有加壁櫥加柵欄等差異。

2、西遊記裡面菩薩定好的 81 難,這就是一個頂層的邏輯骨架。

鉤子方法

提供預設行為:

在模板方法模式的父類中,我們可以定義一個方法,它預設不做任何事,子類可以視情況要不要覆蓋它,該方法稱為“鉤子”

優點:

1、封裝不變部分,擴充套件可變部分。

2、提取公共程式碼,便於維護。

3、行為由父類控制,子類實現。

缺點:

每一個不同的實現都需要一個子類來實現,導致類的個數增加,使得系統更加龐大。

繼承關係自身缺點,如果父類新增新的抽象方法,所有子類都要改一遍

注意事項:

為防止惡意操作,一般模板方法都加上 final 關鍵詞。鎖定模板方法

ConfigurableWebApplicationContext  wac
wac.refresh();


ConfigurableApplicationContext  介面  定義了refresh()
ConfigurableWebApplicationContext類 

2.錨定原始碼:

spring refresh()

比如spring的refresh方法,不同的容器呼叫會有不同的實現,但configureAndRefreshWebApplicationContext這個方法的執行流程是不變的,refresh只是其中一個固定的環節

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
   if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
      if (idParam != null) {
         wac.setId(idParam);
      }
      else {
         // Generate default id...
         wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
               ObjectUtils.getDisplayString(sc.getContextPath()));
      }
   }

   wac.setServletContext(sc);
   String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
   if (configLocationParam != null) {
      wac.setConfigLocation(configLocationParam);
   }

   // The wac environment's #initPropertySources will be called in any case when the context
   // is refreshed; do it eagerly here to ensure servlet property sources are in place for
   // use in any post-processing or initialization that occurs below prior to #refresh
   ConfigurableEnvironment env = wac.getEnvironment();
   if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
   }

   customizeContext(sc, wac);
   wac.refresh();
}

3.實戰

舉個貼近生活的例子吧,就以我吃的午餐為介面,設計使用模板方法設計午餐類

午餐類

package DesignPattern.templatemethod;

/**
 * 午餐類
 */
public abstract class Lunch {
    //固定流程吃午飯,1米飯+1葷+1素+(湯預設不需要)
    protected final void eatLunch() {
        eatStapleFood();
        eatVegetable();
        eatMeat();
        if (needSoup()) {
            this.Soup();
        }
    }


    //吃主食  米飯是固定的,不需要改變
    final void eatStapleFood() {
        System.out.println("每天吃米飯");
    }

    //吃蔬菜  每天吃什麼蔬菜是變化的
    abstract void eatVegetable();

    //吃肉   每天吃什麼葷菜是變化的
    abstract void eatMeat();

    //鉤子方法  是否需要湯  預設不需要   每天不一定會喝湯
    protected boolean needSoup() {
        return false;
    }

    //是否需要湯 預設不需要
    final void Soup() {
        System.out.println("今天喝湯");
    }
}

週一午餐類

package DesignPattern.templatemethod;

//週一午餐
public class MonLunch extends Lunch{
    @Override
    void eatVegetable() {
        System.out.println("蔬菜吃大白菜");
    }

    @Override
    void eatMeat() {
        System.out.println("葷菜吃紅燒蝦");
    }
}

週二午餐

package DesignPattern.templatemethod;

public class TueLunch extends Lunch{
    @Override
    void eatVegetable() {
        System.out.println("蔬菜吃秋葵");
    }

    @Override
    void eatMeat() {
        System.out.println("葷菜吃牛肉");
    }

    //週二想喝湯了
    @Override
    protected boolean needSoup() {
        return true;
    }
}

測試類

package DesignPattern.templatemethod;

public class Test {
    public static void main(String[] args) {
        System.out.println("————週一午餐————");
        Lunch mondayLunch = new MonLunch();
        mondayLunch.eatLunch();
        System.out.println("————週二午餐————");
        Lunch tuesday = new TueLunch();
        tuesday.eatLunch();
    }
}

控制檯輸出:

4.實戰改進

這裡的鉤子方式的實現方式是在週二午餐類中寫死為需要,就是每個週二都必須喝湯,但如果我不想要喝湯怎麼辦呢?

可以使用構造方法來改進,通過傳入true or false 來控制是否需要喝湯

改進後的週二午餐類如下

package DesignPattern.templatemethod;

public class TueLunch extends Lunch {
    //是否需要喝湯標誌位  預設不需要
    private boolean needSoupFlag = false;

    public TueLunch(boolean needSoupFlag) {
        this.needSoupFlag = needSoupFlag;
    }

    @Override
    void eatVegetable() {
        System.out.println("蔬菜吃秋葵");
    }

    @Override
    void eatMeat() {
        System.out.println("葷菜吃牛肉");
    }

    //週二想喝湯了
    @Override
    protected boolean needSoup() {
        return this.needSoupFlag;
    }
}

test類

package DesignPattern.templatemethod;

public class Test {
    public static void main(String[] args) {
        System.out.println("————週一午餐————");
        Lunch mondayLunch = new MonLunch();
        mondayLunch.eatLunch();
        System.out.println("————週二午餐————");
        Lunch tuesday = new TueLunch(false);
        tuesday.eatLunch();
    }
}

控制檯輸出

不破不立,怕啥懟啥!