軟件開發工程師面試題之三

、簡述觀察者模式。
一個被觀察者物件管理所有觀察它的物件,當其自身狀態發生改變時,對所有觀察者主動發出通知。
二、bridge模式
將兩個角色之間的繼承關係改爲聚合關係,就是將它們之間的強關聯改換成爲弱關聯。因此,橋樑模式中的所謂脫耦,就是指在一個軟件系統的抽象化和實現化之間使用組合/聚合關係而不是繼承關係,從而使兩者可以相對獨立地變化。這就是橋樑模式的用意。
三、工廠模式。
工廠模式主要是爲創建對象提供過渡接口,以便將創建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的。
簡單工廠模式:

簡單工廠模式又稱靜態工廠方法模式。重命名上就可以看出這個模式一定很簡單。它存在的目的很簡單:定義一個用於創建對象的接口。
       
先來看看它的組成:

1)        工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實現。

2)        抽象產品角色:它一般是具體產品繼承的父類或者實現的接口。在java中由接口或者抽象類來實現。

3)        具體產品角色:工廠類所創建的對象就是此角色的實例。在java中由一個具體類實現。


工廠方法模式:

工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。這樣在簡單工廠模式裏集中在工廠方法上的壓力可以由工廠方法模式裏不同的工廠子類來分擔。

你應該大致猜出了工廠方法模式的結構,來看下它的組成:

1)        抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。

2)        具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。

3)        抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。

4)        具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。

用類圖來清晰的表示下的它們之間的關係:


抽象工廠模式:

可以說,抽象工廠模式和工廠方法模式的區別就在於需要創建對象的複雜程度上。而且抽象工廠模式是三個裏面最爲抽象、最具一般性的。

抽象工廠模式的用意爲:給客戶端提供一個接口,可以創建多個產品族中的產品對象

而且使用抽象工廠模式還要滿足一下條件:

1)        系統中有多個產品族,而系統一次只可能消費其中一族產品。

2)        同屬於同一個產品族的產品以其使用。

來看看抽象工廠模式的各個角色(和工廠方法的如出一轍):

1)        抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。

2)        具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。在java中它由具體的類來實現。

3)        抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。

4)        具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。


四、socket編程。


Socket,ServerSocket.

客戶端Socket步驟:

1,創建一個Socket實例:構造函數向指定的遠程主機和端口建立tcp鏈接;

2,通過socket的i/o流與服務器端通行;

3,通過Socket類的close方法關閉連接。


服務器端執行如下步驟:

1,創建ServerSocket實例並指定監聽本地端口,用來監聽客戶端發送的tcp連接請求;

2,重複執行:

1,通過accept方法獲取客戶端連接,並通過其返回值創建一個socket實例;

2,爲返回的socket實例開啓一個新的線程,並使用放回的socket的i/o流與客戶端通信;

3,通過socket類的close方法關閉與客戶端連接。

實例代碼:

客戶端:

package zyb.org.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class Client1 {
public static void main(String[] args) throws IOException {
//客戶端請求與本機在20006端口建立TCP連接
Socket client = new Socket("127.0.0.1", 20006);
client.setSoTimeout(10000);
//獲取鍵盤輸入
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//獲取Socket的輸出流,用來發送數據到服務端
PrintStream out = new PrintStream(client.getOutputStream());
//獲取Socket的輸入流,用來接收從服務端發送過來的數據
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
boolean flag = true;
while(flag){
System.out.print("輸入信息:");
String str = input.readLine();
//發送數據到服務端
out.println(str);
if("bye".equals(str)){
flag = false;
}else{
try{
//從服務器端接收數據有個時間限制(系統自設,也可以自己設置),超過了這個時間,便會拋出該異常
String echo = buf.readLine();
System.out.println(echo);
}catch(SocketTimeoutException e){
System.out.println("Time out, No response");
}
}
}
input.close();
if(client != null){
//如果構造函數建立起了連接,則關閉套接字,如果沒有建立起連接,自然不用關閉
client.close(); //只關閉socket,其關聯的輸入輸出流也會被關閉
}
}
}

服務器:

package zyb.org.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class Client1 {
public static void main(String[] args) throws IOException {
//客戶端請求與本機在20006端口建立TCP連接
Socket client = new Socket("127.0.0.1", 20006);
client.setSoTimeout(10000);
//獲取鍵盤輸入
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//獲取Socket的輸出流,用來發送數據到服務端
PrintStream out = new PrintStream(client.getOutputStream());
//獲取Socket的輸入流,用來接收從服務端發送過來的數據
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
boolean flag = true;
while(flag){
System.out.print("輸入信息:");
String str = input.readLine();
//發送數據到服務端
out.println(str);
if("bye".equals(str)){
flag = false;
}else{
try{
//從服務器端接收數據有個時間限制(系統自設,也可以自己設置),超過了這個時間,便會拋出該異常
String echo = buf.readLine();
System.out.println(echo);
}catch(SocketTimeoutException e){
System.out.println("Time out, No response");
}
}
}
input.close();
if(client != null){
//如果構造函數建立起了連接,則關閉套接字,如果沒有建立起連接,自然不用關閉
client.close(); //只關閉socket,其關聯的輸入輸出流也會被關閉
}
}
}

五、TCP連接過程

1,三次握手

客戶端往服務器發送syn報文,seq = i

服務器迴應ack = i+1,同時發送syn報文,seq = j。

客戶端發送ack = j +1可以發送報文。

2,四次揮手

客戶端發送fin,用來關閉和服務器的數據連接。

服務器迴應ack。

服務器關閉客戶端連接,向客戶端發送fin。

客戶端發回ack報文確認。


1、 爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?
這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章