C Primer Plus(三)

重讀C Primer Plus ,查漏補缺

  重讀C Primer Plus,記錄遺漏的、未掌握的、不清楚的知識點

 

文件輸入/輸出

  1、fgets函數在讀取文件內容時會將換行符讀入,但gets不會,fputs函數在寫入文件時不會追加一個換行符,但puts會,應該對應配合使用。

  2、不同操作系統下,以文本方式打開文件,幾乎沒有區別,但由於不同操作系統文件結尾的的標識符不同,以二進制方式打開時,可能會將結尾標識符錯誤輸出。

  3、對於大型文件,有兩個特殊的函數提供支持:

1 int fgetpos(FILE * restrict stream, fpos_t * restrict pos);
2 int fsetpos(FILE * stream, const fpos_t *pos);

  其中,fpos_t是通過其他類型定義的文件定位類型,在使用上述函數時,fsetpos中的pos必須是通過fgetpos函數獲得的。當兩個函數執行成功時,會返回0。

  4、其他標準IO函數

 1 size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);
 2 size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);
 3 // 是否到達文件結尾
 4 int feof(FILE* fp);
 5 // 是否發生讀寫錯誤
 6 int ferror(FILE* fp);
 7 // 將字符迴流進緩衝區
 8 int ungetc(int c, FILE* fp)
 9 // 立刻將緩衝區內容寫入文件
10 int fflush(FILE* fp)
11 // 替換緩衝區
12 int setvbuf(FILE* restrict fp, char * restrict buf, int mode, size_t size)

  當然,上述的一些函數在目前的VS Studio中會被認為是不安全的函數,已經過時。

  

結構和其他數據格式

   5、C99標準下支持對結構體初始化時的任意字段賦值:

1 struct book gift = {.value=25.99, .author="Harry Potter", .title="Yoo"};
2 // 此時 0.25 會被賦給定義結構體時author后的那個成員,即便那個成員已經被初始化過。
3 struct book gift = {.value=25.99, .author="Harry Potter", 0.25};

  6、對於結構體數組,數組名不是其首個元素的地址,需要引用首個元素再取地址。

  7、在結構中一般使用字符數組,而不使用字符指針,結構中的字符指針無法很好的初始化地址,這樣會有使用上的風險,所以結構中的字符指針最好只指向那些字符串常量或者是指向由malloc分配的內存。

  8、C99標準對結構也支持複合文字,同時複合文字的結構也可以作為函數參數,也可以取地址,也和普通變量有相同的生存周期,聲明方式如下:

1 (struct book) {"The Idiot", "Fyodor Dostoyevsky", 6.99}

  9、C99支持一種伸縮型數組成員,這個成員必須是結構中最後一個成員,而且不是唯一一個成員,就像聲明普通數組一樣,但括號內為空,這個成員不會在聲明后立即存在,實際上,C99希望使用malloc為這樣含有伸縮型成員的數組分配空間。

1 struct flex{
2     int count;
3     double avreage;
4     double scores[]; // 伸縮型成員
5 }
6 struct flex * pf;
7 pf = malloc(sizeof(struct flex) + 5*sizeof(double))
8 pf->count = 5;
9 pf->scores[2] = 2.99;

  10、對於C中的枚舉類型,某些屬性不能順延至C++,例如C允許對枚舉做++運算,但C++不允許。

1 enum spectrum {red, yellow, green, blue};
2 spectrum color;
3 for(color = red; color != blue; color++);

  11、在C中,對於同一作用域下的標記和變量名可以使用同一個名字,因為對於標記(枚舉、結構,聯合),他們使用的名字空間與普通變量不同,但C++中不可以,例:

1 struct complex{double x, double y};
2 int complex; // 在C中不會引起衝突,但C++中則不允許

  12、對於函數指針執行函數時,會出現兩種語法,ANSI C把他們視為等價的。

1 void ToUpper(char *);
2 void (*pf) (char*);
3 char str[] = "hello";
4 pf = ToUpper;
5 (*pf)(str); // 語法1
6 pf(str);    // 語法2

  

