設計模式總結

weixin_33936401發表於2016-02-24

學一樣東西,自己另外舉個例子實現一遍,才能知道里面的原理.記錄一下學習的幾種基本的設計模式

檔案結構

幾種設計模式的檔案結構如下圖所示

558092-c5e079b7d7922eb0.png
目錄結構圖

原始碼下載
原始碼下載

代理模式

說明

這裡我舉了一個網頁渲染時使用代理延遲載入圖片的例子,用執行緒的睡眠模擬延遲載入,hibernate的延遲載入就是用了代理模式實現
代理模式的主要應用:

  1. 遠端代理,例如webservice
  2. 虛擬代理,html渲染
  3. 安全代理,控制真實物件的訪問許可權

spring的AOP就是用的代理模式的思想設計實現的

類圖

558092-dc7c5b01b230b744.png
UML類圖

程式碼

package codeDesign.proxy;
/**
 * Created by kangbiao on 2015/11/22.
 * 網頁繪製介面,代理和被代理類均實現該介面
 */
public interface Draw {
    /**
     * 繪製圖片,需要花很多時間,使用代理來繪製
     * @param url
     */
    void drawPicture(String url);
}

package codeDesign.proxy;
/**
 * Created by kangbiao on 2015/11/22.
 * 繪製html網頁的類(該類會消耗很多時間)
 */
