天天看點

黑馬程式員——設計模式

------- android教育訓練、java教育訓練、期待與您交流! ----------

    設計模式概述:         •設計模式這個術語是由Erich Gamma等人在1990年代從建築設計領域引入到計算機科學的。它是對軟體設計中普        遍存在(反複出現)的各種問題,所提出的解決方案。         •設計模式并不直接用來完成代碼的編寫,而是描述在各種不同情況下,要怎麼解決問題的一種方案。面向對象設        計模式通常以類或對象來描述其中的關系和互相作用,但不涉及用來完成應用程式的特定類或對象。設計模式能使        不穩定依賴于相對穩定、具體依賴于相對抽象,避免會引起麻煩的緊耦合,以增強軟體設計面對并适應變化的能            力。     設計模式分類:         •建立型模式,共五種:             -工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。         •結構型模式,共七種:             -擴充卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。         •行為型模式,共十一種:             -政策模式、模闆方法模式、觀察者模式、疊代子模式、責任鍊模式、指令模式、備忘錄模式、狀态模式、訪               問者模式、中介者模式、解釋器模式。         •課上遇到的設計模式:

            (1)、單例設計模式

              在整個應用中有且僅有一個執行個體對象

              典型案例:

             RunTime

/*
 * 定義單例Person
 * 
 * 懶漢式單例
 */
public class Person {

	//定義靜态私有的本類型成員變量,并建立對象供方法傳回
	private static Person p;
	
	//私有化構造方法,讓外界無法直接建立對象
	private Person() {
	}

//	//對外提供靜态公共的擷取執行個體方法,不考慮安全,不考慮效率
	public static Person getInstance1() {
		//判斷是否已經有執行個體對象
		if(p==null) {
			//如果沒有對象,才建立
			p = new Person();
		}
		return p;
	}
	
	//對外提供靜态公共的擷取執行個體方法,考慮安全,不考慮效率
	public synchronized static Person getInstance2() {
		//判斷是否已經有執行個體對象
		if(p==null) {
			//如果沒有對象,才建立
			p = new Person();
		}
		return p;
	}
	//對外提供靜态公共的擷取執行個體方法,考慮安全,不考慮效率
	public static Person getInstance3() {
		
		synchronized (Person.class) {
			//判斷是否已經有執行個體對象
			if(p==null) {
				//如果沒有對象,才建立
				p = new Person();
			}
		}
		
		return p;
	}
	//對外提供靜态公共的擷取執行個體方法,考慮安全,考慮效率
	public static Person getInstance4() {
		//為了判斷是否執行同步
		if(p==null) {
			synchronized (Person.class) {
				//為了判斷是否建立對象
				if(p==null) {
					//如果沒有對象,才建立
					p = new Person();
				}
			}
		}
		return p;
	}
}
           
/*
 * 定義單例Person
 * 
 * 餓漢式單例
 */
public class Person {

	//定義靜态私有的本類型成員變量,并建立對象供方法傳回
	private static Person p = new Person();
	
	//私有化構造方法,讓外界無法直接建立對象
	private Person() {
	}

	//對外提供靜态公共的擷取執行個體方法
	public static Person getInstance() {
		return p;
	}
}
           

       (2)、擴充卡設計模式

              将一個類的接口根據使用者的需求,适配成便于使用的類/抽象類

              典型案例:

             GUI監聽器

  以WindowAdapter()為例進行學習:

          WindowListener:用于接收視窗事件的偵聽器接口。

          WindowAdapter: 接收視窗事件的抽象擴充卡類。

          由于WindowListener接口中抽象方法太多,在事件監聽時一般隻使用其中的一個或幾個,為了簡化操作,用         WindowAdapter實作WindowListener接口,但是WindowAdapter中的方法體為空,在使用時,我們隻需要将           用到的方法進行重寫即可,簡化了操作。

//添加監聽器
		//使用擴充卡完成事件監聽
		frame.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
			
		});
           
//添加監聽器
		//使用監聽器接口完成事件監聽
		frame.addWindowListener(new WindowListener() {
			
			@Override
			public void windowOpened(WindowEvent e) {
			}
			
			@Override
			public void windowIconified(WindowEvent e) {
			}
			
			@Override
			public void windowDeiconified(WindowEvent e) {
			}
			
			@Override
			public void windowDeactivated(WindowEvent e) {
			}
			
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
			
			@Override
			public void windowClosed(WindowEvent e) {
			}
			
			@Override
			public void windowActivated(WindowEvent e) {
			}	
		});
           

            (3)、裝飾設計模式

              添加一個修飾類包裹原來的類,在運作時便可以擴充其新的功能

              典型案例:

              高效緩沖IO流

