成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

面向?qū)ο笈c設(shè)計模式

macg0406 / 3325人閱讀

摘要:而面向?qū)ο笫前褑栴}中出現(xiàn)的角色獨立出來,讓他們互相通信來完成最終的問題。不管是面向過程還是面向?qū)ο?,都是我們認識世界的一種方法。工廠方法模式問題陳述在面向?qū)ο缶幊讨凶钔ǔ5姆椒ㄊ且粋€操作符產(chǎn)生一個對象實例操作符就是用來構(gòu)造對象實例的。

前言

大一的時候?qū)W校就開了C語言這門課,最開始糊里糊涂無從下手,后來慢慢寫了幾個幾百行的小程序就逐漸明白編程是怎么一回事了,還以為自己都懂了(too young ?。墒呛髞聿淞艘还?jié)java公選課,才知道還有面向?qū)ο缶幊踢@么一回事。老師說C是面向過程的,代碼超過十萬行就不好組織管理了,還得要面向?qū)ο蟮恼Z言才能解決這個問題。我當(dāng)時仿佛發(fā)現(xiàn)了一個新大陸,于是就開啟了自學(xué)java面向?qū)ο缶幊痰穆烦獭?/p> 面向?qū)ο笫鞘裁?/b>

我感覺這個問題還真的不好回答,不同的人有不同的理解,下面就談?wù)勎业睦斫?,望大家指正?/p>

要說面向?qū)ο笫紫染偷谜f說面向過程(出現(xiàn)的先后順序),面向過程就是分析要解決的問題A,然后把這個問題劃分為不同的步驟A1,A2,...(或者問題足夠小就不用劃分)。然后用函數(shù)把這些子問題一個一個地實現(xiàn),最終解決A。

而面向?qū)ο笫前褑栴}中出現(xiàn)的角色獨立出來,讓他們互相通信來完成最終的問題。

不管是面向過程還是面向?qū)ο?,都是我們認識世界的一種方法。那你可能會問了,既然面向過程先出現(xiàn)而且能解決問題,那么面向?qū)ο鬄槭裁磿霈F(xiàn)呢?首先面向過程既然出現(xiàn)就肯定有它的道理,因為它符合我們最常見的邏輯,我們現(xiàn)實生活中遇上問題大多會采用這種思維,比如我有個目標(biāo)A:“我要成為科學(xué)家” ,那么很自然我就會想到A1:完成小學(xué),A2:完成中學(xué),A3:完成大學(xué),A4:完成研究生,...,An:獲得科研機構(gòu)認可。把這一系列子問題挨個解決,那么我的問題就解決了,如圖:

代碼:

A(baby){
    primary = A1(baby);
    middle = A2(primary);
    university = A3(middle);
    graduate = A4(university);
    //...
    scientist = An(graduate);
    return scientist;
}

這是一種很自然的思路,所以面向過程最早出現(xiàn)。但是這種思路有個問題就是當(dāng)系統(tǒng)龐大了龐大起來過后,各個步驟之間協(xié)調(diào)起來比較復(fù)雜,修改一個步驟可能引起很多的步驟的改變,比如那一天中國在中學(xué)和大學(xué)之間增加了一個學(xué)歷preUniversity,那么至少就得改動兩個函數(shù),如果美國沒有小學(xué)那么這個函數(shù)就得搞一個美國版去掉A1,修改A2。等等等等。

這既不利于維護,也沒有達到代碼可重用的目的。面向?qū)ο缶蛻?yīng)運而生了,用面向?qū)ο蟮乃悸肪涂梢匀缦陆鉀Q:

代碼:

//人
class People(){
    
}

//教育機構(gòu)
class Education(People people){
    private People people = people;
    public void primary(People people);
    public void middle (People people);
    public void university (People people);
    public void graduate (People people);
    //...
    public void scientist (People people);     
    public bool finish(){
        primary(people);
        middle (people);
        university (people);
        graduate (people);
        scientist (people);
        retrun true;
    }    
      
}

//科研機構(gòu)
class Institution(){
    public void Recognize(Education education){
        if(education.finish()&&others){//完成學(xué)業(yè)以及科研機構(gòu)的其他判斷條件
            print "Scientist";
        }else{
            print "Not Scientist";
        }
    }
    public static void main(Sting args[]){
        People people = new People();
        Education education = new Education(people); 
        Recognize(education);
    }    
}

這樣的話,即使學(xué)習(xí)歷程有變化都可以只在Education類中修改,不同國別學(xué)歷不同也可以繼承這個基類來實現(xiàn),大大提高了維護性和重用性。

設(shè)計模式是什么

