常用設計模式的簡單描述

這篇文章主要介紹一些常用的設計模式,寄希望通過簡單的幾句代碼能夠一眼看出該設計模式的本質和精髓。(下面的編程語言爲Java語言僞代碼)


1. 觀察者模式

現實例子:找工作過程中,當多個應聘者想跟蹤一家單位招聘信息的變化,無需飯不吃、覺不睡時時刻刻的關注着,只需要把你的簡歷投遞過去,把郵箱告訴人家單位就行了,招聘信息有變化時會主動告訴你的,在這個期間,你該吃飯的吃飯、該睡覺的睡覺。

主題(如招聘單位)

public interface Subject {
	void addObserver(Observer o);
	void deleteObserver(Observer o);
	void notifyObservers();
}
觀察者應聘學生)

public interface Observer {
	void seekEmail();
}
具體主題騰訊公司)

public class TengXun implements Subject {

	@Override
	public void addObserver(Observer o) { //應聘者發送郵件了
		list.add(o);
	}

	@Override
	public void deleteObserver(Observer o) { //刪除郵件
		list.delete(o);
	}

	@Override
	public void notifyObservers() { //通知所有求職者看Email
		for(int i=0; i<list.size(); i++) {
			list.get(i).seekEmail();
		}
	}
}
主題觀察者李四)

public class UniversityStudent implements Observer {
	@Override
	public void seekEmail() {
		doSomething();
	}
}

2. 裝飾模式

具體例子:JDK中的java.io包中的類就使用了裝飾模式,如Reader是一個抽象類,是字符輸入流,相當於裝飾模式中的抽象組件(Component);FileReader類相當於裝飾模式中的具體組件(ConcreteComponent);而BufferedReader相當於裝飾模式中的裝飾(Decorator)。

抽象組件(如java.io.Reader)

public abstract class Bird {
	public abstract int fly();
}
具體組件(如java.io.FileReader)

public class Sparrow extends Bird {
	@Override
	public int fly() {
		return 100; //飛100米
	}
}
裝飾

裝飾不但要繼承抽象組件,而且內部還有一個抽象組件的成員變量

public abstract class Decorator extends Bird {
	//裝飾不但要繼承抽象組件,而且內部還有一個抽象組件的成員變量
	Bird bird;

	public Decorator() {}
	public Decorator(Bird bird) {
		super();
		this.bird = bird;
	}
}
具體裝飾(如java.io.BufferedReader)

public class SparrowDecorator extends Decorator {
	public SparrowDecorator(Bird sparrow) {
		super(sparrow);
	}

	@Override
	public int fly() {
		return bird.fly() + 50; //多飛50米
	}
}

測試運行

下面例子中,“小鳥”被裝飾了兩次,從可以飛100米,到可以飛150米,到可以飛200米。

public class Application {
	public void needBird(Bird bird) {
		int flyDis = bird.fly();
		System.out.println("這隻鳥可以飛 " + flyDis + " 米");
	}
	
	public static void main(String[] args) {
		Application app = new Application();
		Bird sparrow = new Sparrow();
		Bird sparrowDec1 = new SparrowDecorator(sparrow); //裝飾了一次
		Bird sparrowDec2 = new SparrowDecorator(sparrowDec1); //把裝飾又裝飾了一次
		app.needBird(sparrowDec1);
		app.needBird(sparrowDec2);
	}
}

運行結果如下:



3. 適配器模式



4. 工廠方法模式

具體實例:Java集合中有一個接口Collection,該接口中的iterator()方法就使用了工廠方法。Collection的實現類比如ArrayList和LinkedList中都有不同的關於Iterator對象的生成方法。按照工廠模式角色的劃分,Iterator接口是抽象產品角色;Collection接口是構造者;ArrayList、LinkedList等是具體構造者;ArrayList、LinkedList中的的具體Iterator類就是具體產品。

抽象產品(如java.util.Iterator)

public abstract class PenCore { //抽象產品:筆芯
	String color;
	public abstract void writeWord(String s);
}
抽象構造者(如java.util.Collection)

