天天看點

我要做 Android 之面筆試總結

說說什麼是工廠模式 ps:之前隻是單純了解過工廠模式,不知道其實有三種工廠模式

一:工廠模式

工廠模式就有三種,它們分别是簡單工廠模式(并不在23中模式之中),工廠方法模式以及抽象工廠模式,其中我們通常所說的工廠模式指的是工廠方法模式,工廠方法模式是日常開發中使用頻率最高的一種設計模式。

簡單工廠模式

簡單工廠模式其實并不算是一種設計模式,更多的時候是一種程式設計習慣。

定義:

  定義一個工廠類,根據傳入的參數不同傳回不同的執行個體,被建立的執行個體具有共同的父類或接口。

适用場景:

  其實由定義也大概能推測出其使用場景,首先由于隻有一個工廠類,是以工廠類中建立的對象不能太多,否則工廠類的業務邏輯就太複雜了,其次由于工廠類封裝了對象的建立過程,是以用戶端應該不關心對象的建立。總結一下适用場景:

  (1)需要建立的對象較少。

  (2)用戶端不關心對象的建立過程。

以上就是簡單工廠模式簡單工廠模式的适用場景,下面看一個具體的執行個體。

執行個體:

  建立一個可以繪制不同形狀的繪圖工具,可以繪制圓形,正方形,三角形,每個圖形都會有一個draw()方法用于繪圖,不看代碼先考慮一下如何通過該模式設計完成此功能。

由題可知圓形,正方形,三角形都屬于一種圖形,并且都具有draw方法,是以首先可以定義一個接口或者抽象類,作為這三個圖像的公共父類,并在其中聲明一個公共的draw方法。

public interface Shape {
    void draw();
}
           

這裡定義成抽象類也是可以的,隻不過接口是更高一級的抽象,是以習慣定義成接口,而且接口支援多實作,友善以後擴充。

下面就是編寫具體的圖形,每種圖形都實作Shape 接口

圓形

public class CircleShape implements Shape {

    public CircleShape() {
        System.out.println(  "CircleShape: created");
    }

    @Override
    public void draw() {
        System.out.println(  "draw: CircleShape");
    }

}
           

正方形

public class RectShape implements Shape {
    public RectShape() {
       System.out.println(  "RectShape: created");
    }

    @Override
    public void draw() {
       System.out.println(  "draw: RectShape");
    }

}
           

三角形

public class TriangleShape implements Shape {

    public TriangleShape() {
        System.out.println(  "TriangleShape: created");
    }

    @Override
    public 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 {
    @Override
    public void read() {
        System.out.print("read jpg");
    }
}
           

Png圖檔加載器

public class PngReader implements Reader {
    @Override
    public void read() {
        System.out.print("read png");
    }
}
           

Gif圖檔加載器

public class GifReader implements Reader {
    @Override
    public void read() {
        System.out.print("read gif");
    }
}
           

現在我們按照定義所說定義一個抽象的工廠接口ReaderFactory

public interface ReaderFactory {
    Reader getReader();
}
           

裡面有一個getReader()方法傳回我們的Reader 類,接下來我們把上面定義好的每個圖檔加載器都提供一個工廠類,這些工廠類實作了ReaderFactory 。

Jpg加載器工廠

public class JpgReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new JpgReader();
    }
}
           

Png加載器工廠

public class PngReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new PngReader();
    }
}
           

Gif加載器工廠

public class GifReaderFactory implements ReaderFactory {
    @Override
    public 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

public class AndroidOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("AndroidOperationController");
    }
}

public class AndroidUIController implements UIController {
    @Override
    public void display() {
        System.out.println("AndroidInterfaceController");
    }
}
           

Ios

public class IosOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("IosOperationController");
    }
}

public class IosUIController implements UIController {
    @Override
    public void display() {
        System.out.println("IosInterfaceController");
    }
}
           

Wp

public class WpOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("WpOperationController");
    }
}
public class WpUIController implements UIController {
    @Override
    public void display() {
        System.out.println("WpInterfaceController");
    }
}
           

下面定義一個抽象工廠建立OperationController和UIController