概念上來說,如果一個問題反復(fù)發(fā)生,那么這個問題的解決方案就會被反復(fù)的使用,這種被頻繁使用的解決方案就是模式。設(shè)計模式是語言獨立的,主要用來解決程序設(shè)計的一般性問題(簡單說來就是組織代碼)。比如我們做菜,無論是西紅柿炒雞蛋還是紅燒排骨,做多了就發(fā)現(xiàn)這個行為是有著固定模式的:點火,切菜,入鍋,裝進盤子。于是乎炒菜便成為了一種模式,以后每種菜(菜品獨立)都可以沿襲這種模式,然后不同的菜實施細節(jié)不同而已。

按我理解,設(shè)計模式存在的終極意義就是代碼的可重用性(也就順帶了可維護性)。其實不只是設(shè)計模式,面向過程和面向?qū)ο蟊旧砥鋵嵰灿羞@個作用,只不過面向過程是通過函數(shù)來實現(xiàn),而面向?qū)ο笫峭ㄟ^類來實現(xiàn),而且面向?qū)ο蟀堰@個目的完成的更好一些。更徹底一些。

設(shè)計模式一般來說包含如下幾個方面:

模式名稱,設(shè)計模式的名稱是重要的,因為它會讓其他程序員能立刻理解你的代碼的目的

問題陳述,問題描述是用來說明這個模式的應(yīng)用的領(lǐng)域,即應(yīng)該在何時使用該模式

解決方案,解決方案描述了這個模型的執(zhí)行

效果,描述了模式應(yīng)用的效果及使用模式應(yīng)權(quán)衡的問題

下面我就通過一些常見的設(shè)計模式來說明設(shè)計模式是怎樣起到這種效果的。

工廠方法模式 問題陳述

在面向?qū)ο缶幊讨? 最通常的方法是一個 new 操作符產(chǎn)生一個對象實例,new 操作符就是用來構(gòu)造對象實例的。但是在一些情況下 , new操作符直接生成對象會帶來一些問題。舉例來說, 許多類型對象的創(chuàng)造需要一系列的步驟: 你可能需要計算或取得對象的初始設(shè)置 ;選擇生成哪個子對象實例 ; 或在生成你需要的對象之前必須先生成一些輔助功能的對象。在這些情況, 新對象的建立就是一個 “過程” ,不僅是一個操作,像一部大機器中的一個齒輪傳動。你如何能輕松方便地建立這么" 復(fù)雜 " 的對象即操作中不需要粘貼復(fù)制呢?

解決方案

定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。

工廠方法模式通用類圖:

在工廠方法模式中,抽象產(chǎn)品類Product負責(zé)定義產(chǎn)品的共性,實現(xiàn)對事物最抽象的定義;Creator為抽象創(chuàng)建類,也就是抽象工廠,具體如何創(chuàng)建產(chǎn)品類是由具體的實現(xiàn)工廠ConcreteCreator完成的。我們來看一個比較實用的通用源碼:


    //抽象產(chǎn)品類
    public abstract class Product {
        //產(chǎn)品類的公共方法
        public void method1(){
        //業(yè)務(wù)邏輯處理
        }
        //抽象方法
        public abstract void method2();   
    }

    //具體產(chǎn)品類,可以有多個
    public class ConcreteProduct1 extends Product {
        public void method2() {
        //業(yè)務(wù)邏輯處理
        }
    }
    public class ConcreteProduct2 extends Product {
        public void method2() {
        //業(yè)務(wù)邏輯處理
        }
    }

    //抽象工廠類
    public abstract class Creator {
         //創(chuàng)建一個產(chǎn)品對象,其輸入?yún)?shù)類型可以自行設(shè)置
         //通常為String、Enum、Class等,當(dāng)然也可以為空  
        public abstract  T createProduct(Class c);
    }

    //具體工廠類
    public class ConcreteCreator extends Creator {
        public  T createProduct(Class c){
            Product product=null;
            try {
                product = (Product)Class.forName(c.getName()).newInstance();
            } catch (Exception e) {
                //異常處理
            }
            return (T)product;   
        }
    }
    
    //場景類
    public class Client {
        public static void main(String[] args) {
        Creator creator = new ConcreteCreator();
        Product product = creator.createProduct(ConcreteProduct1.class);
        //繼續(xù)業(yè)務(wù)處理
        }
    }
效果

首先,代碼具有了良好的封裝性,結(jié)構(gòu)清晰。一個對象創(chuàng)建是有條件約束的,一個調(diào)用者需要一個具體的產(chǎn)品對象,只要知道這個產(chǎn)品的類名(或約束字符串)就可以了,不用知道創(chuàng)建對象的艱辛過程,降低模塊間的耦合。

其次,工廠方法模式的擴展性非常好。在增加產(chǎn)品類的情況下,只要適當(dāng)?shù)匦薷木唧w的工廠類或擴展一個工廠類就行了。