public abstract class BallPen { //抽象構造者:圓珠筆
	public BallPen() {
		System.out.println("生產了有" + getPenCore() + "筆芯的筆");
	}
	public abstract PenCore getPenCore();
}
具體產品(如java.util.Iterator的具體實現類)

下面有兩個具體產品:紅筆芯、藍筆芯。

紅筆芯:

public class RedPenCore extends PenCore {
	public RedPenCore() {
		color = "紅色";
	}
	@Override
	public void writeWord(String s) {
		System.out.println("寫" + color + "顏色的字:" + s);
	}
}
藍筆芯:

public class BluePenCore extends PenCore {
	public BluePenCore() {
		color = "藍色";
	}
	@Override
	public void writeWord(String s) {
		System.out.println("寫" + color + "顏色的字:" + s);
	}
}
具體構造者(如java.util.ArrayList、java.util.LinkedList)

下面有兩個具體構造者:紅圓珠筆、藍圓珠筆。

紅圓珠筆:

public class RedBallPen extends BallPen {
	@Override
	public PenCore getPenCore() {
		return new RedPenCore();
	}
}
藍圓珠筆:
public class BlueBallPen extends BallPen {
	@Override
	public PenCore getPenCore() {
		return new BluePenCore();
	}
}

5. 抽象工廠模式



6. 單例模式

現實實例:對於一個衣服工廠,可能生產很多衣服,但是工廠對象只需要一個,因此對於工廠可使用單例模式。當系統只需要某個類有一個實例時就可以使用單例模式。

單例模式需要保證兩件事:1 提供一個單例對象給別人;2 阻止其他開發人員創建新的對象。

單例模式的Java實現如下:

public class Factory {
	private static Factory instance; //唯一的實例
	private Factory() { //私有的構造方法
	}
	
	public Factory getInstance() { //獲取唯一的對象
		if(instance == null)
			instance = new Factory();
		return instance;
	}
}
多線程改進

對於上述代碼,如果有多線程的話,可能創建的就不止一個對象了,因此需要加鎖,如下:

public class Factory {
	private static Factory instance; //唯一的實例
	private static Object lockObj = Factory.class; //用於加鎖的
	
	private Factory() { //私有的構造方法
	}
	
	public Factory getInstance() { //獲取唯一的對象
		synchronized (lockObj) {
			if(instance == null)
				instance = new Factory();
			return instance;
		}
	}
}

7. 享元模式



8. 接橋模式


9. 代理模式

現實實例:用戶在跟公司老闆聯繫時必須先聯繫老闆的祕書,此時祕書就相當於老闆的代理。

代理分爲靜態代理和動態代理,其中動態代理的例子可參見: JDK和CGLib兩種方式實現動態代理模式

下面是靜態代理的代碼實現。

抽象主題

public interface Geometry {
	double getArea();
}
具體模板

public class Triangle implements Geometry {
	double sideA, sideB, sideC;

	public Triangle(double sideA, double sideB, double sideC) {
		this.sideA = sideA;
		this.sideB = sideB;
		this.sideC = sideC;
	}

	@Override
	public double getArea() {
		double p = (sideA + sideB + sideC) / 2.0;
		return Math.sqrt(p * (p-sideA) * (p-sideB) * (p-sideC));
	}
}
代理

public class TriangleProxy implements Geometry {
	double sideA, sideB, sideC;

	public void setABC(double a, double b, double c) {
		this.sideA = a;
		this.sideB = b;
		this.sideC = c;
	}

	@Override
	public double getArea() {
		if(sideA+sideB>sideC || sideA+sideC>sideB || sideB+sideC>sideA) {
			return new Triangle(sideA, sideB, sideC).getArea(); //相當於祕書叫老闆
		}
		return -1;
	}
}
測試運行

public class Application {
	public static void main(String[] args) {
		double a = 3, b = 4, c = 5;
		TriangleProxy triProxy = new TriangleProxy();
		triProxy.setABC(a, b, c);
		double area = triProxy.getArea();
		System.out.println("面積是:" + area);
	}
}
運行結果如下:



有待完善。轉載請註明出處。


參考文獻

耿祥義,Java設計模式.清華大學出版社.

John Metsker,Designs Patterns In Java. 電子工業出版社.


發佈了52 篇原創文章 · 獲贊 17 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章