public interface SystemFactory {
    public OperationController createOperationController();
    public UIController createInterfaceController();
}
           

在各平台具體的工廠類中完成操作控制器和界面控制器的建立過程

public class AndroidFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new AndroidOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new AndroidUIController();
    }
}
           
public class IosFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new IosOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new IosUIController();
    }
}
           
public class WpFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new WpOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new WpUIController();
    }
}
           

用戶端調用:

SystemFactory mFactory;
    UIController interfaceController;
    OperationController operationController;

    //Android
    mFactory=new AndroidFactory();
    //Ios
    mFactory=new IosFactory();
    //Wp
    mFactory=new WpFactory();

    interfaceController=mFactory.createInterfaceController();
    operationController=mFactory.createOperationController();
    interfaceController.display();
    operationController.control();
           

針對不同平台隻通過建立不同的工廠對象就完成了操作和UI控制器的建立。小夥伴們可以對比一下,如果這個遊戲使用工廠方法模式搭建需要建立多少個工廠類呢?下面總結一下抽象工廠的适用場景。

(1)和工廠方法一樣用戶端不需要知道它所建立的對象的類。

(2)需要一組對象共同完成某種功能時。并且可能存在多組對象完成不同功能的情況。

(3)系統結構穩定,不會頻繁的增加對象。(因為一旦增加就需要修改原有代碼,不符合開閉原則)

什麼是裝飾者模式?

1、定義

裝飾模式(Decorator Pattern) :動态地給一個對象增加一些額外的職責(Responsibility),就增加對象功能來說,裝飾模式比生成子類實作更為靈活。

tips: 要使用裝飾者模式,需要滿足以下設計原則:

1、多用組合,少用繼承

2、開放-關閉原則:類應該對拓展開放,對修改關閉

裝飾者模式的結構:

我要做 Android 之面筆試總結

07.png

從上圖中可以看出,裝飾模式一共有四部分組成:

1、抽象元件角色(Component):定義一個對象接口,以規範準備接受附加責任的對象,即可以給這些對象動态地添加職責。

2、具體元件角色(ConcreteComponent) :被裝飾者,定義一個将要被裝飾增加功能的類。可以給這個類的對象添加一些職責。

3、抽象裝飾器(Decorator):維持一個指向構件Component對象的執行個體,并定義一個與抽象元件角色Component接口一緻的接口。

4、具體裝飾器角色(ConcreteDecorator):向元件添加職責。

源代碼

抽象構件角色“齊天大聖”接口定義了一個move()方法,這是所有的具體構件類和裝飾類必須實作的。

//大聖的尊号
public interface TheGreatestSage {
    
    public void move();
}
           

具體構件角色“大聖本尊”猢狲類

public class Monkey implements TheGreatestSage {

    @Override
    public void move() {
        //代碼
        System.out.println("Monkey Move");
    }

}
           

抽象裝飾角色“七十二變”

public class Change implements TheGreatestSage {
    private TheGreatestSage sage;
    
    public Change(TheGreatestSage sage){
        this.sage = sage;
    }
    @Override
    public void move() {
        // 代碼
        sage.move();
    }

}
           

具體裝飾角色“魚兒”

public class Fish extends Change {
    
    public Fish(TheGreatestSage sage) {
        super(sage);
    }

    @Override
    public void move() {
        // 代碼
        System.out.println("Fish Move");
    }
}

           

具體裝飾角色“鳥兒”

public class Bird extends Change {
    
    public Bird(TheGreatestSage sage) {
        super(sage);
    }

    @Override
    public 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 機器則更适合于通用機。

排序算法中初始資料順序對于算法性能無影響的是?

堆排序的資料順序對于算法性能沒有影響,其他類似于 冒泡,插入,選擇都有影響。

總結:說實話有些無力吐槽的感覺,很多知識點确實課都學過但是基本都屬于不聽或者聽了也不常用記不得的那種,但是筆試就是考這種題目。很偏冷門。無奈,但是沒辦法,我們隻能随波逐流而已。是以就是不斷學習,不斷總結,相信更好的明天在等着你。終有一天你會耀眼。

願我們成為真實的自己。