位操作

  13、為什麼一個字節可以表示的有符號整數的範圍是-128~+127?

  看這裏:https://www.cnblogs.com/Dylan7/p/12649972.html

  14、計算機中小數是如何表示的?(一部分表示指數,一部分表示小數,有精確度問題)

  15、對位進行操作的第二種方法就是位字段(從沒用過,細節可以用到時再研究),位字段好比一個結構體,但其中的成員,代表的是某幾位上的值,好處是避免了通過複雜的位運算去控制某些位上的值,聲明例如:

1 struct box
2 {
3     unsigned int opaque       :1 // 整體結構的對齊補齊依據無符號整型
4     unsigned int fill_color   :3 // 数字代表需要幾位來表示這個字段
5     unsigned int              :4 // 可以跳過一些位
6     unsigned int show_border  :1 // 但一個字段不能橫跨兩個無符號整型的邊界
7 }
8 struct box b;
9 b.fill_color = 7; // 不可以超過字段所佔用的位可表示的上限

  

C預處理器和C庫

  16、程序翻譯的第一步,在預處理前,編譯器會對代碼做一些翻譯,將代碼中出現的字符映射到源字符集(用來處理多字節字符和使C外觀更加國際化的三元字符擴展),接着查找反斜杠后緊跟換行符的實例,將其轉換為一行,然後將文本劃分為預處理的語言符號序列以及空白字符及註釋序列(將用一個空格代替一個註釋),最後進入預處理階段,尋找每一個預處理指令。

  17、 幾個宏定義

1 #define F(x) #x      // #將語言符號字符串化
2 #define F(x) F##x    // ##將兩個語言符號組成一個語言符號
3 #define F(x,...)  printf("x", __VA_ARGS__)  // ...和__VA_ARGS__,可變參數(必須為最後一個參數)

  18、#if 指令後面跟常量整數表達式,可以與 #elif 配合使用,例如:

1 #if 1 == SYS
2     ...
3 #elif 2 == SYS
4     ...
5 #endif    

  同時,還有以下新的實現方式,defined 是一個預處理運算符,如果參數使用#define定義過,defined返回1,否則返回0。

1 #if defined(INMPC)
2     ...
3 #elif defined(VAX)
4     ...
5 #endif   

  19、#line 用於重置__LINE__,__FILE__宏所報告的行數

    #error 指令使預處理器可以發出一條錯誤信息

1 #line 10000
2 #line 10 cool.c"
3 #if __STD_VERSION__ != 199901L
4     #error Not C99
5 #endif

  20、C99 提供了_Pragma預處理器運算符,可以將字符串轉換成常規的編譯指示

1 _Pragma("c99 on") 等價於
2 #pragma c99 on

  21、內聯函數不會在調試器中显示,例如使用gdb調試時,有些內聯函數無法被手動執行,同時內聯函數具有內部鏈接屬性,所以在多文件程序中,使用其他文件的內聯函數時,要單獨聲明一次,並且在嘗試獲 取內聯函數的地址時,編譯器都會產生非內聯函數,也就是說可能產生外部定義的函數。

  23、在main()函數結束時,會隱式地調用exit()函數,同時,可以通過atexit()函數,向exit()註冊在程序允許結束時執行的函數,ANSI C保證可以設置至少32個函數,按照先設置后執行的順序執行,atexit()函數接受一個返回值為void,參數也為void的函數指針作為唯一參數。

  24、memcpy()與memmove()兩個函數的區別在於聲明上,以及memcpy()會假定兩個內存區沒有重疊。

1 void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
2 void *memmove(void *s1, void *s2, size_t n);

  25、可變參數的相關內容包含在stdarg.h頭文件中,使用起來比較複雜,包括初始化可變參數列表,遍歷列表,清理列表,拷貝列表等一系列操作,需要時再研究。

 

高級數據表示

  26、 這章沒什麼新奇內容,但它告訴我們,用C可以實現很多複雜的數據結構。

 

 

  2020年4月16日,星期五,晚23點09分,首次完整讀完這本書,共勉。

  學如逆水行舟,不進則退;心似平原放馬,易縱難收。

 

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

【其他文章推薦】

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

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

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

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

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

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

從0到70%:Chrome上位揭秘!

最近的數據显示,Chrome在2020年4月的市場份額達到了70%左右,把微軟的Edge和Firefox遠遠甩在身後,毫無疑問,Chrome贏得了第二次遊覽器之戰,成為新一代王者。 

 

