設計模式系列之組合模式(Composite Pattern)——樹形結構的處理

說明:設計模式系列文章是讀劉偉所著《設計模式的藝術之道(軟件開發人員內功修鍊之道)》一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的博客https://blog.csdn.net/LoveLion/article/details/17517213

模式概述

樹形結構在軟件中隨處可見,例如操作系統中的目錄結構、應用軟件中的菜單、辦公系統中的公司組織結構等等,如何運用面向對象的方式來處理這種樹形結構是組合模式需要解決的問題。組合模式通過一種巧妙的設計方案使得用戶可以一致性地處理整個樹形結構或者樹形結構的一部分,也可以一致性地處理樹形結構中的恭弘=叶 恭弘子節點(不包含子節點的節點)和容器節點(包含子節點的節點)。

模式定義

組合模式(Composite Pattern):組合多個對象形成樹形結構以表示具有“整體—部分”關係的層次結構。組合模式對單個對象(即恭弘=叶 恭弘子對象)和組合對象(即容器對象)的使用具有一致性,組合模式又可以稱為“整體—部分”(Part-Whole)模式,它是一種對象結構型模式。

模式結構圖

組合模式結構圖如下所示:

在組合模式結構圖中包含如下幾個角色:

  • Component(抽象構件):它可以是接口或抽象類,為恭弘=叶 恭弘子構件和容器構件對象聲明接口,在該角色中可以包含所有子類共有行為的聲明和實現。在抽象構件中定義了訪問及管理它的子構件的方法,如增加子構件、刪除子構件、獲取子構件等。

  • Leaf(恭弘=叶 恭弘子構件):它在組合結構中表示恭弘=叶 恭弘子節點對象,恭弘=叶 恭弘子節點沒有子節點,它實現了在抽象構件中定義的行為。對於那些訪問及管理子構件的方法,可以通過異常等方式進行處理。

  • Composite(容器構件):它在組合結構中表示容器節點對象,容器節點包含子節點,其子節點可以是恭弘=叶 恭弘子節點,也可以是容器節點,它提供一個集合用於存儲子節點,實現了在抽象構件中定義的行為,包括那些訪問及管理子構件的方法,在其業務方法中可以遞歸調用其子節點的業務方法。

組合模式的關鍵是定義了一個抽象構件類,它既可以代表恭弘=叶 恭弘子,又可以代表容器,而客戶端針對該抽象構件類進行編程,無須知道它到底表示的是恭弘=叶 恭弘子還是容器,可以對其進行統一處理。同時容器對象與抽象構件類之間還建立一個聚合關聯關係,在容器對象中既可以包含恭弘=叶 恭弘子,也可以包含容器,以此實現遞歸組合,形成一個樹形結構。

模式偽代碼

對於客戶端而言,一般針對抽象構件編程,而無須關心其具體子類是容器構件還是恭弘=叶 恭弘子構件。抽象構建類典型代碼如下:

public abstract class Component {
    public abstract void add(Component c); //增加成員

    public abstract void remove(Component c); //刪除成員

    public abstract Component getChild(int i); //獲取成員

    public abstract void operation();  //業務方法
}

如果繼承抽象構件的是恭弘=叶 恭弘子構件,則其典型代碼如下所示:

public class Leaf extends Component {
    @Override
    public void add(Component c) {
        //異常處理或錯誤提示 
    }

    @Override
    public void remove(Component c) {
        //異常處理或錯誤提示 
    }

    @Override
    public Component getChild(int i) {
        //異常處理或錯誤提示 
        return null;
    }

    @Override
    public void operation() {
        //恭弘=叶 恭弘子構件具體業務方法的實現
    }
}

如果繼承抽象構件的是容器構件,則其典型代碼如下所示:

public class Composite extends Component {

    private List<Component> list = new ArrayList<>();

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public Component getChild(int i) {
        return (Component) list.get(i);
    }

    @Override
    public void operation() {
        //容器構件具體業務方法的實現
        //遞歸調用成員構件的業務方法
        for (Object obj : list) {
            ((Component) obj).operation();
        }
    }
}

客戶端對抽象構件類進行編程

public class Client {
    public static void main(String[] args) {
        Component component;
        component = new Leaf();
        //component = new Composite();

        // 無須知道到底是恭弘=叶 恭弘子還是容器
        // 可以對其進行統一處理
        component.operation();
    }
}

模式簡化

透明組合模式

透明組合模式中,抽象構件Component中聲明了所有用於管理成員對象的方法,包括add()、remove()以及getChild()等方法,這樣做的好處是確保所有的構件類都有相同的接口。在客戶端看來,恭弘=叶 恭弘子對象與容器對象所提供的方法是一致的,客戶端可以相同地對待所有的對象。透明組合模式也是組合模式的標準形式。

透明組合模式的完整結構圖如下:

也可以將恭弘=叶 恭弘子構件的add()remove()等方法的實現代碼移至Component中,由Component提供統一的默認實現,這樣子類就不必強制去實現管理子Component。代碼如下所示:

public abstract class Component {
    public void add(Component c) {
        throw new RuntimeException("不支持的操作");
    }

    public void remove(Component c) {
        throw new RuntimeException("不支持的操作");
    }

    public Component getChild(int i) {
        throw new RuntimeException("不支持的操作");
    }

    public abstract void operation();  //業務方法
}

透明組合模式的缺點是不夠安全,因為恭弘=叶 恭弘子對象和容器對象在本質上是有區別的。恭弘=叶 恭弘子對象不可能有下一個層次的對象,即不可能包含成員對象,因此為其提供add()、remove()以及getChild()等方法是沒有意義的,這在編譯階段不會出錯,但在運行階段如果調用這些方法可能會出錯(如果沒有提供相應的錯誤處理代碼)。

安全組合模式

安全組合模式中,在抽象構件Component中沒有聲明任何用於管理成員對象的方法,而是在Composite類中聲明並實現這些方法。

安全組合模式的完整結構圖如下:

此時Component就應該這樣定義了

public abstract class Component {
    // 業務方法
    public abstract void operation();
}