public class HtmlDraw implements Draw{
    /**
     * 該方法不耗時,不需要代理
     * @param text
     */
    public void drawText(String text) {
        System.out.println("正在繪製文字:" + text);
    }
    /**
     * 會消耗一定的時間,需要代理
     * @param url
     */
    @Override
    public void drawPicture(String url) {
        System.out.println("圖片區域正在從遠端載入圖片");
        try {
            Thread.sleep(5000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("正在繪製圖片:"+url);
    }
}

package codeDesign.proxy;
/**
 * Created by kangbiao on 2015/11/22.
 * 圖片繪製代理類
 */
public class ProxyDraw implements Draw {
    HtmlDraw htmlDraw;
    public ProxyDraw(){
        this.htmlDraw=new HtmlDraw();
    }
    @Override
    public void drawPicture(String url) {
        System.out.println("代理先輸出一張佔點陣圖片");
        new Thread(new Runnable() {
            @Override
            public void run() {
                htmlDraw.drawPicture("1.jpg");
                System.out.println("代理去掉佔點陣圖片");
            }
        }).start();
    }
}

package codeDesign.proxy;
/**
 * Created by kangbiao on 2015/11/22.
 * 代理模式測試類
 */
public class ProxyTest {
    /**
     * 該過程演示了網頁的繪製過程,使用代理模式非同步繪製網頁上面的圖片
     * @param args
     */
    public static void main(String[] args){
        HtmlDraw htmlDraw=new HtmlDraw();
        htmlDraw.drawText("文字1");
        ProxyDraw proxyDraw=new ProxyDraw();
        proxyDraw.drawPicture("1.jpg");
        htmlDraw.drawText("文字2");
    }
}

工廠模式

說明

最基礎的設計模式

類圖

558092-e857a907aa3c044c.png
工廠模式UML類圖

程式碼

package codeDesign.factory;
/**
 * Created by kangbiao on 2015/11/21.
 *
 */
public class Tea {
    private String sugar;
    public void mixSugarTea(){
        System.out.print("只有"+sugar);
    }
    public String getSugar()
    {
        return sugar;
    }
    public void setSugar(String sugar)
    {
        this.sugar = sugar;
    }
}

package codeDesign.factory;
/**
 * Created by kangbiao on 2015/11/21.
 * 藍茶
 */
public class BlueTea extends Tea{
    public void mixSugarTea(){
        System.out.print(super.getSugar()+"藍茶");
    }
}

package codeDesign.factory;
/**
 * Created by kangbiao on 2015/11/21.
 * 紅茶
 */
public class BlackTea extends Tea{
    public void mixSugarTea(){
        System.out.print(super.getSugar()+"紅茶");
    }
}

package codeDesign.factory;
/**
 * Created by kangbiao on 2015/11/21.
 * 茶的工廠類
 */
public class TeaFactory {
    public static Tea getTea(String teaType){
        Tea tea;
        switch (teaType){
            case "black":
                tea=new BlackTea();
                break;
            case "blue":
                tea=new BlueTea();
                break;
            default:
                tea=new Tea();
                break;
        }
        return tea;
    }
}

package codeDesign.factory;
/**
 * Created by kangbiao on 2015/11/21.
 * 工廠模式測試
 */
public class FactoryTest {
    public static void main(String[] args){
        Tea tea = TeaFactory.getTea("black");
        tea.setSugar("紅糖");
        tea.mixSugarTea();
    }
}

裝飾器模式

說明

  1. 如果只有一個Concrete Component類而沒有抽象的Component介面時,可以讓Decorator繼承Concrete Component。
  2. 如果只有一個Concrete Decorator類時,可以將Decorator和Concrete Decorator合併。
  3. java的io流包就是使用的裝飾器模式

類圖

558092-61f691e60aaf6cd6.png
裝飾器模式UML類圖

程式碼

package codeDesign.decorator;
/**
 * Created by kangbiao on 2015/11/21.
 * 汽車類
 */
public class Car {
    public void showFunc(){
        System.out.print("組裝完畢");
    }
}

package codeDesign.decorator;
/**
 * Created by kangbiao on 2015/11/21.
 * 汽車的功能類
 */
public class Function extends Car{
    protected Car car;
    public void addFuncs(Car car){
        this.car=car;
    }
    public void showFunc(){
        if (car!=null){
            car.showFunc();
        }
    }
}

package codeDesign.decorator;
/**
 * Created by kangbiao on 2015/11/21.
 * 制動功能
 */
public class BrakingFunction extends Function{
    public void showFunc(){
        System.out.print("制動");
        super.showFunc();
    }
}

package codeDesign.decorator;
/**
 * Created by kangbiao on 2015/11/21.
 * ABS防抱死功能
 */
public class ABSFunction extends Function{
    public void showFunc(){
        System.out.print("ABS");
        super.showFunc();
    }
}

package codeDesign.decorator;
/**
 * Created by kangbiao on 2015/11/21.
 * 裝飾模式測試
 */
public class DecoratorTest {
    public static void main(String[] args){
        Car car=new Car();
        ABSFunction abs=new ABSFunction();
        BrakingFunction braking=new BrakingFunction();
        abs.addFuncs(car);
        braking.addFuncs(abs);
        braking.showFunc();
    }
}

策略模式

說明

這裡我結合了工廠模式,使得加密演算法的選擇邏輯不用暴露給客戶端
Strategy中定義了公共演算法的實現介面,然後通過多型在Context動態的建立不同的實現類的例項從而達到演算法策略選擇邏輯
簡化單元測試,因為每一個具體的實現都在一個類裡面,可以分開測試
減少了演算法呼叫類和演算法實現類之間的耦合

類圖

558092-fb0ab6045c07eb6c.png
策略模式UML類圖

程式碼

package codeDesign.strategy;
/**
 * Created by kangbiao on 2015/11/21.
 * 加密演算法介面
 */
public interface EncryptStrategy {
    /**
     * 加密演算法實現介面
     * @param rawString
     * @return
     */
    String doEncrypt(String rawString);
}

package codeDesign.strategy;
/**
 * Created by kangbiao on 2015/11/21.
 * md5加密策略實現類
 */
public class MD5Strategy implements EncryptStrategy{
    @Override
    public String doEncrypt(String rawString) {
        return "MD5("+rawString+")";
    }
}

package codeDesign.strategy;
/**
 * Created by kangbiao on 2015/11/21.
 * SHA1加密實現類
 */
public class SHA1Strategy implements EncryptStrategy {
    @Override
    public String doEncrypt(String rawString) {
        return "SHA1("+rawString+")";
    }
}

package codeDesign.strategy;
/**
 * Created by kangbiao on 2015/11/21.
 * 加密上下文維護類,客戶端呼叫類
 */
public class EncryptContext {
    private EncryptStrategy encryptStrategy;
    public final static byte MD5=0;
    public final static byte SHA1=1;
    /**
     * 這裡實現用工廠模式實現自動裝載不同的類
     * @param method
     */
    public EncryptContext(Byte method){
        switch (method){
            case MD5:
                this.encryptStrategy=new MD5Strategy();
                break;
            case SHA1:
                this.encryptStrategy=new SHA1Strategy();
                break;
            default:
                break;
        }
    }
    public String doEncrypt(String rawString){
        return encryptStrategy.doEncrypt(rawString);
    }
}

package codeDesign.strategy;
/**
 * Created by kangbiao on 2015/11/21.
 * 策略模式測試類
 */
public class EncryptTest {
    public static void main(String[] args){
        EncryptContext encryptContext=new EncryptContext(EncryptContext.MD5);
        String result=encryptContext.doEncrypt("123456");
        System.out.print(result);
    }
}

相關文章