23種設計模式[3]:抽象工廠模式

1、簡單工廠模式(靜態工廠方法,不屬於23種GOF設計模式之一)

定義:定義一個用於建立產品對象的方法,由該工廠類根據傳入的參數,動態決定應該建立哪個產品類(這些產品類繼承自一個父類或接口)的實例。編程

類型:建立類模式設計模式

public interface SmsService {
    void sendSms();
}

public class MontnetsSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過夢網發送!");
    }
}

public class EtonenetSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過移通發送!");
    }
}

public class SmsServiceFactory {

    public static SmsService getSmsService(int providerId) {
        SmsService ss;

        switch (providerId) {
            case 0:
                ss = new MontnetsSmsService();
                break;
            case 1:
                ss = new EtonenetSmsService();
                break;
            default:
                ss = new EtonenetSmsService();
        }

        return ss;
    }

    public static void main(String[] args) {
        SmsService ss = SmsServiceFactory.getSmsService(0);
        //發送短信
        ss.sendSms();
    }
}

 

 

2、工廠方法模式

定義:定義一個用於建立產品對象的接口,由子類決定實例化哪個類,工廠方法使一個類的實例化延遲到其子類。ide

類型:建立類模式spa

類圖:.net

工廠方法模式代碼:設計

public interface SmsService {
    void sendSms();
}

//工廠接口
public interface SmsServiceFactory {
    SmsService getSmsService(int providerId);
}

public class MontnetsSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過夢網發送!");
    }
}

public class EtonenetSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過移通發送!");
    }
}

/**
 * 工廠實現類
 */
public class SmsServiceFactoryImpl implements SmsServiceFactory{

    @Override
    public SmsService getSmsService(int providerId) {
        SmsService ss;

        switch (providerId) {
            case 0:
                ss = new MontnetsSmsService();
                break;
            case 1:
                ss = new EtonenetSmsService();
                break;
            default:
                ss = new EtonenetSmsService();
        }

        return ss;
    }

    public static void main(String[] args) {
     //向上轉型爲工程接口
        SmsServiceFactory ssf = new SmsServiceFactoryImpl();
        SmsService ss = ssf.getSmsService(0);
        //發送短信
        ss.sendSms();
    }
}

工廠方法模式:code

  經過工廠方法模式的類圖能夠看到,工廠方法模式有四個要素:對象

  • 工廠接口。工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。在實際編程中,有時候也會使用一個抽象類來做爲與調用者交互的接口,其本質上是同樣的。
  • 工廠實現。在編程中,工廠實現決定如何實例化產品,是實現擴展的途徑,須要有多少種產品,就須要有多少個具體的工廠實現。
  • 產品接口。產品接口的主要目的是定義產品的規範,全部的產品實現都必須遵循產品接口定義的規範。產品接口是調用者最爲關心的,產品接口定義的優劣直接決定了調用者代碼的穩定性。一樣,產品接口也能夠用抽象類來代替,但要注意最好不要違反里氏替換原則。
  • 產品實現。實現產品接口的具體類,決定了產品在客戶端中的具體行爲。

  上文提到的簡單工廠模式跟工廠方法模式極爲類似,區別是:簡單工廠只有三個要素,他沒有工廠接口,而且獲得產品的方法通常是靜態的(紅色註釋部分)。由於沒有工廠接口,因此在工廠實現的擴展性方面稍弱,能夠算所工廠方法模式的簡化版。blog

 

 

3、抽象工廠模式

定義:爲建立一組相關或相互依賴的對象提供一個接口,並且無需指定他們的具體類。繼承

類型:建立類模式

類圖:

 

抽象工廠模式代碼:

public interface SmsService {
    void sendMsg();
}

public interface NoticeService {
    void sendMsg();
}

public interface MsgServiceFactory {
    SmsService getSmsService();
    
    SmsService getNoticeService();
}

public class MontnetsSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過夢網發送!");
    }
}

public class EtonenetSmsService implements SmsService {
    @Override
    public void sendMsg() {
        System.out.println("經過移通發送!");
    }
}

public class ApnsService implements NoticeService {
    @Override
    public void sendMsg() {
        System.out.println("經過APNS發送!");
    }
}

public class JpushService implements NoticeService {
    @Override
    public void sendMsg() {
        System.out.println("經過極光發送!");
    }
}

/**
 * 抽象工廠實現類1
 */
public class MsgServiceFactoryImpl implements MsgServiceFactory{

    @Override
    public SmsService getSmsService() {
        return new MontnetsSmsService();
    }
    
    @Override
    public NoticeService getNoticeService() {
        return new ApnsService();
    }
    
    public static void main(String[] args) {
     //向上轉型爲工程接口
        SmsServiceFactory ssf = new SmsServiceFactoryImpl();
        //發送消息經過短信,移通
        ssf.getSmsService().sendMsg();
        //發送消息經過App,APNS
        ssf.getNoticeService().sendMsg();
    }
}

/**
 * 抽象工廠實現類2
 */