Chrome的第一版於2008年推出,當時微軟的IE瀏覽器幾乎佔到了60%的份額,Firefox緊隨其後,佔據了大概30%,Chrome在2008年僅占0.3%。 

十年以後Chrome就主導了瀏覽器的市場, 這一切是怎麼發生的? 

我們先來回顧一下第一次瀏覽器之戰,交戰的雙方是Netscape的Navigator瀏覽器和微軟的IE, Netscape佔據着先發優勢,IE則背靠Windows這棵大樹,雙方你來我往,戰事極為精彩,競爭帶來了技術進步,像JavaScript、DHTML、CSS、XMLHttpRequest等各種技術層出不窮。 

IE4成為這場戰爭的轉折點,因為它被集成到了Windows當中, 開箱即用,免費,誰還會去額外下載安裝收費的Netscape呢?  

Netscape從此潰不成軍,IE贏得了最後的勝利,從這張圖中可以清楚地看出IE和Netscape之間此消彼長的勢頭。 

 

IE的勝利也結束了Web瀏覽器的快速創新,早期的IE是积極進取的,比如AJAX的基石XMLHttpRequest就是IE率先提出來,並且發揚光大的。 

可是一旦垄斷形成,微軟就不思進取,不想更新了,2001年微軟發布IE6以後,在長達5年的時間里,IE居然沒有新版本發布! 

很多年輕的程序員沒有經歷過被IE支配的“恐懼”,那個時候開發網頁,必須要保證在IE6上能夠運行,否則你絕對活不了。巔峰時期IE6曾經達到過90%多的恐怖佔有率, 很多國企,內部系統都是基於IE6。 

雖然Netscape的瀏覽器戰敗,卻沒有因為死亡,Netscape把Navigator的代碼開源,捐給了非盈利的Mozilla基金會。在這裏Netscape幾經輾轉,終於在2004年涅槃重生,變身為著名的Firefox。 

 

我現在還記得第一次看到FireFox時的感受:非常輕薄!速度飛快!作為開發人員,我迅速就拋棄了老舊不堪的IE, 把Firefox作為主力的瀏覽器。 

Firefox也不負眾望,在此後的幾年中穩步上升,到2009年達到了30%多的佔有率,隱隱有成為下一個霸主的潛質。 

可是另外一個可怕的對手出現了,Google在2008年推出了一個叫做Chrome的瀏覽器,這個時候iPhone上市不到一年,Windows7剛剛面世,IE依然是最流行的瀏覽器。 

但是Google卻看到了不一樣的東西,它們認為現在的互聯網和10幾年前大不相同了,原來只是web pages,現在到處是applications,而瀏覽器的本質卻沒有變化。Google覺得自己有責任改變, 這幾幅漫畫講述了Google要推出Chrome的根本原因: 

 

 此時的Web已經進入Web2.0時代,像Google Map和GMail這樣的應用迫切需要瀏覽器能夠快速地裝載頁面,快速地執行JavaScript。 

Google下定決心,從零開始設計一個滿足現代Web應用的瀏覽器, 瀏覽器不僅僅是一個瀏覽網頁的工具,而是一個新的平台,在此之上可以在線完成各種事情,這種深刻的洞察力將給Google Chrome帶來極大的成功。 

Google給新瀏覽器定下的目標是:穩定,快速,安全,好用,開源。財大氣粗的它組建了一支豪華團隊來開發Chrome , 並且從Firefox挖走了好幾員幹將,如Ben Goodger,這可是Firefox的主力開發。 

與IE和Firefox相比,Chrome的一大優勢就是拋棄了遺留代碼的包袱,從頭開始設計,開發人員可以盡情地施展才華,他們帶來了兩個重要的創新: 

1. 在很早的時候就確定下了“沙箱”的機制:每個Tab頁都運行在自己的進程中,互不影響,充分利用多核。 

2. 開發了強勁的JavaScript執行引擎 V8,讓Web應用迅速地執行JavaScript代碼。 

2008年9月,Chrome推出Beta版,9個月後,即獲得3000萬用戶 

2009年12月,推出擴展程序庫,讓用戶安裝第三方插件,生態迅速繁榮。 

2010年,推出Web 應用商店。 

2012年2月,Chrome發布了Android版本, 6月推出iOS版本,此時市場份額達到30%以上 