安全組合模式的缺點是不夠透明,因為恭弘=叶 恭弘子構件和容器構件具有不同的方法,且容器構件中那些用於管理成員對象的方法沒有在抽象構件類中定義,因此客戶端不能完全針對抽象編程,必須有區別地對待恭弘=叶 恭弘子構件和容器構件。在實際應用中,安全組合模式的使用頻率也非常高,在Java AWT中使用的組合模式就是安全組合模式。

模式應用

模式在JDK中的應用

Java SE中的AWTSwing包的設計就基於組合模式,在這些界麵包中為用戶提供了大量的容器構件(如Container)和成員構件(如CheckboxButtonTextComponent等),其結構如下圖所示

Component類是抽象構件,CheckboxButtonTextComponent是恭弘=叶 恭弘子構件,而Container是容器構件,在AWT中包含的恭弘=叶 恭弘子構件還有很多。在一個容器構件中可以包含恭弘=叶 恭弘子構件,也可以繼續包含容器構件,這些恭弘=叶 恭弘子構件和容器構件一起組成了複雜的GUI界面。除此以外,在XML解析組織結構樹處理文件系統設計等領域,組合模式都得到了廣泛應用。

模式在開源項目中的應用

Springorg.springframework.web.method.support.HandlerMethodArgumentResolver使用了安全組合模式。提取關鍵代碼如下:

public interface HandlerMethodArgumentResolver {
    
    boolean supportsParameter(MethodParameter parameter);

    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                           NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

再看下它的一個實現類org.springframework.web.method.support.HandlerMethodArgumentResolverComposite

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {


    private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();

    /**
     * Add the given {@link HandlerMethodArgumentResolver}.
     */
    public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver resolver) {
        this.argumentResolvers.add(resolver);
        return this;
    }

    /**
     * Add the given {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.
     */
    public HandlerMethodArgumentResolverComposite addResolvers(
            @Nullable HandlerMethodArgumentResolver... resolvers) {

        if (resolvers != null) {
            Collections.addAll(this.argumentResolvers, resolvers);
        }
        return this;
    }

    /**
     * Clear the list of configured resolvers.
     */
    public void clear() {
        this.argumentResolvers.clear();
    }


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return getArgumentResolver(parameter) != null;
    }


    @Override
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

        HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
        if (resolver == null) {
            throw new IllegalArgumentException("Unsupported parameter type [" +
                    parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
        }
        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    }
}

模式總結

主要優點

  1. 組合模式可以清楚地定義分層次的複雜對象,表示對象的全部或部分層次,它讓客戶端忽略了層次的差異,方便對整個層次結構進行控制。

  2. 客戶端可以一致地使用一個組合結構或其中單個對象,不必關心處理的是單個對象還是整個組合結構,簡化了客戶端代碼。

  3. 組合模式為樹形結構的面向對象實現提供了一種靈活的解決方案,通過恭弘=叶 恭弘子對象和容器對象的遞歸組合,可以形成複雜的樹形結構,但對樹形結構的控制卻非常簡單。

適用場景

(1) 在具有整體和部分的層次結構中,希望通過一種方式忽略整體與部分的差異,客戶端可以一致地對待它們。

(2) 在一個使用面向對象語言開發的系統中需要處理一個樹形結構。

(3) 在一個系統中能夠分離出恭弘=叶 恭弘子對象和容器對象,而且它們的類型不固定,需要增加一些新的類型。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

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

電動車鋰電池進展緩,新普宣布現金減資4成

新普宣布將現金減資4成、即退還股東每股4元現金,加上董事會決議擬配發現金股息6元,合計配發每股現金10元。新普近幾年來自筆記型電腦的成長趨緩,而電動車所需鋰電池進展緩慢,手機與平板使用單顆電池芯鋰電池模組毛利率相對較低、且有大陸同業與之競爭,外界認為這些是新普會大幅現金減資的主因。同時,新普大股東鴻海集團宣布要投資陸廠中國寧德時代新能源股權1.19%,外界也對新普未來在集團內電動車電池領域的所扮演的角色,先抱持觀察態度。

鴻海在29日公告,旗下子公司富泰華以人民幣逾10億元取得寧德時代新能源科技(CATL)股權約766.65萬股,持股比例約1.19%。外界解讀,鴻海以超過10億人民幣入股大陸動力電池大廠寧德時代,意在布局電動車電池市場。

寧德時代母公司是總部位於香港的鋰電池製造商新能源科技(ATL) ;ATL因原股東想撤資並在2005年被大股東之一的日商TDK全資收購。ATL集團旗下有東莞、東莞白馬、東莞松山湖、北京、青海西寧等不同產品線的生產基地,總部在福建的寧德時代(CATL)在集團內則主攻動力與儲能業務為主。全球動力電池市場中,松下透過特斯拉合作保持第一,比亞迪(BYD)次之,而寧德時代已超越LG化學位居全球第三。

(一)新普Q1財測,每股獲利1.71~1.89元:

新普昨日天舉行法人說明會,2016年合併營收年減9.5%至581.2億元,合併毛利率10%,稅前盈餘年減16.8%至38.96億元;稅後盈餘年減12.7%至28.02億元,EPS為9.09元。主要是大陸鋰電池同業在消費電子市場的競爭。

新普同時也發布2017年第1季財測,第1季合併營收約113~117億元,營業毛利約9.64~9.98億元,營業淨利4.6~4.73億元,稅前盈餘約7.31~8.1億元,稅後盈餘5.27~5.83億元,單季EPS約1.71~1.89元。

新普董事會決議現金減資40%,退還股東每股現金4元,並配發現金股息每股6元,股東參與現金減資及除息,每股可以拿回現金10元。

新普宣布減資40%,減資後現金水位仍達100億元以上;減資將能提升ROE(股東權益報酬率)與每股盈餘水準。法人以減資後流通股份18.5億元計算,預估新普2017年每股盈餘可望上揚至13元以上。

(二)新普Q1毛利率受到台幣升值影響,後續毛利率視電池芯漲價影響:

新普估第1季營收季減30~32%、年減幅度則為12~15%,外界預期應是iPhone等消費電子客戶的鋰電池供應比重將降低。

