
單例模式
概念:確保一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例
UML中帶==下劃線的屬性==是靜態(tài)的;
如下特點(diǎn):
- 構(gòu)造方法私有
- 指向自己實(shí)例的私有靜態(tài)引用
- 以自己實(shí)例為返回值的公有靜態(tài)方法
單例模式可詳細(xì)分為兩類, 餓單例模式,懶單例模式
/**
* 餓漢式單例模式,在類被加載的時(shí)候就實(shí)例化好了對象
*/
public class SingleTon {
public static SingleTon singleTon = new SingleTon();
private SingleTon() {
}
public static SingleTon getSingleTon() {
return singleTon;
}
}
/**
* 懶漢式單例模式,在調(diào)用實(shí)例化方法的時(shí)候才會創(chuàng)建它的實(shí)例
*/
public class SingleTon {
public static SingleTon singleTon;
private SingleTon() {
}
public static synchronized SingleTon getSingleTon() {
if (singleTon == null) {
singleTon = new SingleTon();
}
return singleTon;
}
}
單例模式的優(yōu)點(diǎn):
- 在內(nèi)存中只有一個(gè)對象,節(jié)省內(nèi)存空間
- 避免頻繁的創(chuàng)建銷毀對象,加快效率
- 避免對共享資源的多重占用
- 可以全局訪問
適用場景: - 只能適用單例類提供的方法來獲取單例對象,使用反射會創(chuàng)建新的對象
- 多線程使用單例模式時(shí),要注意線程安全
- 不要做斷開單例類對象與類中靜態(tài)引用的危險(xiǎn)操作。(╯°Д°)╯︵┻━┻
在java中餓漢要優(yōu)于懶漢,還要因?yàn)闃?gòu)造方法是私有的,所以不能被繼承ε(┬┬﹏┬┬)3
工廠方法模式
概念:定義一個(gè)創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個(gè)類,工廠方法模式使一個(gè)類的實(shí)例化延遲到了子類。
interface IProduct {
public void productMethod();
}
class Product implements IProduct {
@Override
public void productMethod() {
System.out.println("產(chǎn)品");
}
}
interface IFactory {
public IProduct createProduct();
}
class Factory implements IFactory {
@Override
public IProduct createProduct() {
return new Product();
}
}
public class FactoryClient {
public static void main(String[] arg) {
IFactory factory = new Factory();
IProduct product = factory.createProduct();
product.productMethod();
}
}
工廠模式根據(jù)抽象程度分為三種:簡單工廠模式(靜態(tài)工廠模式),工廠方法模式,抽象工廠模式。
主要優(yōu)點(diǎn):
- 使代碼結(jié)構(gòu)清晰,有效的封裝變化。在編程中有些產(chǎn)品的實(shí)例化是比較復(fù)雜的多變的,通過工廠模式,將產(chǎn)品的實(shí)例化過程封裝起來,使用者不用管產(chǎn)品的實(shí)例化過程,只需要依賴工廠即可得到產(chǎn)品對象。
- 調(diào)用者屏蔽了具體的產(chǎn)品類,即使產(chǎn)品的實(shí)現(xiàn)發(fā)生了變化,調(diào)用只關(guān)心或者依賴產(chǎn)品的接口就好了,不會產(chǎn)生任何影響。
- 降低耦合度,產(chǎn)品的實(shí)例化通常是比較復(fù)雜的,需要依賴很多的類,而這些類對于調(diào)用者來說無需知道,工廠只是把最終的產(chǎn)品對象,交給調(diào)用者,產(chǎn)品所依賴的類都是不存在的ヾ(????)?"
通過工廠方法模式的類圖可以看出,工廠模式有四個(gè)要素:
- 工廠接口,是工廠方法模式的核心,用于與調(diào)用者交互,用來提供產(chǎn)品。
- 工廠實(shí)現(xiàn),決定如何實(shí)現(xiàn)產(chǎn)品,有多少種產(chǎn)品,就要有多少種工廠實(shí)現(xiàn)。
- 產(chǎn)品接口,所有產(chǎn)品都必須遵守產(chǎn)品接口所定義的規(guī)范,產(chǎn)品接口也是調(diào)用者最關(guān)心的,產(chǎn)品接口定義的好壞,決定了代碼的穩(wěn)定性,與工廠接口一樣,可以用抽象類來代替,但是不能違反里氏替換原則ヽ(#`Д′)?┌┛〃
- 產(chǎn)品實(shí)現(xiàn),決定了產(chǎn)品的在客戶端的具體行為。
適用場景:
作為“創(chuàng)建類模式”,在任何需要生成復(fù)雜對象的地方,都可以使用工廠模式。
如果創(chuàng)建一個(gè)類需要大量的依賴其他類,那么調(diào)用者就會產(chǎn)生很強(qiáng)的耦合度,這時(shí)候可以考慮使用工廠模式,來降低調(diào)用者與外界的耦合度。

建造者模式
定義:將一個(gè)復(fù)雜對象的構(gòu)建與表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
類型:創(chuàng)建類模式
四個(gè)要素:
- 產(chǎn)品類,一般是一個(gè)創(chuàng)建過程較為復(fù)雜的對象,在實(shí)際編程中,產(chǎn)品類可以是一個(gè)抽象類,或多個(gè)抽象類及其實(shí)現(xiàn)子類組成;
- 抽象建造者,為了將具體的建造過程交于他的子類實(shí)現(xiàn),更容易擴(kuò)展,最少有兩個(gè)方法,一個(gè)是建造產(chǎn)品,一個(gè)是返回產(chǎn)品。
- 建造者,實(shí)現(xiàn)抽象建造者的方法,組建產(chǎn)品,返回組建好的產(chǎn)品。
- 導(dǎo)演類,調(diào)用適當(dāng)?shù)慕ㄔ煺邅斫M建產(chǎn)品,一般不與產(chǎn)品發(fā)生依賴,用于封裝程序中易變的部分(?`?′)/
class Product {
private String name;
private String type;
public void setName(String name) {
this.name = name;
}
public void setType(String type) {
this.type = type;
}
public void showProduct() {
System.out.println("name = " + name);
System.out.println("type = " + type);
}
}
abstract class Builder {
public abstract void setPart(String arg1, String arg2);
public abstract Product getProduct();
}
class ConcreteBuilder extends Builder {
private Product product = new Product();
@Override
public void setPart(String arg1, String arg2) {
product.setName(arg1);
product.setType(arg2);
}
@Override
public Product getProduct() {
return product;
}
}
/**
* 導(dǎo)演讓你創(chuàng)建啥,你就創(chuàng)建啥ヾ(o?ω?)?
*/
class Director {
private Builder builder = new ConcreteBuilder();
public Product getAProduct() {
builder.setPart("保時(shí)捷", "卡宴");
return builder.getProduct();
}
public Product getBProduct() {
builder.setPart("鳳凰牌", "自行車");
return builder.getProduct();
}
}
public class BuilderClient {
public static void main(String[] args) {
Director director = new Director();
Product p1 = director.getAProduct();
p1.showProduct();
Product p2 = director.getBProduct();
p2.showProduct();
}
}
建造者模式的優(yōu)點(diǎn):
- 一般產(chǎn)品類和建造者類都是比價(jià)穩(wěn)定的,因此,將主要邏輯,以及具體實(shí)現(xiàn),這些易變的部分封裝在了導(dǎo)演類中。
- 當(dāng)有現(xiàn)需求時(shí)候,只要實(shí)現(xiàn)一個(gè)新的建造者類就可以不動之前經(jīng)過測試的代碼了,不會引入風(fēng)險(xiǎn)。
建造者模式與工廠模式的區(qū)別:
與工廠模式相比,建造模式一般用來創(chuàng)建更加復(fù)雜的對象, 因?yàn)楦訌?fù)雜的對象創(chuàng)建過程,需要一個(gè)導(dǎo)演類將這個(gè)復(fù)雜的創(chuàng)建過程獨(dú)立出來。也就是說工廠模式將所有的對象創(chuàng)建過程封裝在工廠中,有工廠類想客戶端提供最終的產(chǎn)品。而建造者模式中,建造者只提供產(chǎn)品的各個(gè)組件的建造,然后將具體的建造過程交給導(dǎo)演類,由導(dǎo)演類將各個(gè)組件的建造特定的規(guī)則組成產(chǎn)品,交給客戶端。
原型模式(Prototype)
定義:用原型實(shí)例指定創(chuàng)建對象的種類,并通過拷貝這些原型創(chuàng)建新的對象。
類型:創(chuàng)建類模式
原型模式主要用于對象的復(fù)制,它的核心就是原型類prototype,prototype需要具備兩個(gè)條件
- 實(shí)現(xiàn)Cloneable接口,它的作用只有一個(gè),就是通知虛擬機(jī)可以安全的在實(shí)現(xiàn)了此接口的類上使用clone方法。只有實(shí)現(xiàn)了這個(gè)接口的類才可以被clone。
- 重寫clone方法,將權(quán)限修飾符修改為public,
模板方法模式(template)
定義:定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類中去,使子類可以不改變算法的結(jié)構(gòu),即可重新定義某些特性的步驟.
架構(gòu)師將整個(gè)應(yīng)用的大體邏輯,試用大量的接口或者抽象類講真?zhèn)€系統(tǒng)串起來,然后根據(jù)實(shí)現(xiàn)的難度不同交給高級工程師,初級工程師,由他們來實(shí)現(xiàn)子類,完成開發(fā)。
模板方法模式的結(jié)構(gòu):
模板方法模式由一個(gè)抽象類和一組(n>=1)子類組成,抽象類中方法分為三種
- 抽象方法,父類只聲明而不實(shí)現(xiàn),定義好規(guī)范,然后由其子類去實(shí)現(xiàn)。
- 模板方法,由抽象類聲明并加以實(shí)現(xiàn),一般來說模板方法調(diào)用抽象方法來完成主要的邏輯功能,并且,模板方法大多數(shù)會定義成final類型,指明主要的邏輯在子類中無法被重寫。
- 鉤子方法,由抽象類聲明并加以實(shí)現(xiàn),但是子類可以去擴(kuò)展,子類可以通過擴(kuò)展鉤子方法,來影響模板方法的邏輯。
- 抽象類的任務(wù)是搭建邏輯框架,通常由經(jīng)驗(yàn)豐富的人,抽象類的好壞直接決定了程序是否穩(wěn)定,
- 實(shí)現(xiàn)類用來實(shí)現(xiàn)細(xì)節(jié),模板方法正式通過實(shí)現(xiàn)類中擴(kuò)展的方法來完成邏輯,只要實(shí)現(xiàn)類中擴(kuò)展方法通過了單元測試,在模板方法正確的前提下,一般整體不會出現(xiàn)太大的錯(cuò)誤。
適用場景:
- 容易擴(kuò)展,一般來說,抽象類中的模板方法是不易發(fā)生改變的部分,而抽象方法式容易發(fā)生改變的部分,因此通過增加實(shí)現(xiàn)類一般很容易實(shí)現(xiàn)功能的擴(kuò)展,符合開閉原則。
- 便于維護(hù),對于模板方法模式來說,正是由于他們的主要邏輯相同,才使用模板方法。
- 靈活,因?yàn)橛秀^子方法,因此子類的實(shí)現(xiàn)也可以影響父類的主要運(yùn)行邏輯,但是卻違反了里氏替換原則。
- 多個(gè)子類擁有相同的方法,并且這些方法的邏輯相同的情況下可以使用模板方法模式,在程序的主框架相同,細(xì)節(jié)不同的情況下,比較適合使用這種模式。
中介者模式
定義:用一個(gè)中介者對象封裝一些列的交互對象,中介者使個(gè)對象不需要顯示的互相作用,從而降低耦合,而且可以獨(dú)立的改變他們之間的交互。
結(jié)構(gòu):中介者模式又稱為調(diào)停者模式,氛圍三部分
- 抽象中介者,定義好同事類對象到中介者對象的接口,用于各同事類之間的通訊,一般包括一個(gè)或者多個(gè)抽象的時(shí)間方法,并由子類去實(shí)現(xiàn)。
- 中介者實(shí)現(xiàn)類:從抽象中介者繼承而來,實(shí)現(xiàn)抽象中介者中定義的事件方法。從一個(gè)同事類接收消息,然后通過消息影響其他同時(shí)類。
- 如果一個(gè)對象會影響其他的對象,同時(shí)也會被其他對象影響,那么這兩個(gè)對象稱為同事類。在類圖中,同事類只有一個(gè),這其實(shí)是現(xiàn)實(shí)的省略,在實(shí)際應(yīng)用中,同事類一般由多個(gè)組成,他們之間相互影響,相互依賴。同事類越多,關(guān)系越復(fù)雜。并且,同事類也可以表現(xiàn)為繼承了同一個(gè)抽象類的一組實(shí)現(xiàn)組成。在中介者模式中,同事類之間必須通過中介者才能進(jìn)行消息傳遞。
代理模式
為其他對象提供一種代理以控制這個(gè)對象的訪問。
結(jié)構(gòu):
- Subject抽象主題角色,可以是抽象類也可以是一個(gè)接口,普通業(yè)務(wù)類型的定義,無特殊要求。
- RealSubject具體角色,被委托角色,業(yè)務(wù)邏輯具體執(zhí)行者。
- Proxy代理角色,負(fù)責(zé)對真實(shí)角色的應(yīng)用,把所有抽象主題的方法,委托給真是主題角色實(shí)現(xiàn),并且在真實(shí)角色處理完畢前后座預(yù)處理和善后工作。
模板代碼:
interface Subject {
void request();
}
class RealSubject implements Subject {
private String name;
public RealSubject(String name) {
this.name = name;
}
@Override
public void request() {
System.out.println("name = " + name);
}
}
class Proxy implements Subject {
private Subject subject = null;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
this.before();
this.subject.request();
this.after();
}
//預(yù)處理工作
private void before() {
System.out.println(System.currentTimeMillis() + "預(yù)處理工作");
}
//善后工作
private void after() {
System.out.println(System.currentTimeMillis() + "善后工作");
}
}
public class ClientProxy {
public static void main(String[] args) {
Subject subject = new RealSubject("zhangsan");
Subject proxy = new Proxy(subject);
proxy.request();
}
}
1506480477076預(yù)處理工作
name = zhangsan
1506480477076善后工作
代理模式優(yōu)點(diǎn):
- 職責(zé)清晰,真是角色就是實(shí)現(xiàn)實(shí)際的業(yè)務(wù)邏輯,不用關(guān)心其他非本職事物,
- 高擴(kuò)展性,具體主題角色可以隨時(shí)改變,只要實(shí)現(xiàn)了接口,甭管怎么變化,都逃不出我的手心,代理類可以不改變的情況下使用。
- 智能化,︵╰(‵□′)╯︵┻━┻
觀察者模式
定義:定義對象間一種一對多的依賴關(guān)系,使得當(dāng)每一個(gè)對象改變狀態(tài),則所有依賴于它的對象,都會的到通知并自動更新。

在軟件系統(tǒng)中通常會有這樣的需求,如果一個(gè)對象的狀態(tài)發(fā)生改變,某些與他先關(guān)的對象也要做出改變。
結(jié)構(gòu):
- 被觀察者,從類圖中可以看到,類中有一個(gè)用來存放觀察者對象的Vector的容器,(在多線程中Vector是線程安全的,而不是用list),這個(gè)集合是被觀察者的核心,另外有三個(gè)方法,attach方法,向這個(gè)容器中添加觀察者對象,detach方法,從容器中移除觀察者對象,notify方法,依次調(diào)用觀察對象的對應(yīng)方法。這個(gè)角色可以是是接口,也可以是抽象類或者具體的類,因?yàn)楹芏嗲闆r是和其他模式一起使用。
- 觀察者,觀察者角色一般是一個(gè)接口,它只有一個(gè)update方法,在被觀察者狀態(tài)發(fā)生改變是,這個(gè)方法就會被觸發(fā)調(diào)用。
- 具體的被觀察者,使用這個(gè)角色是為了便于擴(kuò)展,可以在此角色中定義具體的業(yè)務(wù)邏輯。
- 具體的觀察者,定義被觀察者狀態(tài)發(fā)生改變時(shí),回調(diào)的觀察者對象具體處理的邏輯。
/**
* 被觀察者
*/
abstract class Observeable {
private Vector<Observer> vector = new Vector();
public void addObserve(Observer obs) {
this.vector.add(obs);
}
public void removeObserve(Observer obs) {
this.vector.remove(obs);
}
protected void notifyObserve() {
for (Observer observer : vector) {
observer.update();
}
}
public abstract void doSomething();
}
/**
* 被觀察者實(shí)例
*/
class ContractObserve extends Observeable {
@Override
public void doSomething() {
System.out.println("被觀察者事件發(fā)生");
this.notifyObserve();
}
}
interface Observer {
void update();
}
/**
* 實(shí)例觀察者1
*/
class ConcreteObserve1 implements Observer {
@Override
public void update() {
System.out.println("觀察者1收到信息,并進(jìn)行處理");
}
}
/**
* 實(shí)例觀察者2
*/
class ConcreteObserve2 implements Observer {
@Override
public void update() {
System.out.println("觀察者2收到信息,并進(jìn)行處理");
}
}
public class ObserveClient {
public static void main(String[] args) {
//創(chuàng)建被觀察者
//這里真正new的都是實(shí)現(xiàn)子類
Observeable obs = new ContractObserve();
obs.addObserve(new ConcreteObserve1());
obs.addObserve(new ConcreteObserve2());
obs.doSomething();
}
}
觀察者模式的優(yōu)點(diǎn):
觀察者與被觀察者之間是一種輕度的關(guān)聯(lián)關(guān)系,并且是抽象耦合的,這樣對于二者來說都比較容易擴(kuò)展。觀察者模式是一種常用的觸發(fā)機(jī)制,它形成一條觸發(fā)鏈,依次對各個(gè)觀察者的方法進(jìn)行處理,但同時(shí)由于是鏈?zhǔn)接|發(fā),所以當(dāng)觀察者較多的時(shí)候,性能是比較擔(dān)憂的,
責(zé)任鏈模式
定義:使多個(gè)對象都有機(jī)會處理請求,從而避免了請求的發(fā)送者和接受者之間的耦合關(guān)系,將這些對象連成一條線,并沿著這條線傳遞這些請求,知道有對象處理請求為止。
策略模式
定義:定義一組算法,將每個(gè)算法都封裝起來,并且使他們之間可以相互轉(zhuǎn)換。
策略模式是把算法封裝到一系列的類中去,并且這些類實(shí)現(xiàn)相同的接口,相互之間可以相互替換。他與模板方法的區(qū)別在于,在模板方法模式中調(diào)用算法的主體在抽象的父類中,而在策略模式中,調(diào)用算法的主體則是在封裝了Context的封裝類中。
結(jié)構(gòu):
- 封裝類,也叫上下文,對策略進(jìn)行二次封裝,目的是避免高層模塊對策略的直接調(diào)用。
- 抽象策略,通常情況下為一個(gè)接口,當(dāng)各個(gè)類中出現(xiàn)重復(fù)的邏輯時(shí)候,使用抽象類來封裝這部分代碼,此時(shí)會看上去像是模板方法。
- 具體策略,具體策略通常由一組封裝了算法的類來擔(dān)任,這些類之間可以根據(jù)需要自由替換。
策略模式的優(yōu)點(diǎn)
- 策略類之間可以相互轉(zhuǎn)換,由于策略類實(shí)現(xiàn)自統(tǒng)一個(gè)抽象,所以他們之間可以自由切換。
- 易于擴(kuò)展,增加一個(gè)新的策略模式非常的簡單,可以在不修改原有代碼的基礎(chǔ)上進(jìn)行擴(kuò)展。
- 避免使用多重條件,如果不使用策略模式,所有的算法需要用條件語句去進(jìn)行連接,這樣的做法非常不容易維護(hù)。
- 維護(hù)各個(gè)策略類給開發(fā)者帶來額外的開銷。
- 客戶端必須要知道所有策略類的區(qū)別,然后決定用哪一個(gè),但是有違背迪米特法則。
ヽ(`Д′)?︵ ┻━┻
適用場景:
策略模式實(shí)際上就是面向?qū)ο笾械睦^承和多態(tài)。
- 幾個(gè)類的主要邏輯相同,只是部分邏輯和算法上有所區(qū)別的情況。
- 有相似的行為,或者算法,客戶端需要?jiǎng)討B(tài)的取決定使用哪一個(gè),那么可以使用策略模式,將這些算法封裝起來供客戶端調(diào)用。
- 一般與工廠方法模式,模板方法模式混合使用情況較多。