2013年,為了對第三方的惡意擴展程序進行控制,Google要求所有的擴展必須託管在應用商店中 

……

 

一系列措施讓Chrome迅速蠶食了Firefox和IE的市場,從這幅圖可以清晰地看出IE(藍色線條)的沒落和Chrome(綠色線條)的崛起。

 

 

微軟豈會就此認輸?在這段時間內相繼推出IE7, IE8, IE9,IE10 , IE 11, 但是遺留的包袱讓它步履維艱,它那緩慢的速度經常成為大家調侃的對象: 

 

到了Windows 10 ,微軟另起爐灶,推出新的瀏覽器Edge,但也難挽敗局。 

微軟新CEO納德拉上台以後,一反原來封閉的形象,擁抱開源。2018年底,微軟宣布將會採用Google開源的Chromium為核心來構建Edge瀏覽器,從此Microsoft Edge和Google Chrome算是同源了,以後發展如何,我們拭目以待。 

Chome登上王位以後,對Google帶來了巨大的好處,因為Google本身提供了很多極為Web的服務:GMail, Google Map , Youtube, Google Gocs, Google Earth….  現在Google把瀏覽器端和服務器端都掌握了,那修改一下中間的協議也不算什麼了,對用戶來說,反正背後的協議也看不到,只要能變快就行。 

Google可以用Chrome試驗各種新協議,於是我們看到它對HTTP1.1動手,做了一個叫做SPDY協議的實驗,非常成功,成為了HTTP 2的基礎。然後又對傳輸層協議開刀,搞出了一個新的傳輸層協議QUIC,解決了TCP了諸多問題,有望把TCP給替換掉。基於QUIC,新的HTTP協議,即HTTP/3正在制定當中。 

尾聲

 Chrome的成功主要是因為Google深刻的洞察力,他們看到了Web未來的趨勢,迅速推出產品擁抱了這種趨勢。 

Chrome如今佔據了和當年的IE6一樣的主導地位, 一些批評聲音出現了,The verge有一篇報道說Google的很多Web應用都提倡“使用Chrome瀏覽效果最佳”, “Google Meet、Allo、YouTube TV、Google Earth 和 YouTube Studio Beta 都會阻止 Windows 10 系統的默認瀏覽器 Microsoft Edge 訪問它們,並指引用戶下載 Chrome 瀏覽器” ,“使用非Chrome瀏覽器訪問google.com會被提醒三次下載Chrome。”

 

 

Chrome最終會走向何方?你覺得Chrome會像IE那樣停滯不前嗎? 

參考資料:

https://en.wikipedia.org/wiki/Browser_wars

https://usefyi.com/chrome-history/

https://www.theverge.com/2018/1/4/16805216/google-chrome-only-sites-internet-explorer-6-web-standards

https://www.google.com/googlebooks/chrome/big_00.html

 

更多精彩文章,盡在碼農翻身

微服務把我坑了

如何降低程序員的工資?

程序員,你得選准跑路的時間!

兩年,我學會了所有的編程語言!

一直CRUD,一直996,我煩透了,我要轉型

字節碼萬歲!

上帝託夢給我說:一切皆文件

Javascript: 一個屌絲的逆襲

Node.js :我只需要一個店小二

我是一個線程

TCP/IP之大明郵差

一個故事講完Https

CPU 阿甘

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

【其他文章推薦】

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

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

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

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

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

設計模式系列之工廠模式三兄弟(Factory Pattern)

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

工廠模式是最常用的一類創建型設計模式,通常我們所說的工廠模式是指工廠方法模式,它也是使用頻率最高的工廠模式。簡單工廠模式是工廠方法模式的“小弟”,它不屬於GoF23種設計模式,但在軟件開發中應用也較為頻繁,通常將它作為學習其他工廠模式的入門。此外,工廠方法模式還有一位“大哥”——抽象工廠模式。這三種工廠模式各具特色,難度也逐個加大,在軟件開發中它們都得到了廣泛的應用,成為面向對象軟件中常用的創建對象的工具。

簡單工廠模式

簡單工廠模式並不屬於GoF 23個經典設計模式,但通常將它作為學習其他工廠模式的基礎,它的設計思想很簡單。

模式定義

簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據參數的不同返回不同類的實例,被創建的實例通常都具有共同的父類。因為在簡單工廠模式中用於創建實例的方法是靜態(static)方法,因此簡單工廠模式又被稱為靜態工廠方法(Static Factory Method)模式,它屬於類創建型模式。

簡單工廠模式的要點在於:當你需要什麼,只需要傳入一個正確的參數,就可以獲取你所需要的對象,而無須知道其創建細節。

模式結構圖

簡單工廠模式結構圖如下所示:

模式偽代碼

在使用簡單工廠模式時,首先需要對產品類進行重構,不能設計一個包羅萬象的產品類,而需根據實際情況設計一個產品層次結構,將所有產品類公共的代碼移至抽象產品類,並在抽象產品類中聲明一些抽象方法,以供不同的具體產品類來實現,典型的抽象產品類代碼如下所示:

public abstract class Product {
    // 所有產品的公共屬性

    // 所有產品類的公共業務方法
    public void methodSame() {
        //公共方法的實現
    }

    // 聲明抽象業務方法
    public abstract void methodDiff();
}

具體產品類中實現了抽象產品類中聲明的抽象業務方法。

public class ConcreteProduct extends Product {
    @Override
    public void methodDiff() {
        // 具體產品業務方法的實現
    }
}

簡單工廠模式的核心是工廠類,在沒有工廠類之前,客戶端一般會使用new關鍵字來直接創建產品對象,而在引入工廠類之後,客戶端可以通過工廠類來創建產品,在簡單工廠模式中,工廠類提供了一個靜態工廠方法供客戶端使用,根據所傳入的參數不同可以創建不同的產品對象,典型的工廠類代碼如下所示:

public class Factory {
    //靜態工廠方法
    public static Product getProduct(String arg) {
        Product product = null;
        if (arg.equalsIgnoreCase("A")) {
            product = new ConcreteProductA();
            //初始化設置product
        } else if (arg.equalsIgnoreCase("B")) {
            product = new ConcreteProductB();
            //初始化設置product
        }
        return product;
    }
}

客戶端代碼中,我們通過調用工廠類的工廠方法即可得到產品對象,典型代碼如下所示:

public class Client {
    public static void main(String[] args) {
        Product product;
        product = Factory.getProduct("A"); //通過工廠類創建產品對象
        product.methodSame();
        product.methodDiff();
    }
}

模式簡化

有時候,為了簡化簡單工廠模式,我們可以將抽象產品類工廠類合併,將靜態工廠方法移至抽象產品類中,如下圖所示。

客戶端可以通過產品父類的靜態工廠方法,根據參數的不同創建不同類型的產品子類對象,這種做法在JDK等類庫和框架中也廣泛存在。
比如:java.nio.charset.Charset

public abstract class Charset {

    /**
     * Returns a charset object for the named charset.
     */
    public static Charset forName(String charsetName) {
        java.nio.charset.Charset cs = lookup(charsetName);
        if (cs != null)
            return cs;
        throw new UnsupportedCharsetException(charsetName);
    }
}

模式小結

簡單工廠模式提供了專門的工廠類用於創建對象,將對象的創建和對象的使用分離開,它作為一種最簡單的工廠模式在軟件開發中得到了較為廣泛的應用。

使用場景:

  1. 工廠類負責創建的對象比較少,由於創建的對象較少,不會造成工廠方法中的業務邏輯太過複雜。
  2. 客戶端只知道傳入工廠類的參數,對於如何創建對象並不關心。

工廠方法模式

簡單工廠模式雖然簡單,但存在一個很嚴重的問題。當系統中需要引入新產品時,由於靜態工廠方法通過所傳入參數的不同來創建不同的產品,這必定要修改工廠類的源代碼,將違背“開閉原則”,如何實現增加新產品而不影響已有代碼?工廠方法模式應運而生。

模式定義

工廠方法模式中,我們不再提供一個統一的工廠類來創建所有的產品對象,而是針對不同的產品提供不同的工廠,系統提供一個與產品等級結構對應的工廠等級結構。工廠方法模式定義如下:

工廠方法模式(Factory Method Pattern):定義一個用於創建對象的接口,讓子類決定將哪一個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛擬構造器模式(Virtual Constructor Pattern)或多態工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類創建型模式。

