分類(lèi)
創(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)單工廠(chǎng)模式(并不是23種設(shè)計(jì)模式之一)问拘、工廠(chǎng)方法遍略、抽象工廠(chǎng)模式、單例模式骤坐、生成器模式和原型模式绪杏。
結(jié)構(gòu)型
用于幫助將對(duì)個(gè)對(duì)象組織成更大的結(jié)構(gòu)。結(jié)構(gòu)型模式主要有適配器模式纽绍、橋接模式蕾久、組合器模式、裝飾器模式拌夏、門(mén)面模式僧著、享元模式和代理模式。
行為型
用于幫助系統(tǒng)間各對(duì)象的通信辖佣,以及如何控制復(fù)雜系統(tǒng)中的流程霹抛。行為模式主要有命令模式、解釋器模式卷谈、迭代器模式、中介者模式霞篡、備忘錄模式世蔗、觀察者模式、狀態(tài)模式朗兵、策略模式污淋、模板模式和訪(fǎng)問(wèn)者模式。
單例模式
如果一個(gè)類(lèi)始終只能創(chuàng)建一個(gè)實(shí)例余掖,則這個(gè)類(lèi)被稱(chēng)為單例類(lèi)寸爆,這種模式就被稱(chēng)為單例模式。
Spring推薦將所有業(yè)務(wù)邏輯組件、DAO組件赁豆、數(shù)據(jù)源組件等配置成單例的行為方式仅醇,因?yàn)檫@些組件無(wú)需保存任何用戶(hù)狀態(tài)。
為了保證一個(gè)類(lèi)只能產(chǎn)生一個(gè)實(shí)例魔种,程序不能允許自由創(chuàng)建該類(lèi)的對(duì)象析二,只需要使用private修飾該類(lèi)的構(gòu)造器,從而將該類(lèi)的構(gòu)造器隱藏起來(lái)节预。同時(shí)提供一個(gè)public方法作為該類(lèi)的訪(fǎng)問(wèn)點(diǎn)叶摄,用于創(chuàng)建該類(lèi)的對(duì)象,且該方法必須使用static修飾(因?yàn)檎{(diào)用該方法之前還不存在對(duì)象安拟,因此調(diào)用該方法的不可能是對(duì)象蛤吓,只能是類(lèi))。除此之外糠赦,該類(lèi)還必須緩存已經(jīng)創(chuàng)建的對(duì)象会傲,否則該類(lèi)無(wú)法知道是否曾經(jīng)創(chuàng)建過(guò)實(shí)例,也就無(wú)法保證只創(chuàng)建一個(gè)實(shí)例愉棱。為此該類(lèi)需要使用一個(gè)靜態(tài)屬性來(lái)保存曾經(jīng)創(chuàng)建的實(shí)例唆铐,且該屬性需要被靜態(tài)方法訪(fǎng)問(wèn),所以該屬性也應(yīng)使用static修飾奔滑。class Singleton { //使用一個(gè)類(lèi)變量緩存曾經(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; } }
工廠(chǎng)
- 簡(jiǎn)單工廠(chǎng)
- 工廠(chǎng)方法
- 沖向工廠(chǎng)
定義一個(gè)Factory專(zhuān)門(mén)用于生產(chǎn)類(lèi)對(duì)象氓辣。使用方通過(guò)Factory調(diào)用對(duì)應(yīng)的類(lèi)對(duì)象,將使用者和類(lèi)對(duì)象解耦袱蚓,由統(tǒng)一工廠(chǎng)耦合钞啸。如果需要更改類(lèi)對(duì)象,不需要更改工廠(chǎng)的調(diào)用者喇潘。
如果工廠(chǎng)直接生產(chǎn)被調(diào)用對(duì)象体斩,那就是簡(jiǎn)單工廠(chǎng)模式;如果工廠(chǎng)生產(chǎn)了工廠(chǎng)對(duì)象颖低,那就是會(huì)升級(jí)成抽象工廠(chǎng)模式絮吵。
代理模式
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)景伴嗡,某書(shū)店需要提供打折場(chǎng)景(vip折扣急波,舊書(shū)兌換折扣。闹究。幔崖。)
其用意是針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類(lèi)中渣淤,從而使得它們可以相互替換赏寇。策略模式使得算法可以在不影響到客戶(hù)端的情況下發(fā)生變化。策略模式是對(duì)算法的包裝价认,是把使用算法的責(zé)任和算法本身分割開(kāi)來(lái)嗅定,委派給不同的對(duì)象管理。策略模式通常把一個(gè)系列的算法包裝到一系列的策略類(lèi)里面用踩,作為一個(gè)抽象策略類(lèi)的子類(lèi)渠退。用一句話(huà)來(lái)說(shuō),就是:“準(zhǔn)備一組算法脐彩,并將每一個(gè)算法封裝起來(lái)碎乃,使得它們可以互換”。
橋接模式
假如有一個(gè)飯店提供菜單:牛肉面惠奸、豬肉面...選擇添加辣椒時(shí):無(wú)辣梅誓、微辣、中辣...
此時(shí)可以選擇橋接模式(把變化的部分抽象出來(lái))然后使得變化部分與主類(lèi)分離開(kāi)來(lái)佛南;通過(guò)組合滿(mǎn)足業(yè)務(wù)的需要梗掰。
觀察者模式
觀察者模式定義了對(duì)象間的一對(duì)多依賴(lài)關(guān)系,讓一個(gè)或者多個(gè)觀察者對(duì)象觀察一個(gè)主題對(duì)象嗅回。當(dāng)主題對(duì)象的狀態(tài)發(fā)生變化時(shí)及穗,系統(tǒng)能通知所有的依賴(lài)于次對(duì)象的觀察者對(duì)象,從而使得觀察者對(duì)象能夠自動(dòng)更新绵载。
觀察者模式主要的4個(gè)角色:
- 被觀察者的抽象基類(lèi)埂陆。一般有java.util.Observable提供。
- 觀察者接口 一般由java.util.Observer提供
- 被觀察者實(shí)現(xiàn)類(lèi) Product
- 觀察者實(shí)現(xiàn)類(lèi)
//被觀察者
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("名稱(chēng)改變?yōu)椋? + name);
f.add(l);
f.pack();
f.setVisible(true);
System.out.println("名稱(chēng)觀察者:" + o + "物品名稱(chēng)已經(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("書(shū)桌");
p.setPrice(345f);
}
}