1. 程式人生 > 實用技巧 >常見的幾種設計模式

常見的幾種設計模式

前言

  以下是對常見的幾種設計模式的介紹

  實現程式碼的github地址:https://github.com/Chenrencun/design-pattern

正文

  一、單例模式

  1、定義:

  一個類只有一個例項,且該類能自行建立這個例項的一種模式。

  2、結構:

  (1)單例類:包含一個例項且能自行建立這個例項的類。

  3、實現程式碼:

  (1)餓漢式:

public class HungrySingle {

    private static final HungrySingle singleton = new HungrySingle();

    private
HungrySingle(){ } public static HungrySingle getInstance(){ return singleton; } }

  (2)懶漢式:

   ①單執行緒(執行緒不安全):

public class LazySingletonForNotSafe {

    private static LazySingletonForNotSafe lazySingleton;

    private LazySingletonForNotSafe(){

    }

    public static LazySingletonForNotSafe getInstance(){
        
if (lazySingleton == null){ lazySingleton = new LazySingletonForNotSafe(); } return lazySingleton; } }

   ②多執行緒(執行緒安全):

public class LazySingletonForSafe {

    //volatile關鍵字,保證可見性
    private static volatile LazySingletonForSafe singleton;

    private LazySingletonForSafe(){

    }

    
public static LazySingletonForSafe getInstance(){ if (singleton == null){ synchronized (LazySingletonForSafe.class){ if (singleton == null){ singleton = new LazySingletonForSafe(); } } } return singleton; } }

  二、工廠方法模式:

  1、定義:

   定義一個建立產品物件的工廠介面,將產品物件的實際建立工作推遲到具體子工廠類當中。

  2、結構:

  (1)抽象工廠:提供了建立產品的介面,呼叫者通過它訪問具體工廠的工廠方法 newProduct() 來建立產品。

  (2)具體工廠:主要是實現抽象工廠中的抽象方法,完成具體產品的建立。

  (3)抽象產品:定義了產品的規範,描述了產品的主要特性和功能。

  (4)具體產品:實現了抽象產品角色所定義的介面,由具體工廠來建立,它同具體工廠之間一一對應。

  3、實現程式碼:

  (1)抽象產品介面:

public interface Product {

    public void show();

}

  (2)具體產品類:

public class ConcreteProduct1 implements Product{

    @Override
    public void show() {
        System.out.println("具體產品1顯示------");
    }
}


public class ConcreteProduct2 implements Product{

    @Override
    public void show() {
        System.out.println("具體產品2顯示---------");
    }
}

  (3)抽象工廠介面:

public interface Factory {

    public Product create();
}

  (4)具體工廠類:

public class ConcreteFactory1 implements Factory{

    @Override
    public Product create() {
        System.out.println("具體工廠1生成—>具體產品1");
        return new ConcreteProduct1();
    }
}


public class ConcreteFactory2 implements Factory{

    @Override
    public Product create() {
        System.out.println("具體工廠2生成—>具體產品2");
        return new ConcreteProduct2();
    }
}

  三、抽象工廠模式:

  1、定義:

   是一種為訪問類提供一個建立一組相關或相互依賴物件的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。

  2、結構:

  (1)抽象工廠:提供了建立產品的介面,它包含多個建立產品的方法 newProduct(),可以建立多個不同等級的產品。

  (2)具體工廠:主要是實現抽象工廠中的多個抽象方法,完成具體產品的建立。

  (3)抽象產品:定義了產品的規範,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。

  (4)具體產品:實現了抽象產品角色所定義的介面,由具體工廠來建立,它 同具體工廠之間是多對一的關係。

  3、實現程式碼:

  (1)抽象產品介面:

public interface FirstProduct {

    public void show();
}


public interface SecondProduct {

    public void show();
}

  (2)具體產品類:

public class ConcreteFirstProduct1 implements FirstProduct {

    public void show() {
        System.out.println("顯示具體產品11------");
    }
}


public class ConcreteSecondProduct1 implements SecondProduct {

    public void show() {
        System.out.println("顯示具體產品21------");
    }
}

  (3)抽象工廠介面:

public interface Factory {

    public FirstProduct createFirstProduct();

    public SecondProduct createSecondProduct();
}

  (4)具體工廠類:

