java開發面試問答----設計模式篇

原則

  • 開閉原則:可擴展,不可修改
  • 里氏代換原則:基類能出現的地方子類必定能出現
  • 單一職責原則:一個類應該只有一種職責
  • 依賴倒轉原則:依賴於抽象而不是實現,面向接口編程
  • 接口隔離原則:每一個接口不存在子類用不到的方法
  • 迪米特原則(最少知道):陌生的類不做爲局部變量出如今類中而是直接朋友,直接朋友爲成員變量,方法參數,方法返回值
  • 合成複用原則:儘可能使用合成/聚合,而不是繼承

建立模式

簡單工廠

  • 對須要生成的類進行抽象,即一個工廠類能夠生產出同一接口的不一樣對象

抽象工廠

  • 對須要生成的類和工廠都進行抽象,即同一接口的不一樣工廠類生產出對應的同一接口的不一樣對象

builder模式

  • 當類的屬性大部分可爲空時使用建造者模式,經過一個builder類按需組合出對象

單例模式

  • 餓漢模式:靜態變量,在類初始化時即完成對象的初始化
  • 飽漢模式:在調用生產類方法時才初始化對象,延遲加載
    • 針對多線程問題, 採用雙重鎖;
    • synchronized 保證多線程時只有一個線程能進行初始化即原子性;
    • voliate 保證有序性和可見性,java1.6以後纔出現
    • 什麼是原子性,有序性,可見性?
      • cpu執行命令時爲了提升性能會將內存中的數據讀取到高速緩存中,在高速緩存中計算後再寫回主存,因爲每一個cpu核的高速緩存是不同的,因此多線程時就會出現各類一致性問題
      • 原子性是指一個操做或者連續多個操做要麼執行完要麼不執行
      • 可見性是指當一個線程修改了該參數的值時其餘線程要可以馬上看到該參數的值
      • 有序性是指cpu在執行命令時會發生指令重排序並保證最終一致,但在多線程中指令重排序會引發參數判斷錯誤
public class Demo {
	private final voliate DemoClass demoClass = null;
	
	public static DemoClass getInstance(){
		if (demoClass == null){
			synchronized(DemoClass.class){
				if (demoClass == null){
					demoClass = new DemoClass;
				}
			}
		}
		return demoClass;
	}
}
複製代碼

原型模式

  • 實現Cloneable的接口,能夠經過克隆生產新的對象
  • 深拷貝:對象中的基本類型和引用類型所有都是從新建立的
  • 淺拷貝:對象中的基本類型是從新建立的,引用類型仍是指向原來的對象

結構模式

適配器模式

  • 將某個類的接口轉換成指望的另外一個接口
  • 建立一個適配器類繼承舊類的功能再擴展出新的功能或者直接加工出新功能
public interface DemoA {
	String getA();
}
public class A implements DemoA
public interface DemoB {
	String getA();
	String getB();
}
//類適配器, 具備一樣的方法,接口少變多
public class adapter extends A implements DemoB {
	String getB(){
	}
}
//對象適配器,老接口功能須要重置
pulic class adapter2 implements DemoB{
 	private A a;
 	String getA(){modify(a.getA())}
 	String getB(){}
}
//接口適配器, 僅重置老部分接口功能
public abstract class adapter3 implements DemoB {
	String getA(){}
	String getB(){}
}
public class subAdapter3 extend B3 {
	String getA(){}
}
複製代碼

裝飾器模式

  • 修改原對象的功能而不修改原對象,裝飾器和原對象實現同一種接口,例子:io類
public interface DemoA {
	String getA()
}
public class Old implements DemoA
public class Decorator implements DemoA {
	private Old old;
	public Decorator (Old old){
		this.Old = old;
	}
	String getA() {
		xxxx;
		old.getA()
	}
}
new Decorator(new Decorator(new Old()))
複製代碼

代理模式

  • 經過代理實現行爲,代理模式和裝飾器模式實現基本同樣,惟一區別是代理模式能控制原對象的行爲而裝飾器模式僅修飾原對象的行爲
public class Agent implements DemoA {
	private Old old;
	public Agent (Old old){
		this.Old = old;
	}
	String getA() {
		if (xxx) {
			old.getA()			
		}
	}
}
new Agent(new Old())
複製代碼

外觀模式

  • 組合多個類的同一種方法, 解決類之間的依賴關係
public class A {
	String start(){}
}
public class B {
	String start(){}
}
public class Facade {
	String start(){
		A.start()
		B.start()
	}
}
複製代碼

橋接模式

  • 當一個類有多個維度變換時, 使用橋接模式模式進行維度間的解耦, 將繼承關係轉換成聚合關聯關係
public abstract class Shape{
   private Color color
	public void setColor(Color color){
		color = color;
	}
	public abstract void draw();
}
public class Circle extends Shape {
	public void draw (){
		color.paint(this)
	}
}
public class Square extends Shape {
	public void draw (){
		color.paint(this)
	}
}
public interface Color {
	void paint (Shape shape)
}
public class Red implements Color
public class Black implements Color
Circle.setColor(new Red())
Circle.draw()

複製代碼

組合模式

  • 專門處理樹形結構, 好比文件夾中有文件夾也有文件, 在總體與部分的層次結構中但願忽略總體與部分的差別
public abstract class TreeNode {
	void add(TreeNode treeNode){}
	void delete(TreeNode treeNode){}
	void getName(){}
	void operation(){}
}
public class File extends TreeNode {
	void getName(){}
	void operation(){}
}
public class Dir extends TreeNode {
   private List<TreeNode> nodes = new ArrayList<>() 
	void add (TreeNode treeNode){}
	void delete (TreeNode treeNode){}
	void getName(){}
	void operation(){
		for (TreeNode node : nodes){
			node.operation()
		}
	}
}
複製代碼