同時,新台幣第一季升值已接近7%,新普預期第1季毛利率8.3~8.5%,低於外界守穩在10%的原本預期。

至於第2季毛利率走向,因近期電池芯價格上揚,可能會對上半年毛利率有些影響。在營收方面,受惠於新款平板與平板型電腦將上市,新普第2季營收可望較首季營收季增5~10%。

(三)鴻海集團布局動力與儲能電池,新普定位尚待觀察:

鴻海集團已布局中國大陸電動車領域,例如兩年前與和諧汽車及騰訊,簽訂「互聯網+智能電動車」的戰略合作意向書,昨日也宣布透過子公司投資大陸鋰電池廠寧德時代(CATL)的1.19%的股權。

寧德時代在大陸汽車應用領域積極,2016年12月份與東風汽車簽訂戰略合作協定,2017年年初宣布投資3,000萬歐元參股芬蘭維美德汽車、並取得其22%股權,進軍歐洲汽車市場,而今年3月又與國能電動汽車瑞典公司(NEVS)簽署合作意向書,雙方將展開技術交流與研發的深入合作。

鴻海集團的鴻揚創投也是新普的大股東,鴻海集團持股新普股份4.44%。以過去業務與市場情況來看,新普與寧德時代算是競爭同業。

鴻海未來是否會去尋求新普、與新投資的寧德時代雙方合作的機會,還待觀察。

法人認為,新普今年現金減資提高每股獲利水準,下游手機與平板客戶銷售情況,以及電池芯漲價效應對於新普本業營收與毛利率影響較大。而鴻海集團布局大陸鋰電池業者的消息,對新普而言,先以中性看待。

(本文內容由授權使用。圖為電動車電池,圖片出處:Wikipedia)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

Tesla市值超越Ford,成全美第二大製造商

電動車究竟行不行得通?讓特斯拉(Tesla)來告訴你答案。3 日上午,隨著特斯拉的股價飆升,特斯拉的市值正式超越了百年汽車大廠福特(Ford),成為美國第二大汽車製造商。

電動車將成主流?

華爾街日報報導,特斯拉近日公布2017 年第一季銷售數據,受到Model S、Model X 車款交貨量大增帶動,全球銷售量較去年同期大增69%,創下單季銷售量歷史新高,消息激勵股價3 日大漲7.3% 至298.52 美元,特斯拉的市值也來到487 億美元(約1.48 兆元台幣),超過福特的455 億美元(約1.38 兆元台幣)。

隨著車款交貨量提升,特斯拉將有望順利達成2017 上半年的5 萬台銷售目標。儘管整體銷售量仍無法與其他大廠做比較,但有越來越多的投資人相信,在經過數年可觀的成長後,美國汽車的銷售市場已經開始出現衰退,電動車將逐漸成為主流。

這項在1980 年代時日本車廠企圖研發的技術,如今卻可能由矽谷的公司來讓其發揚光大。

特斯拉的專長?

或許是嗅到未來的商機,不僅僅是特斯拉,許多汽車大廠也開始關注電動車及自駕車領域。通用也在日前就推出平價電動車Chevrolet Bolt,想與特斯拉一較高下,然而3 月僅銷售3,000 輛,與特斯拉Model 3的預購盛況相去勝遠。

福特即將上任的執行長費爾茲(Mark Fields)也承諾將在2021 年前推出自駕車,但百年企業轉型談何容易,目前看來仍舊困難重重。

基金公司ARK Invest 的分析師Tasha Keeney 認為,其他汽車大廠若想投入電動車和自駕車領域發展,目前得需付出比特斯拉雙倍的努力才有望達成。

福特的市值和2010 年底時大致相同,但當時新上市的特斯拉市值仍低於20 億美元(約608 億元台幣)。目前全美最大的汽車製造商是通用(General),市值為521 億美元(約1.58 兆元台幣)。

如今看來,特斯拉隨時有機會超越通用,奪下全美市值第一汽車製造商的寶座。

市值被高估?

由於看好特斯拉對自駕車共乘服務的未來發展,摩根史丹利的分析師Adam Jonas 將特斯拉的目標價訂為每股305 美元,部分投資人認為,相較起其他汽車大廠和科技龍頭,特斯拉更有望能將自駕技術真正帶進道路。

然而並非所有人都對特斯拉有信心,儘管已經成立13 年,特斯拉仍有著沉重的負債、未能穩定獲利,自駕車也還在測試階段。底特律車商和汽車研究中心主席David Cole 就認為,特斯拉的市值攀升是靠著炒作和承諾為基礎的。

對於外界的關注,馬斯克3日發推特表示,如果以特斯拉的歷史來看,確實會讓人覺得公司市值過高,但特斯拉現在的股價是反映風險調整後的未來現金流。福特則發聲明指出,營運並不會受股價波動影響,重心一直都放在透過經營來提升價值。