再次,屏蔽產(chǎn)品類。這一特點非常重要,產(chǎn)品類的實現(xiàn)如何變化,調(diào)用者都不需要關(guān)心,它只需要關(guān)心產(chǎn)品的接口,只要接口保持不變,系統(tǒng)中的上層模塊就不要發(fā)生變化。因為產(chǎn)品類的實例化工作是由工廠類負責(zé)的,一個產(chǎn)品對象具體由哪一個產(chǎn)品生成是由工廠類決定的。在數(shù)據(jù)庫開發(fā)中,大家應(yīng)該能夠深刻體會到工廠方法模式的好處:如果使用JDBC連接數(shù)據(jù)庫,數(shù)據(jù)庫從My SQL 切換到Oracle,需要改動的地方就是切換一下驅(qū)動名稱(前提
條件是SQL 語句是標(biāo)準(zhǔn)語句),其他的都不需要修改,這是工廠方法模式靈活性的一個直接案例。

最后,工廠方法模式是典型的解耦框架。

觀察者模式 問題陳述

如果一個事件A發(fā)生了需要觸發(fā)另一個事件B之時該怎么辦呢?直接修改A?顯然不是科學(xué)的程序設(shè)計,因為這樣就達不到A,B解耦合的目的,如果要修改B就得直接修改A;如果A同時還要觸發(fā)事件C怎么辦?又繼續(xù)往A里面添加?顯然這樣做最后會導(dǎo)致A臃腫不堪難以維護,這個時候就需要用到觀察者模式了。

解決方案

定義對象間一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。

觀察者模式通用類圖:

Subject被觀察者,定義被觀察者必須實現(xiàn)的職責(zé),它必須能夠動態(tài)地增加、取消觀察者。它一般是抽象類或者是實現(xiàn)類,僅僅完成作為被觀察者必須實現(xiàn)的職責(zé):管理觀察者并通知觀察者。

Observer觀察者,觀察者接收到消息后,即進行update(更新方法)操作,對接收到的信息進行處理。

ConcreteSubject具體的被觀察者,定義被觀察者自己的業(yè)務(wù)邏輯,同時定義對哪些事件進行通知。

ConcreteObserver具體的觀察者,每個觀察在接收到消息后的處理反應(yīng)是不同,各個觀察者有自己的處理邏輯。

通用代碼如下:

//被觀察者
public abstract class Subject {
    //定義一個觀察者數(shù)組
    private Vector obsVector = new Vector();
    //增加一個觀察者
    public void addObserver(Observer o){
        this.obsVector.add(o);
    }
    //刪除一個觀察者
    public void delObserver(Observer o){
        this.obsVector.remove(o);
    }
    //通知所有觀察者
    public void notifyObservers(){
        for(Observer o:this.obsVector){
        o.update();
        }
    }
}

//具體被觀察者
public class ConcreteSubject extends Subject {
    //具體的業(yè)務(wù)
    public void doSomething(){
        //do something
        
        super.notifyObservers();
    }
}

//觀察者
public interface Observer {
    //更新方法
    public void update();
}

//具體觀察者
public class ConcreteObserver implements Observer {
    //實現(xiàn)更新方法
    public void update() {
        System.out.println("接收到信息,并進行處理!");
    }
}

//場景類
public class Client {
    public static void main(String[] args) {
        //創(chuàng)建一個被觀察者
        ConcreteSubject subject = new ConcreteSubject();
        //定義一個觀察者
        Observer obs= new ConcreteObserver();
        //觀察者觀察被觀察者
        subject.addObserver(obs);
        //觀察者開始活動了
        subject.doSomething();
    }
}
效果

首先,觀察者和被觀察者之間是抽象耦合。如此設(shè)計,則不管是增加觀察者還是被觀察者都非常容易擴展,而且在Java中都已經(jīng)實現(xiàn)的抽象層級的定義,在系統(tǒng)擴展方面更是得心應(yīng)手。

其次,建立了一套觸發(fā)機制根據(jù)單一職責(zé)原則,每個類的職責(zé)是單一的,那么怎么把各個單一的職責(zé)串聯(lián)成真實世
界的復(fù)雜的邏輯關(guān)系呢?比如,我們?nèi)ゴ颢C,打死了一只母鹿,母鹿有三個幼崽,因失去了母鹿而餓死,尸體又被兩只禿鷹爭搶,因分配不均,禿鷹開始斗毆,然后羸弱的禿鷹死掉,生存下來的禿鷹,則因此擴大了地盤……這就是一個觸發(fā)機制,形成了一個觸發(fā)鏈。觀察者模式可以完美地實現(xiàn)這里的鏈條形式。

策略模式 問題陳述

如果你有很多的算法,他們只是有些許不同,你需要在不同場景使用不同的算法,這個時候是不是需要很多的if語句來判斷呢?可是if語句寫多了又不好維護;

如果你的算法規(guī)則不希望被別人看見,該怎么辦;

這一切都交給策略模式吧。