享元模式

  • 共享對象, 例子:線程池
public class ConnectPool {
	private final Vector<Connect> pool = new Vector<Connect>(size)
	
	public synchronized static Connect getConnect(){
		if (pool > 0){
			Connect c = pool.get(0);
			pool.remove(c);
			return c;
		} else {
			Connect c = new Connect;
			pool.add(c);
			return c;
		}
	}
}
複製代碼

行爲模式

父類和子類

策略模式

  • 封裝算法行爲, 同一抽象類有多個子類須要選擇,子類裏面封裝的是不一樣的算法
  • 和簡單工廠模式的區別,簡單工廠模式封裝了選擇過程,而策略模式返回的是單個的策略,選擇過程須要本身實現,工廠模式是黑盒,策略模式是白盒

模板方法模式

  • 抽象類製做模板實現共同的步驟,子類根據須要重寫抽象類的行爲

兩個類

觀察者模式

  • 一個對象變化時,通知依賴該對象的對象變化,該對象管理全部的觀察者,即通知行爲
public class Pub {
	private Vector<Observer> observers = new Vector<>();
	public void add(Observer ob){
		observers.add(ob)
	}
	public void remove(Observer ob){
		observers.remove(ob)
	}
	public void operation(){
	   xxxx;
		notify();
	}
	private void notify(){
		Enumeration<Observer> obs = observers.elements();
		for (Observer ob : obs){
			ob.update()
		}
	}
	
}
public class Sub{
	public void update()
}
複製代碼

迭代器模式

  • 屏蔽集合底層的實現,使用迭代器統一遍歷行爲
public class Collection {
	Object[] ts;
	public Iterator iterator(){
		return new Iterator(this)
	}
	public Object get(int i){
		return ts[i]
	}
	public int size(){
		return ts.length
	}
}
public class Iterator {
	private int cursor = -1;
	private Collection demos;
	public Iterator(Collection collection){
		this.demos = collection
	}
	public bool hasNext() {
		if (cursor < demos.size - 1){
			return true;
		}
		return false;
	}
	public Demo next(){
	   if (cursor < demos.size() - 1){
			cursor = cursor + 1;	   
	   }
		return demos.get(cursor);
	}
}
複製代碼

命令模式

  • 實現命令發佈者和命令接受者的解耦,是對命令的抽象,有利於擴展和控制命令
public class General {
	private Command command
	public void send(){
		command.exec()
	}
}
public class Command {
	private Soldier soldier
	public void exec(){
		soldier.action()
	}

}
public class Soldier {
	public void action()
}
複製代碼

責任鏈模式

  • 請求發送者不用在意命令在哪一步執行, 能夠動態控制鏈中的實現
  • servlet的filter功能保持了一個filter集合
  • dubbo的filter功能是使用鏈表實現,每一鏈保持後一鏈的信息,最後一個是final

類的狀態

備忘錄模式

  • 保持對象的某個狀態,在必要時候進行恢復,如遊戲存檔,control+z
  • 發起人:建立備忘錄,保存狀態到備忘錄,從備忘錄恢復狀態
  • 備忘錄管理者:存檔備忘錄,提出備忘錄
  • 備忘錄:記錄發起人的狀態

狀態模式

  • 經過改變狀態改變行爲,將與狀態有關的行爲放到狀態類中實現,如qq的隱身不可見上線可見
  • 狀態模式的實現和策略模式徹底同樣,不一樣點在於策略模式是讓用戶本身選擇何種算法,而狀態模式能夠自動切換狀態
public class WaterDispenser {
	private int capacity = 20
	private State state
	public Water press(){
		capacity --;
		if (capacity <= 0) {
			state = new Nullstate()
		}
		return state.press()
	}
}
public interface State {
	Water press()
}
public class NullState implements State {
	public Water press () {
		return null
	}
}
public class FullState implements State {
	public Water press () {
		return new Water()
	}
}
WaterDispenser waterDispenser = new WaterDispenser(new Fullstate)
waterDispenser.press()
複製代碼

中間類

訪問者模式

  • 若是對象結構穩定,而要不修改對象的狀況下修改操做就可使用訪問者模式
  • 如帳單系統,帳單對象只有收入和支出,而針對不一樣的角色須要不一樣的統計手段

中介模式

  • 用一箇中介對象封裝多個對象間的交互,減小對象間的耦合
  • 中介模式和代理模式:代理模式是代理單個對象的行爲,中介模式是管理多個對象間的行爲
  • 中介模式和外觀模式:外觀模式的子系統不知道外觀類的存在,而中介模式中同事類知道中介類的存在
public abstract class User {
	void buyHouse()
	void sellHouse()
}
public class Buyer implements User {
	private Intermediary intermediary
	public void buyHouse () {
		intermediary.buyHouse()
	}
	public void call(String message) {}
}
public class Seller implements User {
	private Intermediary intermediary
	public void sellHouse () {
		intermediary.sellHouse()
	}
	public void call(String message) {}	
}
public class Intermediary implements User {
	private Buyer buyer;
	private Seller seller;
	public void buyHouse() {
		seller.call("賣嗎")
	}
	public void sellHouse()	{
		buyer.call("買嗎")
	}
}

複製代碼

解釋器模式

  • 用於sql和表達式解析,用解釋器對象封裝兩種語言間的對應關係,如+-的執行
相關文章
相關標籤/搜索