模式的祕密---工廠模式

工廠模式
什麼是設計模式?
設計模式就是經過前人無數次的實踐總結出的,設計過程中可以反覆使用的、可以解決特定問題的設計方法,也就是一套被反覆使用,多數人知曉的,經過分類編目的,代碼設計經驗的總結
其目的是:使用設計模式是爲了可重用代碼,讓代碼更容易被他人理解,保證代碼的可靠性。

工廠模式的概念
實列化對象,用工廠方法代替new操作
工廠模式包括工廠方法模式和抽象工廠模式
抽象工廠模式是工廠方法模式的擴展

工廠模式的意圖
定義一個接口來創建對象,但是讓子類決定哪些類需要被實例化
工廠方法把實例化的工作推遲到子類中去實現

工廠模式的應用場景
有一組類似的對象需要創建
在編碼時不能預見需要創建那種類的實例
系統需要考慮擴展性,不應依賴於產品類實例如何被創建,組合和表達細節

工廠模式的動機
項目中的現狀:
在軟件系統中經常面臨着“對象”的創建工作,由於需求的變化,這個對象可能隨之也會發生變化,但它擁有着比較穩定的接口
爲此,我們需要提供一種封裝機制來隔離出這個易變對象的變化,從而保持系統中其他依賴該對象的對象不隨着需求變化而變化
基於項目現狀將代碼進行如下設計:
1.儘量鬆耦合,一個對象的依賴對象的變化與本身無關
2.具體產品與客戶端剝離,責任分割

髮型工廠實例demo
在這裏插入圖片描述

實現接口

package com.example.demo.test3;

/**
 * 髮型接口
 */
public interface HairInterface {

    //實現髮型
    public void draw();


}

左偏分發型

package com.example.demo.test3;

/**
 * 左偏分發型
 */
public class LeftHair implements  HairInterface{

    /**
     * 畫一個左偏分發型
     */
    @Override
    public void draw() {
        System.out.println("實現左偏分發型");
    }
}

右偏分發型

package com.example.demo.test3;

public class RightHair implements  HairInterface {

    @Override
    public void draw() {
        System.out.println("實現一個右偏分的髮型");
    }
}

髮型工廠

package com.example.demo.test3;

import java.util.HashMap;
import java.util.Map;

/**
 * 髮型工廠
 */
public class HairFactory {

    /**
     * 更加類型 來創建對象
     * @return
     */
    public HairInterface getHair(String key){
       if ("left".equals(key)){
           return new LeftHair();
       }else if("right".equals(key)){
           return new RightHair();
       }
        return null;
    }

    /**
     * 根據類的名稱來生產對象
     * @param className
     * @return
     */
    public HairInterface getHairByClass(String className){

        try {
            //根據類的名稱生產一個對象
            HairInterface hair=(HairInterface) Class.forName(className).newInstance();
            return hair;
        }catch (Exception e){
            e.printStackTrace();;
        }

        return  null;
    }

    /**
     * 根據類的名稱來生產對象
     * @param className
     * @return
     */
    public HairInterface getHairByClassKey(String key){

        try {
            Map<String,String> map=new PropertiesReader().getProperties();
            //根據類的名稱生產一個對象
            HairInterface hair=(HairInterface) Class.forName(map.get(key)).newInstance();
            return hair;
        }catch (Exception e){
            e.printStackTrace();;
        }

        return  null;
    }

}

Properties讀取類

package com.example.demo.test3;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Properties讀取類
 */
public class PropertiesReader {