public class ConcreteFactory1 implements Factory{

    public FirstProduct createFirstProduct() {
        return new ConcreteFirstProduct1();
    }

    public SecondProduct createSecondProduct() {
        return new ConcreteSecondProduct1();
    }
}

  四、代理模式:

  1、定義:

   給某物件提供一個代理以控制對該物件的訪問。這時,訪問物件不適合或者不能直接引用目標物件,代理物件作為訪問物件和目標物件之間的中介。

  2、結構:

  (1)抽象主題類:通過介面或抽象類宣告真實主題和代理物件實現的業務方法。

  (2)具體主題類:實現了抽象主題中的具體業務,是代理物件所代表的真實物件,是最終要引用的物件。

  (3)代理類:提供了與真實主題相同的介面,其內部含有對真實主題的引用,它可以訪問、控制或擴充套件真實主題的功能。

  3、實現程式碼:

  (1)普通代理:

    ①抽象主題介面:

public interface Subject {

    void request();
}

    ②具體主題類:

public class ConcreteSubject implements Subject{

    public void request() {
        System.out.println("具體主題類的request方法");
    }
}

    ③代理類:

public class Proxy implements Subject{

    private Subject subject;

    public Proxy(Subject subject){
        this.subject = subject;
    }

    public void request() {
        before();
        subject.request();
        after();
    }

    private void before(){
        System.out.println("執行方法前-----dosomething");
    }

    private void after(){
        System.out.println("執行方法後-----dosomething");
    }

}

  (2)動態代理:

    ①抽象主題介面:

public interface Subject {

    void request();
}

    ②具體主題類:

public class ConcreteSubject implements Subject {

    public void request() {
        System.out.println("具體主題類的request方法");
    }
}

    ③代理類:

public class DynamicProxy implements InvocationHandler {

    private Object object;

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(object, args);
        after();
        return result;
    }

    public Object getProxy(Object object){
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    private void before(){
        System.out.println("執行方法前-----dosomething");
    }

    private void after(){
        System.out.println("執行方法後-----dosomething");
    }
}

  (3)CGLib代理:

    ①抽象主題介面:

public interface Subject {

    void request();
}

    ②具體主題類:

public class ConcreteSubject implements Subject {

    public void request() {
        System.out.println("具體主題類的request方法");
    }
}

    ③代理類:

public class CGLibProxy implements MethodInterceptor {

    private Object object;

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object result = method.invoke(object, objects);
        after();
        return result;
    }

    public Object getProxy(Object object){
        this.object = object;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        Object result = enhancer.create();
        return result;
    }

    private void before(){
        System.out.println("執行方法前-----dosomething");
    }

    private void after(){
        System.out.println("執行方法後-----dosomething");
    }
}

  五、介面卡模式:

  1、定義:

  將一個類的介面轉換成客戶希望的另外一個介面,使得原本由於介面不相容而不能一起工作的那些類能一起工作。

  2、結構:

  (1)目標介面:當前系統業務所期待的介面,它可以是抽象類或介面。

  (2)適配者類:它是被訪問和適配的現存元件庫中的元件介面。

  (3)介面卡類:它是一個轉換器,通過繼承或引用適配者的物件,把適配者介面轉換成目標介面,讓客戶按目標介面的格式訪問適配者。

  3、實現程式碼:

  (1)類介面卡:通過繼承的方式進行適配。

    ①目標介面:

public interface Target {

    void request();

}

    ②適配者類:

public class Adaptee {

    public void specialRequest(){
        System.out.println("執行適配者類的specialRequest方法");
    }
}

    ③介面卡類:

public class Adapter extends Adaptee implements Target{

    public void request() {
        specialRequest();
    }
}

  (2)物件介面卡:通過組合/聚合的方式進行適配。

    ①目標介面:

public interface Target {

    void request();

}

    ②適配者類:

public class Adaptee {

    public void specialRequest(){
        System.out.println("執行適配者類的specialRequest方法");
    }
}

    ③介面卡類:

public class Adapter implements Target{