(合作媒體:。圖片出處:Public Domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

股價飆升有理,大摩指Tesla潛在市場大

 

美國電動車廠特斯拉(Tesla),股價一度飆破300美元,並超越福特汽車,躍居美國第二大車廠。到底特斯拉值不值得此一高價?特斯拉多頭出面力挺,指出特斯拉不只是電動車業者,也是運輸和基礎建設公司,潛在市場極大,300美元合情合理。

MarketWatch、巴倫(Barron’s)報導,4日特斯拉股價首次突破300美元大關,漲勢之快讓大多頭也吃驚。摩根士丹利(大摩)分析師Adam Jonas等人報告稱,他們訝異於特斯拉近來漲勢,在短短時間內就站上300美元,認為技術因素戰勝基本面。

儘管如此,大摩認為,特斯拉並非配不上此一價碼。報告稱,他們和投資人交談後發現,大家比預期更快了解特斯拉的潛在市場。大摩說,特斯拉潛在市場包括10兆美元的輕型車移動市場、1兆美元的物流市場、2~3兆美元的能源市場。另外,消費者待在車上時間高達6,000億小時,特斯拉能從數兆美元的影音內容傳輸等服務獲利。

大摩指出,上次特斯拉飆高時,是在2014年9月,當時少有投資人以此種角度看待特斯拉,多認為大摩報告衝太快,那個時候特斯拉被視為純電動車廠,有機會觸及電池/能源儲存系統。但是這2.5年來情況已大幅轉變。特斯拉佔據三大重要趨勢的中心位置:電動車、自駕系統、車輛共享。

大摩說,特斯拉的「Tesla Mobility」將在2018年問世,此一隨選服務提供自動化運輸功能,預期特斯拉將在共享移動(shared mobility)革命中,扮演領導角色。

需要強調的是,Benzinga報導,Jonas向來看來極為看好特斯拉,2015年年中曾預測特斯股價將站上465美元,被外界稱為「特斯拉啦啦隊」。

特斯拉5日股價拉回,下跌2.86%收在295美元。

特斯拉第1季交車量意外跳高,帶動股價一飛衝天,如今已超越福特(Ford Motor Co.),成為全美市值第二大的汽車製造商。

特斯拉4日終場勁揚1.74%、收303.70美元,創歷史收盤新高。MarketWatch報導,根據計算,特斯拉的市值已達495億美元,一口氣超車福特的444億美元。在汽車類股中,特斯拉的市值如今僅次於通用汽車(General Motors Co.)的513億美元。

特斯拉甫於週日(4月2日)宣布,第1季的Model S、Model X交貨量超過了25,000台,創單季歷史高,比去年同期大增了69%之多。這高於分析師原先預估的23,000~24,500台。特斯拉並預估,今(2017)年上半年的汽車交貨量有機會達到47,000~50,000台。

(本文內容由授權使用。圖片出處:Public Domain CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

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

電動車駛入韓國大邱Green Energy EXPO

汽車是韓國的重要產業之一,而電動車、油電混合車等新能源車款在大邱綠能展之中也佔有一席之地,現場有如小型車展。

三星集團的太陽能事業本次沒有參展,展示的是經典電動車款SM3 Z.E.。這款電動車配有智慧駕駛功能,是2016年韓國最受歡迎的電動車。

現代集團展出多輛新能源車系列IONIQ,系統包括純電動車、油電混合、插電式油電混合車等三類;現代的電動車也在展場中幾個攤位上展示。油電混合車款的每公升行駛里程數可來到22.4公里,扭力5,700rpm。插電式油電混合車在純電模式下的續航力達46公里,混合動力模式下的扭力是5,700rpm,10.6秒可從0加速到100km/hr。純電動車款每kWh的行駛距離達6.3公里,總續航里程依規格不同,最高可達206公里。

KIA Motors在現場展示了新的電動車款SOUL,古典的外型和馬卡龍色調的烤漆相當可愛,續航力則是180公里。

此外,三輪、二輪電動車也有展示。其中,三輪電動車是介於房車與機車之間的產品,只能乘坐兩人,但比機車有更大的空間和遮蔽效果,在現場獲得不少關注。

大邱綠能展的展場上也有數個攤位展示電動車充電設備,包括充電樁和壁掛式充電座,有各種大小規格。部分充電樁可直接感應智慧卡或信用卡付費充電,也有充電樁的面板結合了廣告看板功能。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

Quartz.Net系列(七):Trigger之SimpleScheduleBuilder詳解

所有方法圖

 

 SimpleScheduleBuilder方法

RepeatForever:指定觸發器將無限期重複。

WithRepeatCount:指定重複次數

var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s.WithIntervalInSeconds(1).RepeatForever()).Build();

 

            var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s.WithIntervalInSeconds(1)
                                                                         .WithRepeatCount(10)).Build();

 

注:底層實現是repeatCount+1,也就是總共執行repeatCount+1次

        /// <summary>
        /// Specify a the number of time the trigger will repeat - total number of
        /// firings will be this number + 1.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="repeatCount">the number of seconds at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatCount" />
        /// <seealso cref="RepeatForever" />
        public SimpleScheduleBuilder WithRepeatCount(int repeatCount)
        {
            this.repeatCount = repeatCount;
            return this;
        }

 

 

WithInterval:以毫秒為單位指定重複間隔,由於是TimeSpan也可以指定時分秒

WithIntervalInHours:以小時為單位指定重複間隔

WithIntervalInMinutes:以分鐘單位指定重複間隔

WithIntervalInSeconds:以秒為單位指定重複間隔

            var trigger = TriggerBuilder.Create().WithSimpleSchedule(s=>s .WithIntervalInSeconds(1)
                                                                          .WithInterval(TimeSpan.FromDays(1))
                                                                          .WithIntervalInMinutes(1)
                                                                          .WithIntervalInHours(1)
                                                                          .WithRepeatCount(5))
                                                 .Build();

注:底層都是通過WithInterval實現的

        /// <summary>
        /// Specify a repeat interval in milliseconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="timeSpan">the time span at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatInterval" />
        /// <seealso cref="WithRepeatCount(int)" />
        public SimpleScheduleBuilder WithInterval(TimeSpan timeSpan)
        {
            interval = timeSpan;
            return this;
        }

        /// <summary>
        /// Specify a repeat interval in seconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="seconds">the time span at which the trigger should repeat.</param>
        /// <returns>the updated SimpleScheduleBuilder</returns>
        /// <seealso cref="ISimpleTrigger.RepeatInterval" />
        /// <seealso cref="WithRepeatCount(int)" />
        public SimpleScheduleBuilder WithIntervalInSeconds(int seconds)
        {
            return WithInterval(TimeSpan.FromSeconds(seconds));
        }

靜態方法:

RepeatMinutelyForever

RepeatMinutelyForTotalCount

RepeatSecondlyForever

RepeatSecondlyForTotalCount

RepeatHourlyForever

RepeatHourlyForTotalCount