public class MyBufferedReader {

	//定義Reader類型的成員變量,用來接收Reader對象
	private Reader reader;

	public MyBufferedReader(Reader reader) {
		this.reader = reader;
	}
	
	//定義readLine方法
	public String readLine() throws IOException {
		
		//定義變量,用來緩沖每行的内容,讀到一行結束就傳回
		StringBuilder sb = new StringBuilder();
		
		int c;
		while((c=reader.read())!=-1) {
			
			//如果遇到了一行當中的\r,不存到該行中,直接讀取下一個字元
			if(c=='\r') {
				continue;
			}
			
			//如果遇到了一行當中的\n,不存到該行中,直接将該行傳回了
			if(c=='\n') {
				return sb.toString();
			}
			
			//将改行非回車換行的字元加入到該行的緩沖區中
			sb.append((char)c);
		}
		
		//如果跳出了循環,但是緩沖區内有内容,說明最後一行有内容但沒有回車換行,此時傳回該緩沖區内容
		if(sb.length()!=0) {
			return sb.toString();
		}
		
		//如果該行沒有任何内容,就傳回null
		return null;
	}

	public void close() throws IOException {
		reader.close();
	}
}
           

            (4)、工廠設計模式

              使用工廠建立某些類的執行個體對象,進而取代之前自身調用構造new的操作

              典型案例:

              線程池

//使用工廠類調用方法,傳回線程池對象
		ExecutorService threadPool = Executors.newFixedThreadPool(3);
           

            (5)、模闆設計模式

              将一個完整功能分隔成不同步驟,對多個實作類共同的操作使用具體的實作,對多個類的差異操作使用抽象。

每次建立新的視窗時隻需要完善method方法中的代碼即可。

public class Test2 {

	public static void main(String[] args) {
		//建立窗體對象
		Frame frame = new Frame("唐嫣歡迎您!");
		//設定屬性
		before(frame);
		//完成通過滑鼠移動到指定按鈕上時,改變窗體背景色
		method(frame);
		//窗體可見
		after(frame);
	}

	//業務邏輯方法,完成通過滑鼠移動到指定按鈕上時,改變窗體背景色
	private static void method(final Frame frame) {

		//添加元件
		Button btn = new Button("小紅");
		Button btn2 = new Button("小蘭");
		Button btn3 = new Button("大黃");
		
		frame.add(btn);
		frame.add(btn2);
		frame.add(btn3);
		
		// 為按鈕添加滑鼠監聽
		btn.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("我進來了,我臉紅了");
				//設定窗體為紅色
				frame.setBackground(new Color(255, 0, 0));
			}

			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("我又出來了");
				frame.setBackground(new Color(255, 255, 255));
			}
			
		});
		
		// 為按鈕添加滑鼠監聽
		btn2.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("我進來了,我臉藍了");
				//設定窗體為藍色
				frame.setBackground(new Color(0, 0, 255));
			}

			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("我又出來了");
				frame.setBackground(new Color(255, 255, 255));
			}
			
		});
		
		// 為按鈕添加滑鼠監聽
		btn3.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseEntered(MouseEvent e) {
				System.out.println("我進來了,我臉黃了");
				//設定窗體為黃色
				frame.setBackground(new Color(255, 255, 0));
			}

			@Override
			public void mouseExited(MouseEvent e) {
				System.out.println("我又出來了");
				frame.setBackground(new Color(255, 255, 255));
			}
			
		});
		
		
	}

	//為窗體設定基本屬性
	public static void before(Frame frame) {
		
		//設定窗體屬性
		frame.setSize(600,400);
		
		//1366  768  
		int width = frame.getWidth();
		int height = frame.getHeight();
		
		int x = 1366/2 - width/2;
		int y = 768/2 - height/2;
		
		frame.setLocation(x, y);
		
		//設定窗體布局
		frame.setLayout(new FlowLayout());
		
		//完成窗體關閉
		frame.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
			
		});
	}
	
	//為窗體設定基本屬性
	public static void after(Frame frame) {
		
		//讓窗體可見
		frame.setVisible(true);
	}

}