public class MsgServiceFactoryImpl implements MsgServiceFactory{

    @Override
    public SmsService getSmsService() {
        return new EtonenetSmsService();
    }
    
    @Override
    public NoticeService getNoticeService() {
        return new JpushService();
    }
    
    public static void main(String[] args) {
     //向上轉型爲工程接口
        MsgServiceFactory ssf = new MsgServiceFactoryImpl();
        //發送消息經過短信
        ssf.getSmsService().sendMsg();
        //發送消息經過App
        ssf.getNoticeService().sendMsg();
    }
}

  抽象工廠模式是工廠方法模式的升級版本,抽象工廠模式除了具備工廠方法模式的優勢外,最主要的優勢就是能夠在類的內部對產品族進行約束。所謂的產品族,通常或多或少的都存在必定的關聯,抽象工廠模式就能夠在類內部對產品族的關聯關係進行定義和描述,而沒必要專門引入一個新的類來進行管理。

  在抽象工廠模式中,有一個產品族的概念:所謂的產品族,是指位於不一樣產品等級結構中功能相關聯的產品組成的家族。抽象工廠模式所提供的一系列產品就組成一個產品族;而工廠方法提供的一系列產品稱爲一個等級結構。

  如上代碼中,產品族有短信、App通知。咱們要實現消息的下發,能夠經過以下兩大產品類達到消息下發的目的。實際開發中的代碼好比上編寫的更緊湊,會結合簡單工廠、工廠方法、抽象工廠、反射等編寫。

 代碼相似以下:

public interface SmsService {
    void sendMsg();
}

public interface NoticeService {
    void sendMsg();
}

public interface MsgServiceFactory {
    SmsService getSmsService();

    SmsService getSmsService(int providerId);
    
    SmsService getSmsService(String className);
    
    SmsService getNoticeService();
    
    SmsService getNoticeService(int providerId);
    
    SmsService getNoticeService(String className);
}

public class MontnetsSmsService implements SmsService {
    @Override
    public void sendSms() {
        System.out.println("經過夢網發送!");
    }
}

public class EtonenetSmsService implements SmsService {
    @Override
    public void sendMsg() {
        System.out.println("經過移通發送!");
    }
}

public class ApnsService implements NoticeService {
    @Override
    public void sendMsg() {
        System.out.println("經過APNS發送!");
    }
}

public class JpushService implements NoticeService {
    @Override
    public void sendMsg() {
        System.out.println("經過極光發送!");
    }
}

/**
 * 抽象工廠實現類
 */
public class MsgServiceFactoryImpl implements MsgServiceFactory{

    @Override
    public SmsService getSmsService() {
        return new EtonenetSmsService(); 
    }

    @Override
    public SmsService getSmsService(int providerId) {
        SmsService ss;
        switch (providerId) {
            case 0:
                ss = new MontnetsSmsService();
                break;
            case 1:
                ss = new EtonenetSmsService();
                break;
            default:
                ss = new EtonenetSmsService();
        }

        return ss;
    }
    
    @Override
    public SmsService getSmsService(String className) {
        //使用反射
        Class clazz = Class.forName(className);
        return (SmsService) clazz.newInstance(); 
    }
    
    @Override
    public SmsService getNoticeService() {
        return new ApnsService(); 
    }
    
    @Override
    public NoticeService getNoticeService(int providerId) {
        NoticeService ns;
        switch (providerId) {
            case 0:
                ns = new JpushService();
                break;
            case 1:
                ns = new ApnsService();
                break;
            default:
                ns = new ApnsService();
        }

        return ns;
    }
    
    @Override
    public NoticeService getNoticeService(String className) {
        //使用反射
        Class clazz = Class.forName(className);
        return (NoticeService) clazz.newInstance(); 
    }
    
    public static void main(String[] args) {
     //向上轉型爲工程接口
        SmsServiceFactory ssf = new SmsServiceFactoryImpl();
        //發送消息經過短信,移通
        ssf.getSmsService(0).sendMsg();
        //發送消息經過App,APNS
        ssf.getNoticeService(1).sendMsg();
    }
}

 

 

4、總結

  不管是簡單工廠模式,工廠方法模式,仍是抽象工廠模式,他們都屬於工廠模式,在形式和特色上也是極爲類似的,他們的最終目的都是爲了解耦。在使用時,咱們沒必要去在乎這個模式到底工廠方法模式仍是抽象工廠模式,由於他們之間的演變經常是使人琢磨不透的。常常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,因爲類中的產品構成了不一樣等級結構中的產品族,它就變成抽象工廠模式了;而對於抽象工廠模式,當減小一個方法使的提供的產品再也不構成產品族以後,它就演變成了工廠方法模式。

  因此,在使用工廠模式時,只須要關心下降耦合度的目的是否達到了,不須要徹底遵照各類模式的特色和約束來實現業務代碼。

 

 

 

如寫的很差,歡迎拍磚!

PS:

http://blog.csdn.net/zhengzhb/article/details/7359385

相關文章
相關標籤/搜索