    private Adaptee adaptee;

    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }

    public void request() {
        adaptee.specialRequest();
    }
}

  

  六、模板方法模式:

  1、定義:

  定義一個操作中的演算法骨架,而將演算法的一些步驟延遲到子類中,使得子類可以不改變該演算法結構的情況下重定義該演算法的某些特定步驟。

  2、結構:

  (1)抽象類:負責給出一個演算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。

    ①模板方法:定義了演算法的骨架,按某種順序呼叫其包含的基本方法。

    ②基本方法:是整個演算法中的一個步驟,包含以下幾種型別。

     抽象方法:在抽象類中申明,由具體子類實現。

     具體方法:在抽象類中已經實現,在具體子類中可以繼承或重寫它。

     鉤子方法:在抽象類中已經實現,包括用於判斷的邏輯方法和需要子類重寫的空方法兩種。

  (2)具體子類:實現抽象類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的一個組成步驟。

  3、實現程式碼:

  (1)抽象類:

public abstract class AbstractClass {

    // 模板方法
    public void templateMethod(){
        concreteMethod();
        abstractMethod1();
        // 鉤子方法進行邏輯判斷
        if (hookMethod()){
            abstractMethod2();
        }
    }

    // 具體方法(基本方法)
    public void concreteMethod(){
        System.out.println("執行具體方法");
    }

    // 抽象方法(基本方法)
    public abstract void abstractMethod1();

    // 抽象方法(基本方法)
    public abstract void abstractMethod2();

    // 鉤子方法(基本方法)
    public boolean hookMethod(){
        return true;
    }
}

  (2)具體子類:

public class ConcreteClass extends AbstractClass{

    public void abstractMethod1() {
        System.out.println("執行具體子類的重寫方法1");
    }

    public void abstractMethod2() {
        System.out.println("執行具體子類的重寫方法2");
    }

    @Override
    public boolean hookMethod() {
        return false;
    }
}

  七、策略模式

  1、定義:

  定義了一系列演算法,並將每個演算法封裝起來,使它們可以相互替換,且演算法的變化不會影響使用演算法的客戶。

  2、結構:

  (1)抽象策略類:定義了一個公共介面,各種不同的演算法以不同的方式實現這個介面,環境角色使用這個介面呼叫不同的演算法,一般使用介面或抽象類實現。

  (2)具體策略類:實現了抽象策略定義的介面,提供具體的演算法實現。

  (3)環境類:持有一個策略類的引用,最終給客戶端呼叫。

  3、實現程式碼:

  (1)抽象策略類:

public interface Strategy {

    void strategyMethod();
}

  (2)具體策略類:

public class ConcreteStrategy1 implements Strategy{

    public void strategyMethod() {
        System.out.println("訪問具體策略類1的演算法");
    }
}


public class ConcreteStrategy2 implements Strategy{

    public void strategyMethod() {
        System.out.println("訪問具體策略類2的演算法");
    }
}

  (3)環境類:

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy){
        this.strategy = strategy;
    }

    public void strategyMethod(){
        strategy.strategyMethod();
    }
}

  八、觀察者模式

  1、定義:

  指多個物件間存在一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。

  2、結構:

  (1)抽象目標類:它提供了增加、刪除觀察者物件的抽象方法,以及通知所有觀察者的抽象方法。

  (2)具體目標類:它提供了一個用於儲存觀察者物件的聚集類,實現抽象目標中的增加、刪除觀察者物件的方法以及通知方法。

  (3)抽象觀察者類:它是一個抽象類或介面,它包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被呼叫。

  (4)具體觀察者類:實現抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態。

  3、實現程式碼:

  (1)抽象目標類:

public interface Target {

    void addObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObserver();
}

  (2)具體目標類:

public class ConcreteTarget implements Target{

    private List<Observer> observerList = new ArrayList<Observer>();

    public void addObserver(Observer observer) {
        observerList.add(observer);
    }

    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }

    public void notifyObserver() {
        for (Observer observer:observerList
             ) {
            observer.responseMethod();
        }
    }
}

  (3)抽象觀察者類:

public interface Observer {

    void responseMethod();
}

  (4)具體觀察者類:

public class ConcreteObserver1 implements Observer{

    public void responseMethod() {
        System.out.println("執行具體觀察者1的方法");
    }
}


public class ConcreteObserver2 implements Observer{

    public void responseMethod() {
        System.out.println("執行具體觀察者2的方法");
    }
}