掌握常用的幾種(最起碼單例模式、工廠模式),了解其他的設計模式即可,做到手里有糧,心里不慌。首先,掌握每種模式的定義及使用場景。其次,掌握一個形象的例子,簡單的過一遍代碼。 學習設計模式的真正目的:編程時,有意識地面向接口編程,多用封裝、繼承、組合、多態等OOP思想,而不僅僅是死記幾類設計模式。
常用的設計模式分類: 創建型 (創建一個對象):單例模式、工廠模式、抽象工廠模式 結構型 (將幾個對象組織成一個結構):橋接模式、外觀模式、代理模式 行為型 (多個對象間的通信):觀察者模式、策略模式 其中,工廠模式、橋接模式、策略模式 有點像,放在一起理解(幾個對象具有共同特征,因此繼承共同的接口,然后通過工廠、橋去訪問 )。另外,工廠模式和外觀模式 (幾個對象間有先后關系,是串行的,而非工廠模式中的并行,因此幾個對象組合成一個外觀類,通過這個外觀類來訪問 )區別很明顯,也因此放在一起理解。
參考引用:
http://www.runoob.com/design-pattern/proxy-pattern.html https://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html https://www.cnblogs.com/chinajava/p/5880870.html
設計模式定義
被反復使用的,代碼設計經驗的總結。
設計模式的原則
總結起來,就是多用接口/抽象類 ,從而增加代碼的可擴展性(減少修改代碼)。降低模塊間的依賴和聯系。 體現了OOP的模塊化、可擴展性 等特征。
工廠模式
定義與使用場合 :現在需要創建幾個對象 ,且這幾個對象有共同特征 ,則不需要具體創建各個對象,而是創建對象工廠類 即可。 一般常用靜態工廠模式。 例子: 發送郵件和短信(共同特征:發送的消息)
public interface Sender {
public void Send ();
}
public class MailSender implements Sender { @Override public void Send () { System.out.println(
"this is mailsender!" ); }
}
public class SmsSender implements Sender { @Override public void Send () { System.out.println(
"this is sms sender!" ); }
}
public class SendFactory {
public static Sender
produceMail (){
return new MailSender(); }
public static Sender
produceSms (){
return new SmsSender(); }
}
public class FactoryTest {
public static void main (String[] args) { Sender sender = SendFactory.produceMail(); sender.Send(); }
}
抽象工廠模式
工廠方法模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程序,必須對工廠類進行修改,這違背了閉包原則 。 定義與使用場景: 同上。 例子: 同上。
public interface Provider {
public Sender
produce ();
}
public class SendMailFactory implements Provider { @Override public Sender
produce (){
return new MailSender(); }
}
public class SendSmsFactory implements Provider { @Override public Sender
produce () {
return new SmsSender(); }
}
public class Test {
public static void main (String[] args) { Provider provider =
new SendMailFactory(); Sender sender = provider.produce(); sender.Send(); }
}
總結: 如果要新增發送微信,則只需做一個實現類,實現Sender接口,同時做一個工廠類,實現Provider接口,就OK了,無需去改動現成的代碼。這樣做,拓展性較好! 所有工廠模式中,抽象工廠模式最先進。
策略模式及與工廠模式的區別
定義與使用場合: 一個系統需要動態地在幾種類似的算法中選擇一種。 與工廠模式異同: 實例化一個對象的位置不同。對工廠模式而言,實例化對象是放在了工廠類里面。而策略模式實例化對象的操作在調用的地方。本質都是繼承與多態。 例子: 現有 加/減/乘 幾種算法,輸入參數返回值都一樣(可以理解成類似的算法)。現在需要在調用時動態配置算法策略,實現對不同算法的調用。
public interface Strategy {
public int doOperation (
int num1,
int num2);
}
public class OperationAdd implements Strategy {@Override public int doOperation (
int num1,
int num2) {
return num1 + num2;}
}
public class OperationSubstract implements Strategy {@Override public int doOperation (
int num1,
int num2) {
return num1 - num2;}
}
public class OperationMultiply implements Strategy {@Override public int doOperation (
int num1,
int num2) {
return num1 * num2;}
}
public class Context {
private Strategy strategy;
public Context (Strategy strategy){
this .strategy = strategy;}
public int executeStrategy (
int num1,
int num2){
return strategy.doOperation(num1, num2);}
}
public class StrategyPatternDemo {
public static void main (String[] args) {Context context =
new Context(
new OperationAdd()); System.
out .println(
"10 + 5 = " + context.executeStrategy(
10 ,
5 ));context =
new Context(
new OperationSubstract()); System.
out .println(
"10 - 5 = " + context.executeStrategy(
10 ,
5 ));context =
new Context(
new OperationMultiply()); System.
out .println(
"10 * 5 = " + context.executeStrategy(
10 ,
5 ));}
}
單例模式
定義及使用場合: 只有一個對象被創建。 例子: 建議采用 餓漢式 創建方法。線程安全,容易實現。初始化慢一點。
public class SingleObject {
private static SingleObject instance =
new SingleObject();
private SingleObject (){}
public static SingleObject
getInstance (){
return instance;}}
觀察者模式
定義與使用場景: 一個對象(subject)被其他多個對象(observer)所依賴 。則當一個對象變化時,發出通知 ,其它依賴該對象的對象都會收到通知 ,并且隨著變化。 比如 聲音報警器和閃光燈報警器分別訂閱熱水器溫度,熱水器溫度過高時,發出通知,兩個報警器分別發聲、閃光以實現報警。 又比如很多人訂閱微信公眾號,該公眾號有更新文章時,自動通知每個訂閱的用戶。 **實現:**1,多個觀察者要訂閱這個對象 2,這個對象要發出通知
例子:
public interface Observer {
public void update ();
}
public class Observer1 implements Observer { @Override public void update () { System.out.println(
"observer1 has received!" ); }
}
public class Observer2 implements Observer { @Override public void update () { System.out.println(
"observer2 has received!" ); } }
public interface Subject {
public void add (Observer observer);
public void del (Observer observer);
public void notifyObservers ();
public void operation ();
}
public abstract class AbstractSubject implements Subject { private Vector<Observer> vector =
new Vector<Observer>();
@Override public void add (Observer observer) { vector.add(observer); }
@Override public void del (Observer observer) { vector.remove(observer); }
@Override public void notifyObservers () { Enumeration<Observer> enumo = vector.elements();
while (enumo.hasMoreElements()){ enumo.nextElement().update(); } }
public class MySubject extends AbstractSubject { @Override public void operation () { System.out.println(
"update self!" ); notifyObservers(); } }
public class ObserverTest { public static void main(String[] args) { Subject
sub = new MySubject(); sub .add(new Observer1()); //訂閱這個對象
sub .add(new Observer2()); sub .operation(); //發出改變的一個通知} }
代理模式
定義與使用場景: 一個代理類代表一個真實類的功能,通過訪問代理類來實現對真實類的訪問。 比如買火車票這件小事:黃牛相當于是火車站的代理,我們可以通過黃牛買票,但只能去火車站進行改簽和退票。 又比如需要對原有的方法進行修改,就是采用一個代理類調用原有的方法,以避免修改原有代碼。 例子: 一個真實對象realSubject提供一個代理對象proxy。通過proxy可以調用realSubject的部分功能* ,并添加一些額外的業務處理*,同時可以屏蔽realSubject中未開放的接口。 1、RealSubject 是委托類,Proxy 是代理類; 2、Subject 是委托類和代理類的接口; 3、request() 是委托類和代理類的共同方法;
interface Subject {void request();
}
class RealSubject implements Subject {public void request(){System.out.println(
"RealSubject" );}
}
class Proxy implements Subject {private Subject subject;
public Proxy(Subject subject){
this .subject = subject;}
public void request(){System.out.println(
"begin" );subject.request();System.out.println(
"end" );}
}
public class ProxyTest {public static void main(String args[]) {RealSubject subject =
new RealSubject();Proxy p =
new Proxy(subject);p.request();}
}
橋接模式及與策略模式的區別
定義與使用場景: 訪問多種數據庫驅動(多個具有共同特征的數據庫驅動),不是直接訪問,而是通過DriverManager橋來訪問。
例子: 不再具體實現了。 與策略模式的區別: (個人覺得較復雜,了解即可。本質都是面向接口編程,體現繼承與多態) 策略模式:我要畫圓,要實心圓,我可以用solidPen來配置,畫虛線圓可以用dashedPen來配置。這是strategy模式。 橋接模式:同樣是畫圓,我是在windows下來畫實心圓,就用windowPen+solidPen來配置,在unix下畫實心圓就用unixPen+solidPen來配置。如果要再windows下畫虛線圓,就用windowsPen+dashedPen來配置,要在unix下畫虛線圓,就用unixPen+dashedPen來配置。 所以相對策略模式,橋接模式要表達的內容要更多,結構也更加復雜。
外觀模式
定義與使用場景: 見例子。又比如,去醫院看病,可能要去掛號、門診、劃價、取藥,讓患者或患者家屬覺得很復雜,如果有提供接待人員,只讓接待人員來處理,就很方便。 例子: 計算機啟動,需要先啟動CPU,再啟動memory,最后啟動disk。這三個類之間具有先后關系(依賴關系)。 與工廠模式的區別: 工程模式多個類具有共同特征(繼承一個共同的接口),是并列的。而外觀模式多個類是有先后關系,是串行的,用組合。
貼部分代碼:
public class Computer {
private CPU cpu;
private Memory memory;
private Disk disk;
public Computer (){ cpu =
new CPU(); memory =
new Memory(); disk =
new Disk(); }
public void startup (){ System.
out .println(
"start the computer!" ); cpu.startup(); memory.startup(); disk.startup(); System.
out .println(
"start computer finished!" ); }
public void shutdown (){ System.
out .println(
"begin to close the computer!" ); cpu.shutdown(); memory.shutdown(); disk.shutdown(); System.
out .println(
"computer closed!" ); }
}
public class User {
public static void main (String[] args) { Computer computer =
new Computer(); computer.startup(); computer.shutdown(); }
}
生產者-消費者模式
定義與使用場景: 生產者把數據放入緩沖區,而消費者從緩沖區取出數據。 例子: 緩沖區一般為隊列(FIFO),但在生產消費較為頻繁時,隊列push,pop內存消耗較大,此時可以考慮環形緩沖區(以數組、鏈表方式實現)。 通過互斥鎖防止緩沖區同時讀寫。通過信號量控制緩沖區大小(滿的時候不允許寫,空的時候不允許讀)
總結
以上是生活随笔 為你收集整理的java常用设计模式总结 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。