var trigger = TriggerBuilder.Create().WithSchedule(SimpleScheduleBuilder.RepeatSecondlyForTotalCount(2)).Build();

 

 /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 minute interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of minutes.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForever(int minutes)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(minutes))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 second interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of seconds.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForever(int seconds)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(seconds))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with a 1 hour interval.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForever()
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(1))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat forever with an interval
        /// of the given number of hours.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForever(int hours)
        {
            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(hours))
                .RepeatForever();

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 minute interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of minutes.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatMinutelyForTotalCount(int count, int minutes)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromMinutes(minutes))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 second interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of seconds.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatSecondlyForTotalCount(int count, int seconds)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromSeconds(seconds))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with a 1 hour interval.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForTotalCount(int count)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(1))
                .WithRepeatCount(count - 1);

            return sb;
        }

        /// <summary>
        /// Create a SimpleScheduleBuilder set to repeat the given number
        /// of times - 1  with an interval of the given number of hours.
        /// </summary>
        /// <remarks>
        /// <para>Note: Total count = 1 (at start time) + repeat count</para>
        /// </remarks>
        /// <returns>the new SimpleScheduleBuilder</returns>
        public static SimpleScheduleBuilder RepeatHourlyForTotalCount(int count, int hours)
        {
            if (count < 1)
            {
                throw new ArgumentException("Total count of firings must be at least one! Given count: " + count);
            }

            SimpleScheduleBuilder sb = Create()
                .WithInterval(TimeSpan.FromHours(hours))
                .WithRepeatCount(count - 1);

            return sb;
        }

 

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

【其他文章推薦】

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

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

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

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

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

Day8-微信小程序實戰-交友小程序-首頁用戶列表渲染及多賬號調試及其點贊功能的實現

在這之前已經把編輯個人的所有信息的功能已經完成了

之後先對首頁的列表搞動態的,之前都是寫死的靜態

1、之前都是把好友寫死的,現在就在js裏面定義一個數組,用循環來動態的綁定

在onReady中定義,取真實的數據給定義的列表數組list  

通過調用  db.collection(‘users’).get()  這裏沒有加其他的限制,得到的就是所有的數據了,拿到全部的數據之後就會觸發then方法了

用then返回的res中有一個data的列表集合,有一個注意的點就是,這樣子讀取是吧數據庫中的數據的全部字段,但是我們需要用的只是

用戶的頭像和點贊數、用戶昵稱,其他的數據其實是不需要的

可以加一個field方法,可以要求返回的字段是哪些的

 

可以看到是只有一個用戶,我們為了模擬的話,就可以多賬號進行調試,

 

 1、創立多賬號

    ①首先這個多賬號的一定要是測試號,所以先進入微信的管理後台 https://mp.weixin.qq.com/

    ②進入 【成員管理】添加項目成員

    ③回到微信開發者工具中-》工具-》多賬號調試-》可以通過添加虛擬測試號來進行測試的,不用真實的微信號都可以

 

