我要做 Android 之面笔试总结
說說什么是工廠模式 ps:之前只是單純了解過工廠模式,不知道其實有三種工廠模式
一:工廠模式
工廠模式就有三種,它們分別是簡單工廠模式(并不在23中模式之中),工廠方法模式以及抽象工廠模式,其中我們通常所說的工廠模式指的是工廠方法模式,工廠方法模式是日常開發中使用頻率最高的一種設計模式。
簡單工廠模式
簡單工廠模式其實并不算是一種設計模式,更多的時候是一種編程習慣。
定義:
定義一個工廠類,根據傳入的參數不同返回不同的實例,被創建的實例具有共同的父類或接口。
適用場景:
其實由定義也大概能推測出其使用場景,首先由于只有一個工廠類,所以工廠類中創建的對象不能太多,否則工廠類的業務邏輯就太復雜了,其次由于工廠類封裝了對象的創建過程,所以客戶端應該不關心對象的創建。總結一下適用場景:
(1)需要創建的對象較少。
(2)客戶端不關心對象的創建過程。
以上就是簡單工廠模式簡單工廠模式的適用場景,下面看一個具體的實例。
實例:
創建一個可以繪制不同形狀的繪圖工具,可以繪制圓形,正方形,三角形,每個圖形都會有一個draw()方法用于繪圖,不看代碼先考慮一下如何通過該模式設計完成此功能。
由題可知圓形,正方形,三角形都屬于一種圖形,并且都具有draw方法,所以首先可以定義一個接口或者抽象類,作為這三個圖像的公共父類,并在其中聲明一個公共的draw方法。
public interface Shape {void draw(); }這里定義成抽象類也是可以的,只不過接口是更高一級的抽象,所以習慣定義成接口,而且接口支持多實現,方便以后擴展。
下面就是編寫具體的圖形,每種圖形都實現Shape 接口
圓形
正方形
public class RectShape implements Shape {public RectShape() {System.out.println( "RectShape: created");}@Overridepublic void draw() {System.out.println( "draw: RectShape");}}三角形
public class TriangleShape implements Shape {public TriangleShape() {System.out.println( "TriangleShape: created");}@Overridepublic void draw() {System.out.println( "draw: TriangleShape");}}下面是工廠類的具體實現
public class ShapeFactory {public static final String TAG = "ShapeFactory";public static Shape getShape(String type) {Shape shape = null;if (type.equalsIgnoreCase("circle")) {shape = new CircleShape();} else if (type.equalsIgnoreCase("rect")) {shape = new RectShape();} else if (type.equalsIgnoreCase("triangle")) {shape = new TriangleShape();}return shape;}}在這個工廠類中通過傳入不同的type可以new不同的形狀,返回結果為Shape 類型,這個就是簡單工廠核心的地方了。
客戶端使用
畫圓形
Shape shape= ShapeFactory.getShape("circle");shape.draw();畫正方形
Shape shape= ShapeFactory.getShape("rect");shape.draw();畫三角形
Shape shape= ShapeFactory.getShape("triangle");shape.draw();只通過給ShapeFactory傳入不同的參數就實現了各種形狀的繪制。以上就是簡單工廠方式。
工廠方法模式
工廠方法模式是簡單工廠的僅一步深化, 在工廠方法模式中,我們不再提供一個統一的工廠類來創建所有的對象,而是針對不同的對象提供不同的工廠。也就是說每個對象都有一個與之對應的工廠。
定義:
定義一個用于創建對象的接口,讓子類決定將哪一個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。
這次我們先用實例詳細解釋一下這個定義,最后在總結它的使用場景。
實例:
現在需要設計一個這樣的圖片加載類,它具有多個圖片加載器,用來加載jpg,png,gif格式的圖片,每個加載器都有一個read()方法,用于讀取圖片。下面我們完成這個圖片加載類。
首先完成圖片加載器的設計,編寫一個加載器的公共接口。
public interface Reader {void read(); }Reader 里面只有一個read()方法,然后完成各個圖片加載器的代碼。
Jpg圖片加載器
public class JpgReader implements Reader {@Overridepublic void read() {System.out.print("read jpg");} }Png圖片加載器
public class PngReader implements Reader {@Overridepublic void read() {System.out.print("read png");} }Gif圖片加載器
public class GifReader implements Reader {@Overridepublic void read() {System.out.print("read gif");} }現在我們按照定義所說定義一個抽象的工廠接口ReaderFactory
public interface ReaderFactory {Reader getReader(); }里面有一個getReader()方法返回我們的Reader 類,接下來我們把上面定義好的每個圖片加載器都提供一個工廠類,這些工廠類實現了ReaderFactory 。
Jpg加載器工廠
public class JpgReaderFactory implements ReaderFactory {@Overridepublic Reader getReader() {return new JpgReader();} }Png加載器工廠
public class PngReaderFactory implements ReaderFactory {@Overridepublic Reader getReader() {return new PngReader();} }Gif加載器工廠
public class GifReaderFactory implements ReaderFactory {@Overridepublic Reader getReader() {return new GifReader();} }在每個工廠類中我們都通過復寫的getReader()方法返回各自的圖片加載器對象。
客戶端使用
讀取Jpg
ReaderFactory factory=new JpgReaderFactory(); Reader reader=factory.getReader(); reader.read();讀取Png
ReaderFactory factory=new PngReaderFactory(); Reader reader=factory.getReader(); reader.read();讀取Gif
ReaderFactory factory=new GifReaderFactory(); Reader reader=factory.getReader(); reader.read();可以看到上面三段代碼,分別讀取了不同格式的圖片,不同之處在于針對不同的圖片格式聲明了不同的工廠,進而創建了相應的圖片加載器。
適用場景:
(1)客戶端不需要知道它所創建的對象的類。例子中我們不知道每個圖片加載器具體叫什么名,只知道創建它的工廠名就完成了床架過程。
(2)客戶端可以通過子類來指定創建對應的對象。
以上場景使用于采用工廠方法模式。
抽象工廠模式
這個模式最不好理解,而且在實際應用中局限性也蠻大的,因為這個模式并不符合開閉原則。實際開發還需要做好權衡。
抽象工廠模式是工廠方法的僅一步深化,在這個模式中的工廠類不單單可以創建一個對象,而是可以創建一組對象。這是和工廠方法最大的不同點。
定義:
提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。( 在抽象工廠模式中,每一個具體工廠都提供了多個工廠方法用于產生多種不同類型的對象)
抽象工廠和工廠方法一樣可以劃分為4大部分:
AbstractFactory(抽象工廠)聲明了一組用于創建對象的方法,注意是一組。
ConcreteFactory(具體工廠):它實現了在抽象工廠中聲明的創建對象的方法,生成一組具體對象。
AbstractProduct(抽象產品):它為每種對象聲明接口,在其中聲明了對象所具有的業務方法。
ConcreteProduct(具體產品):它定義具體工廠生產的具體對象。
下面還是先看一個具體實例。
實例:
現在需要做一款跨平臺的游戲,需要兼容Android,Ios,Wp三個移動操作系統,該游戲針對每個系統都設計了一套操作控制器(OperationController)和界面控制器(UIController),下面通過抽閑工廠方式完成這款游戲的架構設計。
由題可知,游戲里邊的各個平臺的UIController和OperationController應該是我們最終生產的具體產品。所以新建兩個抽象產品接口。
抽象操作控制器
public interface OperationController {void control(); }抽象界面控制器
public interface UIController {void display(); }然后完成各個系統平臺的具體操作控制器和界面控制器
Android
Ios
public class IosOperationController implements OperationController {@Overridepublic void control() {System.out.println("IosOperationController");} }public class IosUIController implements UIController {@Overridepublic void display() {System.out.println("IosInterfaceController");} }Wp
public class WpOperationController implements OperationController {@Overridepublic void control() {System.out.println("WpOperationController");} } public class WpUIController implements UIController {@Overridepublic void display() {System.out.println("WpInterfaceController");} }下面定義一個抽象工廠創建OperationController和UIController
public interface SystemFactory {public OperationController createOperationController();public UIController createInterfaceController(); }在各平臺具體的工廠類中完成操作控制器和界面控制器的創建過程
Android
public class AndroidFactory implements SystemFactory {@Overridepublic OperationController createOperationController() {return new AndroidOperationController();}@Overridepublic UIController createInterfaceController() {return new AndroidUIController();} }Ios
public class IosFactory implements SystemFactory {@Overridepublic OperationController createOperationController() {return new IosOperationController();}@Overridepublic UIController createInterfaceController() {return new IosUIController();} }Wp
public class WpFactory implements SystemFactory {@Overridepublic OperationController createOperationController() {return new WpOperationController();}@Overridepublic UIController createInterfaceController() {return new WpUIController();} }客戶端調用:
SystemFactory mFactory;UIController interfaceController;OperationController operationController;//AndroidmFactory=new AndroidFactory();//IosmFactory=new IosFactory();//WpmFactory=new WpFactory();interfaceController=mFactory.createInterfaceController();operationController=mFactory.createOperationController();interfaceController.display();operationController.control();針對不同平臺只通過創建不同的工廠對象就完成了操作和UI控制器的創建。小伙伴們可以對比一下,如果這個游戲使用工廠方法模式搭建需要創建多少個工廠類呢?下面總結一下抽象工廠的適用場景。
適用場景:
(1)和工廠方法一樣客戶端不需要知道它所創建的對象的類。
(2)需要一組對象共同完成某種功能時。并且可能存在多組對象完成不同功能的情況。
(3)系統結構穩定,不會頻繁的增加對象。(因為一旦增加就需要修改原有代碼,不符合開閉原則)
什么是裝飾者模式?
1、定義
裝飾模式(Decorator Pattern) :動態地給一個對象增加一些額外的職責(Responsibility),就增加對象功能來說,裝飾模式比生成子類實現更為靈活。
tips: 要使用裝飾者模式,需要滿足以下設計原則:
1、多用組合,少用繼承
2、開放-關閉原則:類應該對拓展開放,對修改關閉
裝飾者模式的結構:
07.png從上圖中可以看出,裝飾模式一共有四部分組成:
1、抽象組件角色(Component):定義一個對象接口,以規范準備接受附加責任的對象,即可以給這些對象動態地添加職責。
2、具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增加功能的類。可以給這個類的對象添加一些職責。
3、抽象裝飾器(Decorator):維持一個指向構件Component對象的實例,并定義一個與抽象組件角色Component接口一致的接口。
4、具體裝飾器角色(ConcreteDecorator):向組件添加職責。
源代碼
抽象構件角色“齊天大圣”接口定義了一個move()方法,這是所有的具體構件類和裝飾類必須實現的。
//大圣的尊號 public interface TheGreatestSage {public void move(); }具體構件角色“大圣本尊”猢猻類
public class Monkey implements TheGreatestSage {@Overridepublic void move() {//代碼System.out.println("Monkey Move");}}抽象裝飾角色“七十二變”
public class Change implements TheGreatestSage {private TheGreatestSage sage;public Change(TheGreatestSage sage){this.sage = sage;}@Overridepublic void move() {// 代碼sage.move();}}具體裝飾角色“魚兒”
public class Fish extends Change {public Fish(TheGreatestSage sage) {super(sage);}@Overridepublic void move() {// 代碼System.out.println("Fish Move");} }具體裝飾角色“鳥兒”
public class Bird extends Change {public Bird(TheGreatestSage sage) {super(sage);}@Overridepublic void move() {// 代碼System.out.println("Bird Move");} }客戶端類
public class Client {public static void main(String[] args) {TheGreatestSage sage = new Monkey();// 第一種寫法TheGreatestSage bird = new Bird(sage);TheGreatestSage fish = new Fish(bird);// 第二種寫法//TheGreatestSage fish = new Fish(new Bird(sage));fish.move(); }}“大圣本尊”是ConcreteComponent類,而“鳥兒”、“魚兒”是裝飾類。要裝飾的是“大圣本尊”,也即“猢猻”實例。
上面的例子中,系統把大圣從一只猢猻裝飾成了一只鳥兒(把鳥兒的功能加到了猢猻身上),然后又把鳥兒裝飾成了一條魚兒(把魚兒的功能加到了猢猻+鳥兒身上,得到了猢猻+鳥兒+魚兒)。
裝飾模式的優點:
- 裝飾模式與繼承關系的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
- 可以通過一種動態的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的裝飾器,從而實現不同的行為。
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一對象,得到功能更為強大的對象。
- 具體構件類與具體裝飾類可以獨立變化,用戶可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有代碼無須改變,符合“開閉原則”
裝飾模式的缺點:
- 使用裝飾模式進行系統設計時將產生很多小對象,這些對象的區別在于它們之間相互連接的方式有所不同,而不是它們的類或者屬性值有所不同,同時還將產生很多具體裝飾類。這些裝飾類和小對象的產生將增加系統的復雜度,加大學習與理解的難度。
- 這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易于出錯,排錯也很困難,對于多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為煩瑣。
三:如何減少換頁錯誤?
首先我們需要了解什么是換頁錯誤:換頁錯誤又稱缺頁錯誤
起因是一道筆試題,如下:
如何減少換頁錯誤?()
1,進程傾向于占用CPU
2,訪問局部性(localilty of reference)滿足進程要求
3,進程傾向于占用I/O
4,使用基于最短剩余時間(shortest remaining time)的調度機制
5,減少頁大小
1 最短剩余時間優先算法
最短剩余時間優先(Shortest Remaining Time Next,SRTN)調度算法多用于剝奪式的調度中。 在進程調度中,每次調度時,系統把處理機分配給就緒隊列中運行完所需時間最短的進程。 最短剩余時間優先算法也可用于不剝奪式調度方式中,此時退化為短作業優先算法。
2 局部性原理
局部性原理是一個經典的原理,分為時間局部性和空間局部性,意思是應用一旦訪問了一個空間的數據,則這個空間中的相鄰區域的內容也很可能被訪問,一旦訪問了某一段代碼,則其周圍的代碼也很可能被訪問。局部性原理的運用就是根據這個,把可能訪問的數據和代碼都加在到內存中,以后訪問就不用加載了(因為主要的消耗在IO端)
4選項不一定能減少換頁錯誤。進程頻繁切換不一定意味著換頁錯誤多,可以考慮如下兩種情況:
1、如果分配的幀很多,可以裝下所有的頁,根本就不會置換頁表。
2、采用合理的置換策略,即使進程頻繁切換,也可能可以減少換頁錯誤。
所以換頁錯誤和進程切不切換沒有確切的聯系。
所以應該選第二個選項:采用局部性原理。
四:同一進程下的線程可以共享什么?
同一進程下的線程可以共享()
- stack
- data section
- register set
- thread ID
出自筆試題:答案:B
線程共享的環境包括:進程代碼段、進程的公有數據(利用這些共享的數據,線程很容易的實現相互之間的通訊)、進程打開的文件描述符、信號的處理器、進程的當前目錄和進程用戶ID與進程組ID。
tips:同一個進程的多個線程有自己獨立的堆棧和局部變量
A.棧(私有) B.數據段,線程共享 C.寄存器組 D.線程ID
設計模式中屬于結構模式的有哪些?
答:設計模式主要分三個類型:創建型、結構型和行為型。
結構型設計模式是從程序的結構上解決模塊之間的耦合問題(好像是句廢話),GoF23種設計模式中結構型設計模式有7種,分別是:Adapter適配器模式、Bridge橋接模式、Composite組合模式、Decorator裝飾模式、Facade外觀模式、Flyweight享元模式和Proxy代理模式。下面分別總結一下這幾種模式:
設計模式 GoF的描述 我的理解
Adapter適配器模式 將一個類的接口轉換成客戶希望的另一個接口。Adapter模式使得原本由于接口不兼容而不能一起工作的類可以一起工作 轉換接口,由于應用環境的變化,常常需要將“一些現存的對象”放在新的環境中應用,但是,新環境要求的接口是現存對象所不滿足的,此時我們可以通過添加一層Adapter對現有的對象加入一些接口,使其適應新的應用環境。
Bridge橋接模式 將抽象部分與實現部分分離,使他們可以獨立的變化 分離接口(抽象)與其實現,當某個類型具有兩個或兩個以上的緯度變化(或者說是變化點),通過以繼承接口的方式隔離變化,以減少因變化帶來的代碼的修改量。
Composite組合模式 將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite模式使得客戶對單個對象和組合對象的使用具有一致性 解決客戶程序與復雜對象容器的解耦,一類具有“容器特征”的對象——即他們在充當對象的同時,又是其他對象的容器的情況,通過繼承統一的接口,我們可以將容器對象及其子對象看成同一類對象使用,以減少對象使用中的復雜度。
Decorator裝飾模式 動態的給一個對象添加一些額外的職責。就增加功能而言,Decorator模式比生成子類更為靈活 在穩定接口的前提下為對象擴展功能,主要是解決用繼承的方式為對象擴展大量功能而造成的子對象數量膨脹的問題
Facade外觀模式 為子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用 簡化接口,對于復雜子系統或子對象調用的封裝。從客戶程序角度看,只能看見Facade提供的接口。換句話說是對子對象調用的封裝,將客戶程序對子對象的調用與子對象的變化分離。
Flyweight享元模式 運用共享技術有效的支持大量細粒度的對象 主要是解決由于相同對象數量過大而造成系統內存開銷過大的問題。實際上是相同的對象引用指向同一個對象空間。在使用Flyweight模式前要做一個評估,如果使用不當會適得其反
Proxy代理模式 為其他對象提供一種代理以控制這個對象的訪問 解決直接訪問某些對象是出現的問題,如:訪問遠程的對象
在學習的過程中感覺,從代碼的角度看Adapter適配器模式和Proxy代理模式有些類似,Adapter適配器模式是解決現有對象在新的環境中的不足,而Proxy代理模式是解決直接訪問對象時出現的問題
CISC 指令和 RISC 指令
RISC(精簡指令集計算機)和CISC(復雜指令集計算機)是當前CPU的兩種架構。它們的區別在于不同的CPU設計理念和方法。
復雜指令集CPU內部為將較復雜的指令譯碼,也就是指令較長,分成幾個微指令去執行,正是如此開發程序比較容易(指令多的緣故),但是由于指令復雜,執行工作效率較差,處理數據速度較慢
(1) 指令系統:RISC 設計者把主要精力放在那些經常使用的指令上,盡量使它們具有簡單高效的特色。對不常用的功能,常通過組合指令來完成。因此,在RISC 機器上實現特殊功能時,效率可能較低。但可以利用流水技術和超標量技術加以改進和彌補。而CISC 計算機的指令系統比較豐富,有專用指令來完成特定的功能。因此,處理特殊任務效率較高。
(2) 存儲器操作:RISC 對存儲器操作有限制,使控制簡單化;而CISC 機器的存儲器操作指令多,操作直接。
(3) 程序:RISC 匯編語言程序一般需要較大的內存空間,實現特殊功能時程序復雜,不易設計;而CISC 匯編語言程序編程相對簡單,科學計算及復雜操作的程序設計相對容易,效率較高。
(4) 中斷:RISC 機器在一條指令執行的適當地方可以響應中斷;而CISC 機器是在一條指令執行結束后響應中斷。
(5) CPU:RISC CPU 包含有較少的單元電路,因而面積小、功耗低;而CISC CPU 包含有豐富的電路單元,因而功能強、面積大、功耗大。
(6) 設計周期:RISC 微處理器結構簡單,布局緊湊,設計周期短,且易于采用最新技術;CISC 微處理器結構復雜,設計周期長。
(7) 用戶使用:RISC 微處理器結構簡單,指令規整,性能容易把握,易學易用;CISC微處理器結構復雜,功能強大,實現特殊功能容易。
(8) 應用范圍:由于RISC 指令系統的確定與特定的應用領域有關,故RISC 機器更適合于專用機;而CISC 機器則更適合于通用機。
排序算法中初始數據順序對于算法性能無影響的是?
堆排序的數據順序對于算法性能沒有影響,其他類似于 冒泡,插入,選擇都有影響。
總結:說實話有些無力吐槽的感覺,很多知識點確實課都學過但是基本都屬于不聽或者聽了也不常用記不得的那種,但是筆試就是考這種題目。很偏冷門。無奈,但是沒辦法,我們只能隨波逐流而已。所以就是不斷學習,不斷總結,相信更好的明天在等著你。終有一天你會耀眼。
愿我們成為真實的自己。
總結
以上是生活随笔為你收集整理的我要做 Android 之面笔试总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Class.getResourceAsS
- 下一篇: 【随笔】express中间件系统的基本实