設(shè)計(jì)模式之過濾器模式詳解(附源代碼)

過濾器模式(Filter Pattern)

過濾器模式(Filter Pattern)或標(biāo)準(zhǔn)模式(Criteria Pattern)是一種設(shè)計(jì)模式只搁,這種模式允許開發(fā)人員使用不同的標(biāo)準(zhǔn)來過濾一組對象涮毫,通過邏輯運(yùn)算以解耦的方式把它們連接起來像鸡。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式樊拓,它結(jié)合多個標(biāo)準(zhǔn)來獲得單一標(biāo)準(zhǔn)框舔。


實(shí)現(xiàn)

我們將創(chuàng)建一個 Person 對象实束、Criteria 接口和實(shí)現(xiàn)了該接口的實(shí)體類卵惦,來過濾 Person 對象的列表记靡。CriteriaPatternDemo谈竿,我們的演示類使用 Criteria 對象,基于各種標(biāo)準(zhǔn)和它們的結(jié)合來過濾 Person 對象的列表摸吠。

步驟 1:

  1. 創(chuàng)建一個枚舉(PersonAttributes)空凸,保存人(Person)的各種屬性

Java字符使用Unicode編碼,可以使用中文寸痢,但不建議使用呀洲。這里為了方便輸出隨意為之。

/**
 * @see Person類中可選的屬性
 * @author Thornhill
 *
 */
public enum PersonAttributes {
    男, 女, 醫(yī)生, 程序員;
    private PersonAttributes() {
    }

    public static PersonAttributes getMale() {
        return 男;
    }

    public static PersonAttributes getFemale() {
        return 女;
    }

    public static PersonAttributes getProgrammer() {
        return 程序員;
    }

    public static PersonAttributes getDoctor() {
        return PersonAttributes.醫(yī)生;
    }

}
  1. 創(chuàng)建一個類(Person)啼止,在該類上應(yīng)用標(biāo)準(zhǔn)道逗。(即各種過濾)
/**
 * @see 被各種過濾器過濾的實(shí)體
 * @author Thornhill
 *
 */
public class Person {
    private PersonAttributes gender;
    private PersonAttributes career;
    private String name;

    public Person(String name, PersonAttributes gender, PersonAttributes career) {
        this.name = name;
        this.gender = gender;
        this.career = career;
    }

    /**
     * @see 重寫toString,便于直接輸出
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(name + " " + gender + " " + career);
        return sb.toString();
        // return super.toString();
    }

    public PersonAttributes getGender() {
        return gender;
    }

    public PersonAttributes getCareer() {
        return career;
    }

    public String getName() {
        return name;
    }
}

步驟 2:

為標(biāo)準(zhǔn)(Criteria)創(chuàng)建一個接口(Criteria)献烦。

/**
 * @see 定義過濾的行為
 * @author Thornhill
 *
 */
public interface Criteria {
    public List<Person> meetCriteria(List<Person> persons);
}

步驟 3:

創(chuàng)建實(shí)現(xiàn)了 Criteria 接口的各種過濾器實(shí)體類滓窍。

  1. 找出醫(yī)生:
/**
 * @see 找出是醫(yī)生的實(shí)體
 * @author Thornhill
 *
 */
public class CriteriaDoctor implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> list = new ArrayList<Person>();
        for (Person person : persons) {
            if (person.getCareer().equals(PersonAttributes.醫(yī)生)) {
                list.add(person);
            }
        }
        return list;
    }

}
  1. 找出程序員:
/**
 * @see 找出是程序員的實(shí)體
 * @author Thornhill
 *
 */
public class CriteriaProgrammer implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> list = new ArrayList<Person>();
        for (Person person : persons) {
            if (person.getCareer().equals(PersonAttributes.程序員)) {
                list.add(person);
            }
        }
        return list;
    }

}
  1. 找出男人:
/**
 * @see 找出是男的實(shí)體
 * @author Thornhill
 *
 */
public class CriteriaMale implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> list = new ArrayList<Person>();
        for (Person person : persons) {
            if (person.getGender().equals(PersonAttributes.男)) {
                list.add(person);
            }
        }
        return list;
    }

}
  1. 找出女人:
/**
 * @see 找出是女人的實(shí)體
 * @author Thornhill
 *
 */
public class CriteriaFemale implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> list = new ArrayList<Person>();
        for (Person person : persons) {
            if (person.getGender().equals(PersonAttributes.女)) {
                list.add(person);
            }
        }
        return list;
    }

}
  1. 混合查詢:

    1. 與查詢:查詢輸入查詢條件的交集
    /**
     * @see 查詢所有滿足輸入條件的交集
     * @author Thornhill
     *
     */
    public class FilterAnd implements Criteria {
    
        private List<Criteria> list = new ArrayList<Criteria>();
    
        public FilterAnd(Criteria... criterias) {
            for (Criteria criteria : criterias) {
                list.add(criteria);
            }
        }
    
        @Override
        public List<Person> meetCriteria(List<Person> persons) {
            List<Person> result = new ArrayList<Person>(persons);
            for (Criteria criteria : list) {
                result = criteria.meetCriteria(result);
            }
            return result;
        }
    
    }
    
    1. 或查詢:返回所有滿足查詢條件的并集
    因?yàn)椴⒓枰ブ兀赃@里直接使用Set
    
    /**
     * @see 查詢所有輸入條件的并集
     * @author Thornhill
     *
     */
    public class FilterOr implements Criteria {
        private List<Criteria> list = new ArrayList<Criteria>();
    
        public FilterOr(Criteria... criterias) {
            for (Criteria criteria : criterias) {
                list.add(criteria);
            }
        }
    
        @Override
        public List<Person> meetCriteria(List<Person> persons) {
            Set<Person> result = new HashSet<Person>();
            for (Criteria criteria : list) {
                result.addAll(criteria.meetCriteria(persons));
            }
            return new ArrayList<Person>(result);
        }
    
    }
    