    public Map<String,String> getProperties(){
        Properties props=new Properties();
        Map<String,String> map=new HashMap<String,String>();
        try {
            InputStream in=getClass().getResourceAsStream("type.properties");
            props.load(in);
            Enumeration en=props.propertyNames();
            while (en.hasMoreElements()){
                String key=(String)en.nextElement();
                String property=props.getProperty(key);
                map.put(key,property);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }


}

type.properties

left=com.example.demo.test3.LeftHair
right=com.example.demo.test3.RightHair

測試方法

package com.example.demo.test3;

/**
 * 模擬客戶端實現
 */
public class Test {

    public static void main(String[] args) {
        //實現左偏分
//        HairInterface left=new LeftHair();
//        left.draw();
        HairFactory factory=new HairFactory();
//        HairInterface left=factory.getHair("left");
//        left.draw();
      //  HairInterface left= factory.getHairByClass("com.example.demo.test3.LeftHair");
        //left.draw();
       HairInterface left=factory.getHairByClassKey("left");
       left.draw();


    }



}

在這裏插入圖片描述

節日皮膚接口demo

男孩接口

package com.example.demo.test3;

/**
 * 男孩
 */
public interface Boy {

    public void drawMan();
}

女孩接口

package com.example.demo.test3;

/**
 * 女孩
 */
public interface Girl {

    public void DrawWomen();

}

男孩新年系列皮膚

package com.example.demo.test3;


/**
 * 新年系列男孩子
 */
public class HNBoy implements  Boy{

    @Override
    public void drawMan() {
        System.out.println("新年系列男孩子");
    }
}

男孩聖誕系列皮膚

package com.example.demo.test3;

/**
 * 聖誕系列的男孩子
 */
public class MCBoy implements Boy{

    @Override
    public void drawMan() {
        System.out.println("聖誕系列的男孩子");
    }
}

女孩子新年系列皮膚

package com.example.demo.test3;

public class HNGirl implements  Girl{
    @Override
    public void DrawWomen() {
        System.out.println("新年系列的女孩子");
    }
}

女孩子聖誕系列皮膚

package com.example.demo.test3;

/**
 * 聖誕系列的女孩
 */
public class MCGirl implements  Girl{

    @Override
    public void DrawWomen() {
        System.out.println("聖誕系列的女孩子");
    }
}

男孩女孩接口

package com.example.demo.test3;

public interface PersonFactory {

    //男孩接口
    public Boy getBoy();
    //女孩接口
    public Girl getGirl();

}

新年系列工廠

package com.example.demo.test3;

/**
 * 新年系列加工廠
 */
public class HNFctory implements  PersonFactory{

    @Override
    public Boy getBoy() {
        return new HNBoy();
    }

    @Override
    public Girl getGirl() {
        return new HNGirl();
    }
}

聖誕系列工廠

package com.example.demo.test3;

/**
 * 聖誕系列加工廠
 */
public class MCFctory implements  PersonFactory {

    @Override
    public Boy getBoy() {
        return new MCBoy();
    }

    @Override
    public Girl getGirl() {
        return new MCGirl();
    }
}

測試類

package com.example.demo.test3;

/**
 * 模擬客戶端實現
 */
public class Test {

    public static void main(String[] args) {
        //實現左偏分
//        HairInterface left=new LeftHair();
//        left.draw();
   //     HairFactory factory=new HairFactory();
//        HairInterface left=factory.getHair("left");
//        left.draw();
      //  HairInterface left= factory.getHairByClass("com.example.demo.test3.LeftHair");
        //left.draw();
//       HairInterface left=factory.getHairByClassKey("left");
//       left.draw();

        PersonFactory facoty=new MCFctory();
        Girl girl=facoty.getGirl();
       girl.DrawWomen();

       PersonFactory personFactory=new HNFctory();
       Boy boy=personFactory.getBoy();
       boy.drawMan();
    }



}

總結
工廠方法模式和抽象工廠模式對比
1.工廠模式時一種極端情況的抽象工廠模式,而抽象工廠模式可以看成時工廠模式的推廣
2.工廠模式用來創建一個產品的等級結構,而抽象工廠模式是用來創建多個產品的等級結構
3.工廠模式只有一個抽象產品類,而抽象工廠模式有多個抽象產品類

工廠模式的實現幫助我們
1.系統可以在不修改具體工廠角色的情況下引進新的產品
2.客戶端不必關心對象如果創建,明確了職責
3.更好的理解面向對象的原則 面向接口編程,而不要面向實現編程

工廠模式適用與哪些場景呢?
1.一個系統應當不依賴於產品類實例被創立,組成,和表示的細節。這對於所有形態的工廠模式都是重要的
2.這個系統的產品有至少一個的產品族
3.同屬於同一個產品族的產品是設計成在一起使用的。這一約束必須得在系統的設計中體現出來
4.不同的產品以一系列的接口面貌出現,從而使系統不依賴於接口實現的細節

工廠模式常用於
如:JDBC ,SpringBean
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章