模式結構圖

工廠方法模式提供一個抽象工廠接口來聲明抽象工廠方法,而由其子類來具體實現工廠方法,創建具體的產品對象。工廠方法模式結構如圖所示:

在工廠方法模式結構圖中包含如下幾個角色:

  • Product(抽象產品):它是定義產品的接口,是工廠方法模式所創建對象的超類型,也就是產品對象的公共父類。
  • ConcreteProduct(具體產品):它實現了抽象產品接口,某種類型的具體產品由專門的具體工廠創建,具體工廠和具體產品之間一一對應。
  • Factory(抽象工廠):在抽象工廠類中,聲明了工廠方法(Factory Method),用於返回一個產品。抽象工廠是工廠方法模式的核心,所有創建對象的工廠類都必須實現該接口。
  • ConcreteFactory(具體工廠):它是抽象工廠類的子類,實現了抽象工廠中定義的工廠方法,並可由客戶端調用,返回一個具體產品類的實例。

模式偽代碼

與簡單工廠模式相比,工廠方法模式最重要的區別是引入了抽象工廠角色,抽象工廠可以是接口,也可以是抽象類或者具體類,其典型代碼如下所示:

public interface Factory {
    Product factoryMethod();
}

在抽象工廠中聲明了工廠方法但並未實現工廠方法,具體產品對象的創建由其子類負責,客戶端針對抽象工廠編程,可在運行時再指定具體工廠類,具體工廠類實現了工廠方法,不同的具體工廠可以創建不同的具體產品,其典型代碼如下所示:

public class ConcreteFactory implements Factory {
    @Override
    public Product factoryMethod() {
        return new ConcreteProduct();
    }
}

在客戶端代碼中,只需關心工廠類即可,不同的具體工廠可以創建不同的產品,典型的客戶端類代碼片段如下所示:

public class Client {
    public static void main(String[] args) {
        // 確定是哪個工廠可得到產品
        Factory factory = new ConcreteFactory();
        // 獲取產品
        Product product = factory.factoryMethod();
    }
}

模式簡化

有時候,為了進一步簡化客戶端的使用,還可以對客戶端隱藏工廠方法,此時,在工廠類中將直接調用產品類的業務方法,客戶端無須調用工廠方法創建產品,直接通過工廠即可使用所創建的對象中的業務方法。

// 改為抽象類
public class AbstractFactory {
    // 在工廠類中直接調用產品類的業務方法
    public void productMethod() {
        Product product = this.createProduct();
        product.method();
    }

    public abstract Product createProduct();
}

通過將業務方法的調用移入工廠類,可以直接使用工廠對象來調用產品對象的業務方法,客戶端無須直接調用工廠方法,在客戶端並不關心Product細節的情況下使用這種設計方案會更加方便。

模式小結

工廠方法模式能夠讓工廠可以自主確定創建何種產品對象,而如何創建這個對象的細節則完全封裝在具體工廠內部,用戶只需要關心所需產品對應的工廠,無須關心創建細節,甚至無須知道具體產品類的類名。基於工廠角色產品角色的多態性設計是工廠方法模式的關鍵。

抽象工廠模式

工廠方法模式通過引入工廠等級結構,解決了簡單工廠模式中工廠類職責太重的問題,但由於工廠方法模式中的每個工廠只生產一類產品,可能會導致系統中存在大量的工廠類,勢必會增加系統的開銷。此時,我們可以考慮將一些相關的產品組成一個產品族,由同一個工廠來統一生產,這就是我們本文將要學習的抽象工廠模式的基本思想。

這裏我斗膽舉個例子來說明一下吧,如果不恰當歡迎指出。

眾所周知,國內知名的電器廠有海爾、海信(姑且就認為是2個),電器廠會生產電視機、電冰箱、空調(姑且就認為是3種產品)。

  • 使用工廠方法模式:工廠方法模式中每個工廠只生產一類產品,那麼就必須要有海爾電視機廠海爾電冰箱廠海爾空調廠海信電視機廠海信電冰箱廠海信空調廠
  • 使用抽象工廠模式:抽象工廠中每個工廠生產由多種產品組成的”產品族”,那麼就只需要有海爾工廠海信工廠就夠了,每個工廠可生產自家的電視機、電冰箱、空調。