之後就是對點贊的功能進行設計了(就可以在index.wxml中給點贊的小心上加一個點擊事件即可了

(小細節在小程序中規定,在客戶端中讀取用戶列表的時候,一般不會把整個數據庫的用戶都讀取出來的,是有一個限制的

一般都是把前二十條數據給讀取出來的,如果數據一多的話,一般都是進行分頁處理了–一般都是用數據庫中的collection.skip和collection.limit,這兩個東西一起配合的話就可以做下拉加載的功能了)

由於這個點贊是要對找到用戶的id地址的,所以在wxml中給點贊這個圖標加上一個id自定義屬性的掛載

 

data-id="{{ item._id}}"

這個東西的用處就是,在點擊這個心心的時候就可以拿到這個自定義的屬性id了  

通過把handleLinks(ev)函數中把ev打印出來發現,這個自定義屬性id 的位置在

 ev.target.dataset.id

console.log就是用來測試的,如果沒效果的話,一般都是直接在點擊事件後面通過promise 的then把res打印出來看看情況是怎麼樣的

***有時候這些點擊事件無法觸發的話,就可以在檢查一下樣式,可能這個區域在前端显示是在這裏,但是實際上是在其他的地方,

 

 

 也就是布局引起的問題了

 

 

 

 可以看到這裏就是碰到的是點贊的這個圖標,但是這個樣式是在左上角進行了渲染的

這個時候為了演示把,就把自定義屬性,和點擊事件放在點贊圖標還有點贊數包含的這個text裏面了

<text bindtap="handleLinks" data-id="{{ item._id}}" >
          <!-- 點贊圖標 -->
              <text class="iconfont icondianzan"
              ></text>
          <!-- 點贊數 -->
              <text>{{ item.links }}</text>
          </text>

改完之後,再點擊心心或者是數量,就可以正常的進行點贊了

  但是發現只有給自己點贊的時候才可以改變點贊的數量,而改其他人點贊的時候就改不了

比如:

 

 

 這就是一個權限的問題了也就是只能改自己的數據(點贊數)改不了別人的數據l

 

 

因為在小程序端中,由於用戶可以直接對數據庫進行操作,所以會有一定的風險,所以就通過這個訪問權限來進行了限制

那?

怎麼修改別人的數據呢?—這個操作就要在服務端來進行操作了!  也就是在雲函數中去完成一個雲函數的操作了

 

下面就是講解 如何在 服務端來對数字字段來進行更改!

 

二、點贊功能實現與update雲函數

 由於要在服務端來做的話,就可以把這一塊的部分代碼刪掉了

  handleLinks(ev){
    let id = ev.target.dataset.id;
    db.collection('users').doc(id).update({
      data : {
        links : 5
      }
    }).then((res)=>{
      console.log(res)
    }); 
  }

需要新創一個雲函數(新建一個node.js雲函數

 

這些默認的結構都是可以刪掉的了

 

 之後就是參考 微信開放文檔 雲開發-》SDK文檔->數據庫-》collection->update-》示例代碼demo

其中:這個就是指定了數據庫的環境

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

然後就是在服務端拿到數據庫db

const db = cloud.database()

然後可以在示例代碼中看到async這個異步的操作

直接複製 try catch

try {
    return await db.collection('todos').where({
      done: false
    })
    .update({
      data: {
        progress: _.inc(10)
      },
    })
  } catch(e) {
    console.error(e)
  }

return就是返回一個異步的數據,而catch就是返回錯誤信息

主要修改的就是 db.collecion()中要反問那個數據庫表單,這裏不能寫死為users,因為可能其他的地方也是要用到更新的這個功能的

所以最好就是把update這個雲函數寫成一個通用的方式

其中雲函數入口函數 

exports.main = async (event, context) => {  這個裡面的event就是前端傳參過來的對象了 就訪問 event.colletion,然後不用where而是用doc 再把event的doc也傳進來,這 ***小知識點:ES6的擴展運算符 。。。 (三個點)

更新成功了之後,就可以返回結果到前台了

這個就是update雲函數中js文件的代碼(傳進去的doc實際上是用戶的_id

 // 雲函數入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
// 雲函數入口函數
exports.main = async (event, context) => {
  try {
    return await db.collection(event.collection).doc(event.doc)
      .update({
        data: {
         ...event.data 
        },
      })
  } catch (e) {
    console.error(e)
  }
}

View Code

把雲函數寫好之後,這個時候雲函數還是在本地,要把這個雲函數傳到雲開發平台上

 

上傳了之後一定要去雲平台-》雲函數中去檢查一下

 

之後就可以調用這個雲函數了

再回到index.js 點贊的方法 handleLinkes方法中進行設置即可;

 

 如果雲函數沒問題,可能是雲函數裏面定義的env出了問題,就可以寫死了,傳入自己的那個環境,就不用默認的那個環境了

【注意】修改了雲函數記得要重新上傳到雲平台才行

 

 

 

 (因為在服務端是不會受到數據庫權限的限制的)

後面要優化的就是(上面的點贊是寫死給多少links的,並且不能點完之後立馬更新

可以把數據庫的links讀出來,+1之後再寫入,但是這樣的話就多了一個數據庫的操縱了  ,但是數據庫本身就提供了累加或者累減等運算的操作的

(這樣的話就只需要一次的數據庫讀取即可了)

在開放文檔 db.command裏面就有很多的方法

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/command/Command.inc.html

示例代碼
將一個 todo 的進度自增 10:

const _ = db.command
db.collection('todos').doc('todo-id').update({
  data: {
    progress: _.inc(10)
  }
})

為了在服務端不把運算給寫死了,一般都是把運算直接通過前端來傳入的

由於前端不認識下劃線這種操作,因為前端要先解析,之後再把東西傳到服務端的,所以就可以在前端給服務端傳一個字符串的話

然後再在服務端解析即可

 data : "{links : _.inc(1)}"

在前端把這個字符串傳入到服務端中,之後就可以在服務端那邊對這個字符串進行解析了

所以在update雲函數中 就要對event.data這個傳過來的數據進行判斷,判斷它的類型,是普通的還是字符串類型的,如果是字符串類型的話就要進行解析

用js裏面的eval方法,它是把字符串轉成 js 語句的

 if(typeof event.data == 'string'){
      event.data =  eval('(' + event.data + ')')
    }

即可了(點一下心心就可以讓點贊數+1)

後面有空的話,可以繼續進行優化,也就是對一次的點贊數進行限制,或者是點一下加+1,再點一下就是取消了就-1了

後面就是要把點贊了之後,實時的把點贊數進行更新

 

可以看到給服務端那邊上傳之後,對數據庫進行了更新之後,then返回的結果res,中有一個是updated==1,就可以進行if判斷了

再用for循環對列表中的每一個元素判斷,是不是現在被點擊點贊的這個id

let updated = res.result.stats.updated;
    if(updated){
      // 先用擴展運算符 克隆一份數組
      let cloneListData = [...this.data.listData];
      for(let i = 0;i < cloneListData.length ; i++){
        if( cloneListData[i]._id == id){ 
          cloneListData[i].links++;
        }
      }
      this.setData({
        listData : cloneListData
      });
    }

點贊數增加 就是通過_inc 但是在服務端中的update函數中是用全局的,不能寫死,所以運算的規則就通過前端傳過去

為了以後其他的頁面也有更新功能的話做準備了

 

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

一起玩轉微服務(7)——單一職責

 

單一職責

單一職責原則(Single Responsibility Principle, SRP):一個類只負責一個功能領域中的相應職責,或者可以定義為:就一個類而言,應該只有一個引起它變化的原因。

單一職責原則是實現高內聚、低耦合的指導方針,它是最簡單但又最難運用的原則

單一職責原則是最簡單的面向對象設計原則,它用於控制類的粒度大小

設計原則很重要的一點就是簡單,單一職責,也就是我們經常所說的專人干專事。

一個單元(一個類、函數或者微服務)應該有且只有一個職責。無論如何,一個微服務不應該包含多於一個的職責。職責單一的後果之一就是職責單位(微服務,類,接口,函數)的數量劇增。據說Amazon,Netflix這些採用微服務架構的網站一個小功能就會調用幾十上百個微服務。但是相較於每個函數都是多個業務邏輯或職責功能的混合體的情況,維護成本還是低很多的。 SRP中的“單一職責”是個比較模糊的概念。對於函數,它可能指單一的功能,不涉及複雜邏輯;但對於類或者接口,它可能是指對單一對象的操作,也可能是指對該對象單一屬性的操作。總而言之,單一職責原則就是為了讓代碼邏輯更加清晰,可維護性更好,定位問題更快的一種設計原則。

什麼是高內聚低耦合?

這犀利的措辭一看就是來自開發界的術語。高內聚是說一個功能模塊最好僅完成一個獨立的子功能並且完成的很好。低耦合是指模塊與模塊之間盡量獨立/聯繫少/接口簡單。

這個原則出現的背景是為了讓程序“可復用/可擴展/夠靈活/可維護”。干過一陣子產品的人對這幾個詞應該都不陌生。對於程序設計者來說,這幾個詞是十分重要的,不亞於產品經理口中的“用戶體驗”(原則or擋箭牌)。

優點

單一職責的優點如下:

•類的複雜性降低,實現什麼職責都有清晰明確的定義。•可讀性提高,複雜性降低。•可維護性提高,可讀性提高。•變更引起的風險降低,變更是必不可少的,如果接口的單一職責做得好,一個接口修改只對相應的實現類有影響,對其他的接口無影響,這對系統的擴展性、維護性都有非常大的幫助。

記得在三字經裡邊有這樣一段 教之道,貴以專(出自三字經) 說的就是無論學習還是構建團隊,最重要的是專才,而不是全才。就好比一個足球隊,如果都是前鋒或者都是後衛,那麼這樣的球隊一定不能出成績,反而是將各個位置上的人進行統一協調,根據分工不同,共同協作,形成1+1>2的效果,那麼這樣的團隊就非常容易出成績。

有很多公司為了趕進度,經常會招聘一些所謂的全能型人才,但是這種人往往專業的程度不夠,當遇到某些棘手的問題的時候,往往不能夠非常快速的解決問題。從而導致最終交付的質量較差。

單一職責的目的

實施單一職責的目的如下:

•以類來隔離需求功能點,這樣當一個點的需求發生變化的時候,不會影響別的類的邏輯,這個和設計模式中的開閉原則類似,對於擴展持開放態度,對於修改持關閉態度。•是一個原子模塊級的粒度,至於原子的粒度到底是什麼樣的,應該因業務而異,設計的過程中同時考慮業務的擴展,所以這就要求在設計的過程中,必須有業務專家共同參与,共同規避風險。•粒度小,靈活,復用性強,方便更高一級別的抽象。

每個微服務單獨運行在獨立的進程中,能夠實現松耦合,並且獨立部署。

如何做

分3步:

1.把一個具體的問題抽象成一類問題;

2.根據用戶體驗流程劃分功能模塊;

3.針對每個功能設計封閉的解決方案。

最佳實踐

在實際工作中,有一個經常會用到的設計模式,DAO模式,又叫數據訪問對象,裏面定義了數據庫中表的增、刪、改、查操作,按照單一職責原則,為什麼不把增、刪、改、查分別定義成四種接口?這是因為數據庫的表操作,基本上就是這四種類型,不可能變化,所以沒有必要分開定義,反而經常變化的是數據庫的表結構,表結構一變,這四種操作都要跟着變。所以通常我們會針對一張表實現一個DAO,一張表就代表一種類型的職責。

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

【其他文章推薦】

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

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

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

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

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

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

鍵盤俠Linux教程(五)| 基本權限管理

基本權限管理

權限的介紹

權限位的含義

前面講解ls命令時,我們已經知道長格式显示的第一列就是文件的權限,例如:

[root@es ~]# ls -l anaconda-ks.cfg
-rw-------. 1 root root 1573 May 18 23:28 anaconda-ks.cfg

第一位為文件類型

文件類型標識 文件類型
普通文件
d 目錄文件
l 軟鏈接文件
s(偽文件) 套接字文件
b(偽文件) 塊設備文件
c(偽文件) 字符設備文件
p(偽文件) 管道符文件

第一列的權限位如果不計算最後的 “.” (這個點的含義我們在後面解釋),則共有10位,這10位權限位的含義如圖所示。

基本權限介紹

修改權限的命令 chmod ,基本信息如下

命令格式

[root@es ~]#chmod [選項] 權限模式 文件名

選項:

-R : 遞歸設置權限,也就是給子目錄中的所有文件設定權限

權限模式

chmod 命令的權限模式的格式時”[ugoa][[+-=][perms]]”,也就是“[用戶身份][[賦予方式][權限]]”的格式

  • 用戶身份:

    • u:代表所有者(user)

    • g:代表所屬組(group)

    • o:代表其他人(other)

    • a:代表全部身份(all)

  • 賦予方式:

    • +:加入權限

    • -:減去權限

    • =:設置權限

  • 權限:

    • -r:讀取權限(read)

    • -w:寫權限(write)

    • -x:執行權限(execute)

数字權限

数字權限的賦予方式是最簡單的,但是不如之前的字母權限好記,直觀。我們來看看這些数字權限的含義。

  • 4:代表”r”權限

  • 2:代表”w”權限

  • 1:代表”x”權限

常用權限

数字權限的賦予方式更加簡單,但是需要用戶對這幾個数字更加熟悉。其實常用權限也並不多,只有如下幾個。

  • 644:這是文件的基本權限,代表所有者擁有讀,寫權限,而所屬組和其他人擁有隻讀權限。

  • 755:這是文件的執行權限和目錄的基本權限,代表所有者擁有讀,寫和執行權限,而所屬組和其他人擁有讀和執行權限。

  • 777:這時最大權限。在實際的生產服務器中,要儘力避免給文件或目錄賦予這樣的權限,這會造成一定的安全隱患。

基本權限的作用

權限含義的解釋

首先,讀,寫,執行權限對文件和目錄的作用是不同的。

  • 權限對文件的作用

    • 讀(r):對文件有讀(r)權限,代表可以讀取文件中的數據。如果把權限對應到命令上,那麼一旦對文件有讀(r)權限,就可以對文件執行cat,more,less,head,tail等文件查看命令。

    • 寫(w):對文件有寫(w)權限,代表可以修改文件中的數據。如果把權限對應到命令上,那麼一旦對文件有寫(w)權限,就可以對文件執行vim,echo等修改文件數據的命令。注意:對文件有寫權限,是不能刪除文件本身的,只能修改文件中的數據。如果要想刪除文件,則需要對文件的上級目錄擁有寫權限。

    • 執行(x):對文件有執行(x)權限,代表文件擁有了執行權限,可以運行。在Linux中,只要文件有執行(x)權限,這個文件就是執行文件了。只是這個文件到底能不能正確執行,不僅需要執行(x)權限,還要看文件中代碼是不是正確的語言代碼。文件夾來說,執行(x)權限是最高權限。

  • 權限對目錄的作用

    • 讀(r):對目錄有讀(r)權限,代表可以查看目錄下的內容,也就是可以查看目錄下有哪些子文件和子目錄。如果把權限對應到命令上,那麼一旦對目錄擁有了讀(r)權限,就可以在目錄下執行ls命令,查看目錄下的內容

    • 寫(w):對目錄有寫(r)權限,代表可以修改目錄下的數據,也就是可以在目錄中新建,刪除,複製,剪切子文件或子目錄。如果把權限對應到命令上,那麼一旦目錄擁有了寫(w)權限,就可以在目錄下執行touch,rm,cp,mv命令。對目錄來說寫(w)權限是最高權限。

    • 執行(x):目錄是不能運行的,那麼對目錄擁有執行(x)權限,代表可以進入到目錄。如果把權限對應到命令上,那麼一旦對目錄擁有了執行(x)權限,就可以對目錄執行cd命令,進入目錄。

目錄的可用權限

目錄的可用權限其實有以下幾個

  • 0:任何權限都不賦予

  • 5:基本的目錄瀏覽和進入權限

  • 7:完全權限

所有者和所屬組命令

chown命令

修改權限的命令 chown ,基本信息如下

[root@es ~]#chown [選項] 所有者:所屬組 文件或目錄

選項:

-R : 遞歸設置權限,也就是給子目錄中的所有文件設定權限

普通用戶不能修改文件的所有者,哪怕自己是這個文件的所有者也不行,只有超級用戶才能修改
普通用戶可以修改所有者是自己的文件的權限=

umask 默認權限

查看系統的umask權限

#用八進制數值显示umask權限
[root@centos7 ~]# umask
0022

#用字母表示文件和目錄的初始權限
[root@centos7 ~]# umask -S
u=rwx,g=rx,o=rx

umask權限的計算方法

我們需要先了解一下新建文件和目錄的默認最大權限

  • 對文件來講,新建文件的默認最大權限是666,沒有執行(x)權限。這時因為執行權限對文件來講比較危險,不能在新建文件的時候默認賦予,而必須通過用戶手工賦予。

  • 文件的默認權限最大隻能是666,而umask的值是022
    “-rw-rw-rw-“減去”—–w–w-” 等於”-rw-r–r–“

  • 對目錄來講,新建文件的默認最大權限是777。這時因為對目錄而言,執行(x)權限僅僅代表進入目錄,所以即使建立新文件時直接默認賦予,也沒有什麼危險。

  • 目錄的權人權限最大隻能是777,而umask的值是022

“drwxrwxrwx” 減去 “d—-w–w-” 等於 “drwx-r-xr-x”

寫在最後

如果文檔對你有幫助的話,留個贊再走吧 ,你的點擊是我的最大動力。

我是鍵盤俠,現實中我唯唯諾諾,網絡上我重拳出擊,關注我,持續更新Linux乾貨教程。

更多鍵盤俠Linux系列教程:鏈接地址

更多Linux乾貨教程請掃:

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

【其他文章推薦】

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

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

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

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

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

教你一招另闢蹊徑抓取美團火鍋數據

最近有個小夥伴在群里問美團數據怎麼獲取,而且她只要火鍋數據,她在上海,只要求抓上海美團火鍋的數據,而且要求也不高,只要100條,想做個簡單的分析,相關的字段如下圖所示。

乍一看,這個問題還真的是蠻難的,畢竟美團也不是那麼好抓,什麼驗證碼,模擬登陸等一大堆拂面而來,嚇得小夥伴都倒地了。

通過F12查看,抓包,分析URL,找規律,等等操作。

不過白慌,今天小編給大家介紹一個小技巧,另闢蹊徑去搞定美團的數據,這裏需要用到抓包工具Fiddler。講道理,之前我開始接觸網絡爬蟲的時候也沒有聽過這個東東,後來就慢慢知道了,而且它真的蠻實用的,建議大家都能學會用它。這個工具專門用於抓包,而且其安裝包也非常小,如下圖所示。

接下來,我們開始進行抓取信息。

1、在Fiddler的左側找到meituan網站的鏈接,如下圖所示。鏈接的左邊返回的response(響應)的文件類型,可以看到是JSON文件,爾後雙擊這一行鏈接。

2、此時在右側會显示下圖的界面,點擊黃色區域內的那串英文“Responsebody is encoded. Click to decode.”意思是response是加密的,點擊此處進行解碼,對返回的網頁進行解碼。

3、此時會彈出下圖所示的界面,在WebView中可以看到返回的數據,與網頁中的內容對應一致。

4、不過美團網限制一頁最多显示32條火鍋信息,如下圖所示。

5、如果我想獲取100條信息的話,那得前後找4頁,才能夠滿足要求。有沒有辦法讓其一次性多显示一些數據呢?答案是可以的,操作方法如下。

在左側找到對應的美團網鏈接,然後點擊右鍵一次選擇CopyàJustUrl,如下圖所示。

7、將得到的URL放到瀏覽器中去進行訪問,如下圖所示。可以看到limit=32,即代表可以獲取到32條相關的火鍋信息,並且返回的內容和Fiddler抓包工具返回的信息是一致的。

8、此時,我們直接在瀏覽器中將limit=32這個參數改為limit=100,也就是說將32更改為100,讓其一次性返回100條火鍋數據,天助我也,竟然可以一次性訪問到,如下圖所示。就這樣,輕輕鬆松的拿到了一百條數據。

9、接下來,可以將瀏覽器返回的數據進行Ctrl+A全部選中,放到一個本地文件中去,存為txt格式,在sublime中打開,如下圖所示。

10、其實乍一看覺得很亂,其實它就是一個JSON文件,剩下的工作就是對這個JSON文件做字符串的提取,寫個代碼,提取我們的目標信息,包括店門、星級、評論數、關鍵詞、地址、人均消費等,如下圖所示。

11、運行程序之後,我們會得到一個txt文件,列與列之間以製表符分開,如下圖所示。

12、在txt文件中看上去很是費勁,將其導入到Excel文件中去,就清晰多了,如下圖所示。接下來就可以很方便的對數據做分析什麼的了。

13、至此,抓取美團火鍋數據的簡易方法就介紹到這裏了,希望小夥伴們都可以學會,以後抓取類似的數據就不用找他人幫你寫程序啦~~

14、關於本文涉及的部分代碼,小編已經上傳到github了,後台回復【美團火鍋】四個字即可獲取。

看完本文有收穫?請轉發分享給更多的人

IT共享之家

入群請在微信後台回復【入群】

想學習更多Python網絡爬蟲與數據挖掘知識,可前往專業網站:http://pdcfighting.com/

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

【其他文章推薦】

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

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

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

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

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