步驟4:

使用不同的標(biāo)準(zhǔn)(Criteria)和它們的結(jié)合來過濾 Person 對象的列表巩那。

public class CriteriaPatternDemo {

    public static void main(String[] args) {
        List<Person> persons = new ArrayList<Person>();
        //加入元素
        persons.add(new Person("張1", PersonAttributes.男, PersonAttributes.程序員));
        persons.add(new Person("張2", PersonAttributes.男, PersonAttributes.醫(yī)生));
        persons.add(new Person("張3", PersonAttributes.女, PersonAttributes.程序員));
        persons.add(new Person("張4", PersonAttributes.女, PersonAttributes.醫(yī)生));
        //創(chuàng)建篩選
        Criteria criteriaMale = new CriteriaMale();
        Criteria criteriaFemale = new CriteriaFemale();
        Criteria criteriaDoctor = new CriteriaDoctor();
        Criteria criteriaProgrammer = new CriteriaProgrammer();
        //創(chuàng)建混合篩選
        Criteria filterAnd = new FilterAnd(criteriaFemale,criteriaProgrammer);//查詢女程序員
        Criteria filterOr = new FilterOr(criteriaDoctor,criteriaMale);//查詢醫(yī)生或男
        //輸出
        System.out.println(persons.toString());
        System.out.println(criteriaMale.meetCriteria(persons));
        System.out.println(criteriaFemale.meetCriteria(persons));
        System.out.println(criteriaProgrammer.meetCriteria(persons));
        System.out.println(criteriaDoctor.meetCriteria(persons));
        System.out.println("------------混合查詢------------");
        System.out.println(filterAnd.meetCriteria(persons));
        System.out.println(filterOr.meetCriteria(persons));
        
    }

}

步驟 5:

驗(yàn)證輸出吏夯。

[張1 男 程序員, 張2 男 醫(yī)生, 張3 女 程序員, 張4 女 醫(yī)生]
[張1 男 程序員, 張2 男 醫(yī)生]
[張3 女 程序員, 張4 女 醫(yī)生]
[張1 男 程序員, 張3 女 程序員]
[張2 男 醫(yī)生, 張4 女 醫(yī)生]
------------混合查詢------------
[張3 女 程序員]
[張2 男 醫(yī)生, 張1 男 程序員, 張4 女 醫(yī)生]

結(jié)語:

過濾器模式優(yōu)秀在過濾條件可以自動組和此蜈,上一次的結(jié)果可以用于下一次的輸入。

GitHub源代碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末噪生,一起剝皮案震驚了整個濱河市裆赵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跺嗽,老刑警劉巖战授,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抛蚁,居然都是意外死亡陈醒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門瞧甩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钉跷,“玉大人,你說我怎么就攤上這事肚逸∫蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵朦促,是天一觀的道長膝晾。 經(jīng)常有香客問我,道長务冕,這世上最難降的妖魔是什么血当? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮禀忆,結(jié)果婚禮上臊旭,老公的妹妹穿的比我還像新娘。我一直安慰自己箩退,他們只是感情好离熏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戴涝,像睡著了一般滋戳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啥刻,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天奸鸯,我揣著相機(jī)與錄音,去河邊找鬼可帽。 笑死府喳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蘑拯。 我是一名探鬼主播钝满,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼兜粘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弯蚜?” 一聲冷哼從身側(cè)響起孔轴,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碎捺,沒想到半個月后路鹰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡收厨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年晋柱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诵叁。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雁竞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拧额,到底是詐尸還是另有隱情碑诉,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布侥锦,位于F島的核電站进栽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏恭垦。R本人自食惡果不足惜快毛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望番挺。 院中可真熱鬧祸泪,春花似錦、人聲如沸建芙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禁荸。三九已至,卻和暖如春阀湿,著一層夾襖步出監(jiān)牢的瞬間赶熟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工陷嘴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留映砖,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓灾挨,卻偏偏與公主長得像邑退,于是被迫代替她去往敵國和親竹宋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理地技,服務(wù)發(fā)現(xiàn)蜈七,斷路器,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法莫矗,類相關(guān)的語法飒硅,內(nèi)部類的語法,繼承相關(guān)的語法作谚,異常的語法三娩,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 這幾日你的朋友圈一定是被王健林所講的“小目標(biāo)”刷屏著。 1妹懒、 一個億對王健林是什么概念雀监?2015年《胡潤中國百富榜...
    請叫我九哥閱讀 218評論 0 1
  • ARC 在代碼編譯時滔悉,自動的向代碼中插入retain和release,完成了對象的引用計(jì)算加減单绑。在運(yùn)行時回官,通過對w...
    natewang閱讀 1,115評論 1 1
  • 當(dāng)賈躍亭決定戰(zhàn)略入股酷派的時候区转,他應(yīng)該知道周鴻祎是個有仇必報(bào)的人苔巨。 “誰在我背后捅刀子試圖screw我,我的原則是...
    悟東閱讀 4,265評論 11 34