由此看出使用抽象工廠模式極大地減少了系統中類的個數。

模式定義

抽象工廠模式為創建一組對象提供了一種解決方案。與工廠方法模式相比,抽象工廠模式中的具體工廠不只是創建一種產品,它負責創建一族產品。抽象工廠模式定義如下:

抽象工廠模式(Abstract Factory Pattern):提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,它是一種對象創建型模式。

模式結構圖

在抽象工廠模式中,每一個具體工廠都提供了多個工廠方法用於產生多種不同類型的產品,這些產品構成了一個產品族,抽象工廠模式結構如圖所示:

在抽象工廠模式結構圖中包含如下幾個角色:

  • AbstractFactory(抽象工廠):它聲明了一組用於創建一族產品的方法,每一個方法對應一種產品。
  • ConcreteFactory(具體工廠):它實現了在抽象工廠中聲明的創建產品的方法,生成一組具體產品,這些產品構成了一個產品族,每一個產品都位於某個產品等級結構中。
  • AbstractProduct(抽象產品):它為每種產品聲明接口,在抽象產品中聲明了產品所具有的業務方法。
  • ConcreteProduct(具體產品):它定義具體工廠生產的具體產品對象,實現抽象產品接口中聲明的業務方法。

模式偽代碼

在抽象工廠中聲明了多個工廠方法,用於創建不同類型的產品,抽象工廠可以是接口,也可以是抽象類或者具體類,其典型代碼如下所示:

public abstract class AbstractFactory {

    public abstract AbstractProductA createProductA();

    public abstract AbstractProductB createProductB();

    public abstract AbstractProductC createProductC();
}

具體工廠實現了抽象工廠,每一個具體的工廠方法可以返回一個特定的產品對象,而同一個具體工廠所創建的產品對象構成了一個產品族。對於每一個具體工廠類,其典型代碼如下所示:

public class ConcreteFactory1 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }

    @Override
    public AbstractProductC createProductC() {
        return new ConcreteProductC1();
    }
}

模式小結

如果一開始就學習抽象工廠模式估計很難理解為什麼這樣設計,按次序學習分析簡單工廠模式工廠方法模式抽象工廠模式基本就順理成章了。實際開發中,可能並不是照搬照套工廠模式三兄弟的偽代碼,大多會簡化其中的部分實現。本來學習設計模式就是重思想,學習如何用抽象類、接口、拆分、組合等將軟件解耦合,並增強系統可擴展性,這才是最關鍵的。

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

【其他文章推薦】

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

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

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

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

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

防疫封鎖 馬達加斯加狐猴族群獲得喘息

摘錄自2020年9月24日公視報導

安達西貝自然保護區是馬達加斯加島生態觀光的熱門地點之一,過去五個月因為新冠病毒疫情造成的封鎖以及邊境管制,當地最具代表性的動物狐猴,在原始雨林裡享受了沒有人類嘈雜群聚,寧靜自得的生活。島內九月起放寬了封鎖政策,觀光人數開始緩步回升,但因為國際航班仍然停擺,多數是馬達加斯加人自己的島內旅遊。

3月起陷入封鎖寒冬的旅遊業者,樂見顧客回歸,但富裕的外國觀光客進不來,仍然入不敷出。經濟壓力也傷害了自然環境。森林嚮導發現,最近林木被濫伐破壞的情況比過去30年都要嚴重。

馬達加斯加的旅遊業佔全國經濟的7%,堪稱重要支柱,而雨林生態體系脆弱,全國上百種的狐猴,幾乎都已經因為盜獵、暖化與森林砍伐,名列國際自然保護聯盟的紅色瀕危名單,其中30種更已經是極度瀕危,離滅絕只差一步。

生物多樣性
國際新聞
馬達加斯加
防疫
狐猴
動物與大環境變遷

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

口罩繩易纏動物 動保籲丟棄前先剪掉

摘錄自2020年9月24日公視報導

英國陸續發現有海鷗的雙腳被口罩繩纏住,就像戴了腳鐐一樣。根據統計,全球目前每個月消耗1000多億個拋棄式口罩和手套,對環境造成很大的負擔;動保團體呼籲民眾在丟掉口罩之前,至少先把繩子剪掉,以免傷害無辜的動物。

