分類
創(chuàng)建型
創(chuàng)建對(duì)象時(shí),不再直接實(shí)例化對(duì)象;而是根據(jù)特定場(chǎng)景,由程序來(lái)確定創(chuàng)建對(duì)象的方式,從而保證更高的性能、更好的架構(gòu)優(yōu)勢(shì)。創(chuàng)建型模式主要有簡(jiǎn)單工廠模式(并不是23種設(shè)計(jì)模式之一)、工廠方法、抽象工廠模式、單例模式、生成器模式和原型模式。
結(jié)構(gòu)型
用于幫助將對(duì)個(gè)對(duì)象組織成更大的結(jié)構(gòu)。結(jié)構(gòu)型模式主要有適配器模式、橋接模式、組合器模式、裝飾器模式、門面模式、享元模式和代理模式。
行為型
用于幫助系統(tǒng)間各對(duì)象的通信,以及如何控制復(fù)雜系統(tǒng)中的流程。行為模式主要有命令模式、解釋器模式、迭代器模式、中介者模式、備忘錄模式、觀察者模式、狀態(tài)模式、策略模式、模板模式和訪問(wèn)者模式。
單例模式
如果一個(gè)類始終只能創(chuàng)建一個(gè)實(shí)例,則這個(gè)類被稱為單例類,這種模式就被稱為單例模式。
Spring推薦將所有業(yè)務(wù)邏輯組件、DAO組件、數(shù)據(jù)源組件等配置成單例的行為方式,因?yàn)檫@些組件無(wú)需保存任何用戶狀態(tài)。
為了保證一個(gè)類只能產(chǎn)生一個(gè)實(shí)例,程序不能允許自由創(chuàng)建該類的對(duì)象,只需要使用private修飾該類的構(gòu)造器,從而將該類的構(gòu)造器隱藏起來(lái)。同時(shí)提供一個(gè)public方法作為該類的訪問(wèn)點(diǎn),用于創(chuàng)建該類的對(duì)象,且該方法必須使用static修飾(因?yàn)檎{(diào)用該方法之前還不存在對(duì)象,因此調(diào)用該方法的不可能是對(duì)象,只能是類)。除此之外,該類還必須緩存已經(jīng)創(chuàng)建的對(duì)象,否則該類無(wú)法知道是否曾經(jīng)創(chuàng)建過(guò)實(shí)例,也就無(wú)法保證只創(chuàng)建一個(gè)實(shí)例。為此該類需要使用一個(gè)靜態(tài)屬性來(lái)保存曾經(jīng)創(chuàng)建的實(shí)例,且該屬性需要被靜態(tài)方法訪問(wèn),所以該屬性也應(yīng)使用static修飾。class Singleton { //使用一個(gè)類變量緩存曾經(jīng)創(chuàng)建的實(shí)例 private static Singleton instance; // 將構(gòu)造器使用private修飾,隱藏該構(gòu)造器 private Singleton(){} //提供一個(gè)靜態(tài)方法,用于返回Singleton實(shí)例 //該方法可以加入自定義的控制,保證只產(chǎn)生一個(gè)Singleton對(duì)象 public static Singleton getInstance(){ //如果instance為null,表明不曾創(chuàng)建Singleton對(duì)象 //如果instance不為null,則表明已創(chuàng)建了Singleton對(duì)象,將不會(huì)執(zhí)行該方法 if(instance == null){ instance = new Singleton(); } return instance; } }
工廠
- 簡(jiǎn)單工廠
- 工廠方法
- 沖向工廠
定義一個(gè)Factory專門用于生產(chǎn)類對(duì)象。使用方通過(guò)Factory調(diào)用對(duì)應(yīng)的類對(duì)象,將使用者和類對(duì)象解耦,由統(tǒng)一工廠耦合。如果需要更改類對(duì)象,不需要更改工廠的調(diào)用者。
如果工廠直接生產(chǎn)被調(diào)用對(duì)象,那就是簡(jiǎn)單工廠模式;如果工廠生產(chǎn)了工廠對(duì)象,那就是會(huì)升級(jí)成抽象工廠模式。
代理模式
InvokationHandler實(shí)現(xiàn)
public class MyInvokationHandler implements InvocationHandler { //需要被代理的對(duì)象 private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { TxUtil tx = new TxUtil(); tx.beginTx(); Object result = method.invoke(target,args); tx.endTx(); return result; } } public class MyProxyFactory { //為指定target生成動(dòng)態(tài)代理對(duì)象 public static Object getProxy(Object target) throws Exception{ //創(chuàng)建一個(gè)MyInvokationHandler對(duì)象 MyInvokationHandler handler = new MyInvokationHandler(); //為MyInvokationHandler設(shè)置target對(duì)象 handler.setTarget(target); //創(chuàng)建并返回一個(gè)動(dòng)態(tài)代理 return Proxy.newProxyInstance(target.getClass().getClassLoader() , >target.getClass().getInterfaces(),handler); } }
命令模式
思考一種場(chǎng)景,某個(gè)方法需要完成某一個(gè)功能,完成這個(gè)功能的參數(shù)要求可以變化,具體執(zhí)行的代碼也可以變化,即需要把“處理行為”也作為一個(gè)參數(shù)傳入方法。
public interface Command { void process(int[] target); } public class ProcessArray { public void each(int[] target,Command cmd){ cmd.process(target); } } public class CommandTest { public static void main(String[] args) { ProcessArray pa = new ProcessArray(); int[] target = {3,-4,6,4}; pa.each(target, new Command() { @Override public void process(int[] target) { for(int tmp : target){ System.out.println("迭代輸出目標(biāo)數(shù)組的元素:"+ tmp); } } }); } }
策略模式
思考一種場(chǎng)景,某書店需要提供打折場(chǎng)景(vip折扣,舊書兌換折扣。。。)
其用意是針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發(fā)生變化。策略模式是對(duì)算法的包裝,是把使用算法的責(zé)任和算法本身分割開來(lái),委派給不同的對(duì)象管理。策略模式通常把一個(gè)系列的算法包裝到一系列的策略類里面,作為一個(gè)抽象策略類的子類。用一句話來(lái)說(shuō),就是:“準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來(lái),使得它們可以互換”。
橋接模式
假如有一個(gè)飯店提供菜單:牛肉面、豬肉面...選擇添加辣椒時(shí):無(wú)辣、微辣、中辣...
此時(shí)可以選擇橋接模式(把變化的部分抽象出來(lái))然后使得變化部分與主類分離開來(lái);通過(guò)組合滿足業(yè)務(wù)的需要。
觀察者模式
觀察者模式定義了對(duì)象間的一對(duì)多依賴關(guān)系,讓一個(gè)或者多個(gè)觀察者對(duì)象觀察一個(gè)主題對(duì)象。當(dāng)主題對(duì)象的狀態(tài)發(fā)生變化時(shí),系統(tǒng)能通知所有的依賴于次對(duì)象的觀察者對(duì)象,從而使得觀察者對(duì)象能夠自動(dòng)更新。
觀察者模式主要的4個(gè)角色:
- 被觀察者的抽象基類。一般有java.util.Observable提供。
- 觀察者接口 一般由java.util.Observer提供
- 被觀察者實(shí)現(xiàn)類 Product
- 觀察者實(shí)現(xiàn)類
//被觀察者
public class Product extends Observable {
//定義兩個(gè)成員變量
private String name;
private double price;
public Product(){}
public Product(String name,double price){
this.name = name;
this.price = price;
}
public String getName(){
return name;
}
//當(dāng)程序調(diào)用name的setter方法來(lái)修改Product的name成員變量時(shí),程序自然觸發(fā)該對(duì)象上注冊(cè)的所有觀察者
public void setName(String name){
this.name = name;
this.setChanged();
notifyObservers(name);
}
public double getPrice(){
return price;
}
public void setPrice(double price){
this.price = price;
this.setChanged();
notifyObservers(price);
}
}
//觀察者實(shí)現(xiàn)
public class NameObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
if( arg instanceof String ){
String name = (String) arg;
JFrame f = new JFrame("觀察者");
JLabel l = new JLabel("名稱改變?yōu)椋? + name);
f.add(l);
f.pack();
f.setVisible(true);
System.out.println("名稱觀察者:" + o + "物品名稱已經(jīng)改變?yōu)椋? + name);
}
}
}
//注冊(cè)觀察者至被觀察者
public class Main {
public static void main(String[] args) {
Product p = new Product("電視劇",176);
NameObserver no = new NameObserver();
PriceObserver po = new PriceObserver();
// p.registObserver(no);
// p.registObserver(po);
p.addObserver(no);
p.addObserver(po);
p.setName("書桌");
p.setPrice(345f);
}
}