金樓家Kening
設計模式在實際工作中的運用是一個潛移默化的過程,如果為了設計模式而設計模式,可能走上過度設計的歧途,自己也會感覺很彆扭。
要想用好設計模式,我有以下三點經驗:
1,首先徹底理解設計模式,為什麼會有這23種設計模式,都解決的什麼問題?
2,學習設計模式的使用樣例。在很多開源代碼中都會找到典型的使用設計模式的例子
3,理解自己的業務。先別急著套用設計模式。先理解自己的代碼。看看是否有些代碼可以優化。
循序漸進,不要急
IT技術圈
一、設計模式入門:
1.設計模式是人們在面對同類型軟件工程設計問題所總結出的一些有用經驗。模式不是代碼,而是某類問題的通用設計解決方案
2.設計模式的本質目的是使軟件工程在維護性、擴展性、變化性、複雜度方面成O(N)
3.OOP是原則,設計模式是具體方法、工具
————————————————————————————————————————————
二、策略模式
從文字方面可能我們很難理解,所以我們從實際項目入手
現在假設我們有個“鴨子項目”,首先我們用OOP的角度設計這個項目,找到鴨子中共同的特性抽取在父類中並具體實現,不同的特性不實現,由子類具體實現,好下面看代碼:
public abstract class Duck {
/**
* 叫聲和游泳為相同的特性抽取並具體實現
*/
public void Quack() {
System.out.println("~~gaga~~");
}
public void swim() {
System.out.println("~~im swim~~");
}
/**
* 外貌為不同的特性設計為抽象的方法,有子類具體實現
*/
public abstract void display();
}
現在我們看它的子類:
public class GreenHeadDuck extends Duck {
@Override
public void display() {
System.out.println("**GreenHead**");
}
}
public class RedHeadDuck extends Duck {
@Override
public void display() {
System.out.println("**RedHead**");
}
}
現在我們可以看到使用OOP可以很好的解決目前的問題,但是我們往往是需求不斷,所以我們現在又來一個新需求:添加會飛的鴨子
好辦啊,我們只要在父類中添加一個新的方法:
public abstract class Duck {
/**
* 叫聲和游泳為相同的特性抽取並具體實現
*/
public void Quack() {
System.out.println("~~gaga~~");
}
public void swim() {
System.out.println("~~im swim~~");
}
/**針對新需求的方法*/
public void Fly() {
System.out.println("~~im fly~~");
}
/**
* 外貌為不同的特性設計為抽象的方法,有子類具體實現
*/
public abstract void display();
}
繼承的問題:對類的局部改動,尤其超類的局部改動,會影響其他部分。影響會有溢出效應
好現在我們繼續用OOP的方式去解決,使其子類覆蓋Fly:
public class GreenHeadDuck extends Duck {
@Override
public void display() {
System.out.println("**GreenHead**");
}
/**
* 覆蓋
* */
public void Fly() {
System.out.println("~~no fly~~");
}
}
分析問題:
需要新的設計方式,應對項目的擴展性,降低複雜度:
1)分析項目變化與不變部分,提取變化部分,抽象成接口+實現;
2)鴨子哪些功能是會根據新需求變化的?叫聲、飛行…
我們將變化的功能設計成接口,下面看代碼:
public interface FlyBehavior {
void fly();
}
public interface QuackBehavior {
void quack();
}
來看看新的Duck類:
public abstract class Duck {
/**
* 父類定義行為出來,但是沒有具體實例化
*/
FlyBehavior mFlyBehavior;
QuackBehavior mQuackBehavior;
public Duck() {
}
public void Fly() {
if (mFlyBehavior!=null) {
mFlyBehavior.fly();
}
}
public void Quack() {
if (mQuackBehavior!=null) {
mQuackBehavior.quack();
}
}
/**
* 子類可以透過兩個行為的set方法去動態改變自己的具體行為
*/
public void setmFlyBehavior(FlyBehavior mFlyBehavior) {
this.mFlyBehavior = mFlyBehavior;
}
public void setmQuackBehavior(QuackBehavior mQuackBehavior) {
this.mQuackBehavior = mQuackBehavior;
}
public abstract void display();
}
在去看看子類:
public class RedHeadDuck extends Duck{
public RedHeadDuck() {
mFlyBehavior=new GoodFlyBehavior();
mQuackBehavior=new GaGaQuackBehavior();
}
@Override
public void display() {
System.out.println("redDuck");
}
}
public class GreenHeadDuck extends Duck{
public GreenHeadDuck() {
mFlyBehavior=new BadFlyBehavior();
mQuackBehavior=new GeGeQuackBehavior();
}
@Override
public void display() {
System.out.println("greenDuck");
}
再來看看接口實現類:
public class BadFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println("bad fly");
}
}
public class GoodFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println("good fly");
}
}
public class NoFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println("No fly");
}
}
public class GaGaQuackBehavior implements QuackBehavior{
@Override
public void quack() {
System.out.println("gaga quack");
}
}
public class GeGeQuackBehavior implements QuackBehavior{
@Override
public void quack() {
System.out.println("gege quack");
}
}
public class NoQuackBehavior implements QuackBehavior{
@Override
public void quack() {
System.out.println("No Quack");
}
}
在父類中我們定義好FlyBehavior & QuackBehavior 兩個行為接口,然後在子類構造方法中分別設定對應的具體行為
現在來測試一下:
策略模式:分別封裝行為接口,實現算法族,超類裡放行為接口對象,在子類裡具體設定行為對象。原則就是:分離變化部分,封裝接口,基於接口編程各種功能。此模式讓行為算法的變化獨立於算法的使用者
—————————————————————————————————————————————
三、觀察者模式:
跟之前一樣,我們還是通過實際項目入手,之後,這句話我就不重複了,直接從項目開始講解了
現在假設我們有一個需要為A公司實時提供天氣的天氣預報接口項目,好的,首先我們還是以OOP的方式去解決問題,首先我們創建一個天氣臺對象並提供相關方法假設它可以實時為A公司提供天氣數據,下面看代碼:
public class MeteorologicalStation {
private float pressure;
private float temperature;
private float humidity;
private ACompany company;
public MeteorologicalStation(ACompany company) {
this.company=company;
}
public float getPressure() {
return pressure;
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
/**
* 實時提供天氣情況
* */
public void uploadData(float pressure,float temperature,float humidity){
company.getMeteorologicalStationData(pressure, temperature, humidity);
}
}
ACompany為A公司:
public class ACompany {
public void getMeteorologicalStationData(float pressure, float temperature, float humidity) {
System.out.println("pressure: "+pressure+\
itkeji綜合
這裡有一個誤區,並不是刻意的要在項目中使用設計模式,而是實際經驗發現的最佳實踐提煉出來是設計模式。所以在沒有很多實際經驗的情況下,很難切中設計模式的使用要領。
這時候可以在瞭解各種設計模式的前提下,多多去看實際項目包括開源項目的使用模式,才能慢慢體會到設計模式是如何付諸實踐的。接著自己多寫多想,就會突然發現,某些情況就是自然而然需要使用某個設計模式的最佳時機。