南韓環境運動聯合會白娜媛說:「一次性口罩是塑料做的,因此幾乎不能分解,因為無法回收,所以不是焚化就是掩埋,這對自然造成巨大負擔。」

英國皇家防止虐待動物協會10號指出,疫情爆發僅半年,他們就救援900多隻因廢棄口罩或塑膠垃圾受困的動物,呼籲大眾丟口罩前先剪斷鬆緊繩,以免纏住動物。

生物多樣性
國際新聞
口罩
海鷗

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

【其他文章推薦】

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

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

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

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

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

中國承諾2060年實現碳中和 外媒提五大疑問

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

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

亂棄口罩掀生態災難 企鵝誤吞N95口罩伏屍巴西沙灘

摘錄自2020年9月25日蘋果新聞報導

近日巴西聖保羅有企鵝伏屍沙灘,經驗屍發現牠胃內藏有一個無法消化的N95口罩,當地保育組織斥人類不當棄置廢物會導致海洋動物傷亡。

當地海洋保育組織Instituto Argonauta解剖時發現,企鵝的胃部有一個完整的N95口罩,相信令企鵝無法消化致死。組織又指出,自4月起在聖保羅北部沿岸已撿到多達113個棄置口罩,當中包括企鵝伏屍的沙灘。組織斥企鵝之死反映不當棄置廢物可導致海洋動物傷亡。

世界自然基金會(WWF)在7月亦警告過不當棄置口罩等個人防護設備(PPE),恐會對環境造成威脅。即使僅有1%的口罩未有妥善處理,已可導致每月有1000萬個棄置口罩流出大自然。

生物多樣性
國際新聞
巴西
企鵝
口罩
誤食

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

【其他文章推薦】

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

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

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

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

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

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

福島農夫的七種土質實測:土壤輻射污染越高,作物污染越嚴重

文:宋瑞文(媽媽監督核電廠聯盟特約撰述)

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

日本群馬縣養豬場爆發豬瘟 將撲殺5400頭豬隻

摘錄自2020年09月27日中央通訊社日本報導

日本農林水產省26日宣布,群馬縣高崎市一座養豬場發現豬隻感染家畜傳染病豬瘟(CSF),縣當局將依法撲殺養豬場內全部約5400頭豬隻。

時事通信社報導,這座養豬場為預防感染豬瘟,曾為豬隻接種疫苗,但確診感染的小豬並未接種疫苗。

這是時隔約半年,日本國內養豬場再度爆發豬瘟疫情,也是自2018年日本國內睽違26年首度爆發豬瘟疫情以來,群馬縣內養豬場首度確認感染。

群馬縣當局於發現野生野豬感染豬瘟後,從去年10月起,著手為養豬場接種疫苗。

生物多樣性
循環經濟
國際新聞
日本
豬瘟
經濟動物

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

【其他文章推薦】

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

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

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

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

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

最後生還者!澳洲擱淺領航鯨110頭獲救 360具鯨屍將拋海上

摘錄自2020年9月27日自由時報報導

澳洲塔斯馬尼亞州一座偏遠海港附近,上週約有470頭長肢領航鯨(long-finned pilot whale)擱淺,是澳洲史上最大規模的鯨魚擱淺紀錄,在救援人員積極搶救後,最後一頭還殘喘鯨魚在今(27)日被送回大海,讓倖存鯨魚數量達到110頭,政府將把重點轉向處理約360具鯨屍。

綜合外媒報導,在麥格理港(Macquarie Harbour)發現領航鯨擱淺後,100多名救援人員過去幾天不斷在寒冷的海水中搶救生還者,週日在數百具鯨屍中又發現了一頭還活著的鯨魚。塔斯馬尼亞州環境部門發言人說,這「完全不簡單」,並提到這頭鯨魚已被帶回大海中。

當地政府今日將重點從搜救轉為處理大批鯨屍,有數艘船今天將約200具屍體拖離港口,官方希望在週三天氣惡化前將處理完剩餘的死亡鯨魚。官方警告說,該地區可能會發現更多的鯨魚,因為有些鯨魚可能會二次擱淺。巴克也說,一些鯨魚屍體可能會漂回該地區的海灘。

海洋
國際新聞
澳洲
鯨豚擱淺
鯨魚
鯨魚擱淺

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案