解決方案

定義一組算法,將每個算法都封裝起來,并且使它們之間可以互換。

策略模式的通用類圖:

Context 封裝角色,它也叫做上下文角色,起承上啟下封裝作用,屏蔽高層模塊對策略、算法的直接訪問,封裝可能存在的變化。

Strategy 抽象策略角色,策略、算法家族的抽象,通常為接口,定義每個策略或算法必須具有的方法和屬性。

ConcreteStrategy 具體策略角色,實現(xiàn)抽象策略中的操作,該類含有具體的算法。

通用代碼:

//抽象的策略角色
public interface Strategy {
    //策略模式的運算法則
    public void doSomething();
}

//具體策略角色
public class ConcreteStrategy1 implements Strategy {
    public void doSomething() {
        System.out.println("具體策略1的運算法則");
    }
}
public class ConcreteStrategy2 implements Strategy {
    public void doSomething() {
        System.out.println("具體策略2的運算法則");
    }
}

//封裝角色
public class Context {
    //抽象策略
    private Strategy strategy = null;
        //構(gòu)造函數(shù)設(shè)置具體策略
        public Context(Strategy _strategy){
        this.strategy = _strategy;
    }
    //封裝后的策略方法
    public void doAnythinig(){
        this.strategy.doSomething();
    }
}

//場景類
public class Client {
    public static void main(String[] args) {
        //聲明一個具體的策略
        Strategy strategy = new ConcreteStrategy1();
        //聲明上下文對象
        Context context = new Context(strategy);
        //執(zhí)行封裝后的方法
        context.doAnythinig();
    }
}
效果

首先,算法可以自由切換。這是策略模式本身定義的,只要實現(xiàn)抽象策略,它就成為策略家族的一個成員,通過封
裝角色對其進行封裝,保證對外提供“可自由切換”的策略。

其次,避免使用多重條件判斷。如果沒有策略模式,我們想想看會是什么樣子?一個策略家族有5個策略算法,一會要
使用A策略,一會要使用B策略,怎么設(shè)計呢?使用多重的條件語句?多重條件語句不易維護,而且出錯的概率大大增強。使用策略模式后,可以由其他模塊決定采用何種策略,策略家族對外提供的訪問接口就是封裝類,簡化了操作,同時避免了條件語句判斷。

最后,擴展性良好。在現(xiàn)有的系統(tǒng)中增加一個策略太容易了,只要實現(xiàn)接口就可以了,其他都不用修改,類似于一個可反復(fù)拆卸的插件,這大大地符合了OCP原則。

總結(jié)

還有很多設(shè)計模式我就不一一闡述了。大家可以找找資料看看。

我感覺設(shè)計模式說白了就是對面向?qū)ο缶幊痰囊环N補充,把面向?qū)ο蠓椒ㄋM_到的效果進一步完善罷了。但是這些模式還得在實戰(zhàn)中慢慢體會,以后編程過程中慢慢加深運用設(shè)計模式,相信會對我們寫出可復(fù)用、易維護的代碼有幫助的。

本文參考了《大話設(shè)計模式》,這本書通俗易懂,風(fēng)趣幽默,強烈推薦給大家~

歡迎訪問我的主頁(http://mageek.cn)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65720.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評論0 收藏0
  • 初探面向對象編程之oop設(shè)計模式

    摘要:為什么要采用面向?qū)ο缶幊探鉀Q問題更容易設(shè)計計算機程序就是為了解決人類的問題。面向?qū)ο缶幊绦枰獙I(yè)務(wù)及代碼的架構(gòu)是有一定的要求的。 1. 編程方式 我們目前的編程方式大體可以有以下三種編程方式: 順序編程 過程式編程 面向?qū)ο缶幊? 在講面向?qū)ο缶幊虝r先講一下什么是順序編程,什么是過程式編程,什么是面向?qū)ο缶幊蹋? 順序編程: 就是只用一個單線程去執(zhí)行一段代碼,執(zhí)行過程根據(jù)代碼依次從上...

    BingqiChen 評論0 收藏0
  • [零基礎(chǔ)學(xué)python]關(guān)于類的初步認識

    摘要:反對者在某些領(lǐng)域?qū)Υ擞枰苑裾J。下面再引用一段來自維基百科中關(guān)于的歷史。類的更嚴(yán)格的定義是由某種特定的元數(shù)據(jù)所組成的內(nèi)聚的包。類還可以有運行時表示形式元對象,它為操作與類相關(guān)的元數(shù)據(jù)提供了運行時支持。 在開始部分,請看官非常非常耐心地閱讀下面幾個枯燥的術(shù)語解釋,本來這不符合本教程的風(fēng)格,但是,請看官諒解,因為列位將來一定要閱讀枯燥的東西的。這些枯燥的屬于解釋,均來自維基百科。 1、問題...

    王巖威 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<