深刻分析面向對象中的對象概念

  OOP:面向對象編程,一提到面向對象,你們可能就想到類,接口。一說特性,你們可能張口就來:繼承、封裝、多態,那麼到底什麼樣的對象(類)纔是真正意義上的對象呢?特別是如今流行的DDD領域驅動設計思想,講究職責劃分,那麼如何定義一個對象(類)它應該具備的一些特性、行爲方法及承擔責任成爲關鍵。程序員

  一個看似簡單的問題,其實也是耐人思索,以前也在網上看到一些人關於討論類的設計問題,認爲設計類時不該該考慮數據庫,我以爲這只是實現真正的面向對象設計的基礎,也是前提條件,大多數程序員以前都是受面向過程編程思想的影響,我(夢在旅途)也不例外,一個須要求下來,首先就是想它須要存哪些數據,建哪些表,要定義哪些個方法來完成數據的存儲,整個過程基本是圍繞數據庫來進行的,我這裏稱之爲數據驅動編程,這樣開發其實也沒有錯,由於存在即有存在的道理,我也能夠分析出這種編程的優勢:開發速度快,執行效率高(沒有層級或層級以前只是簡單的轉發),缺點是:可讀性差,不利於後續的二次開發等,簡單的應用程序或某個獨立的核心模塊使用這種編程方式我以爲也是能夠的,但除此以外,我仍以爲合理的面向對象是有必要的,我這裏強調合理,是不要一味的盲目採用某個框架或某種設計模式,沒有最好的框架,一樣也沒有最好的設計模式,惟有最適合的框架與設計模式,那麼如何評估框架與設計是否合適,我認爲對象(類)的設計相當重要,下面就個人經驗及我所看到的現象來談談的對象的設計問題,因爲我不是什麼大牛,因此不免表達有誤的地方,請多包涵,固然也歡迎你們一塊兒討論。數據庫

1.對象是什麼?編程

在現實生活中,對象指的是某一個客觀存在的事物,它具備能識別它惟一性的屬性,好比:某人的某個品牌的某個型號的汽車,我這裏爲何用了多個某個,由於人+品牌+型號+汽車,就能肯定具對這個對象,而不是汽車這麼簡單,注意汽車並非一個對象,它只是表示的是某類事物,因此經過現實生活的分析,咱們能夠轉換思想到編程的世界中,來分析對象與類的區別。在編程中,類就是上面的汽車,而對象則是類的實例化,識別對象的惟一性從計算機的角色講,應該是內存堆中地址,每個地址肯定一個對象。設計模式

2.對象有什麼?框架

對象指的是具體的某個事物,除了有識別它惟一性的屬性外,它應該還有如下幾個特性:函數

1、狀態(也能夠簡單的稱之爲屬性):描述一個對象的特徵,這個特徵能夠永久的,也能夠是受外界影響而改變的,好比:某人的某個品牌的某個型號的汽車,若是這輛車從新噴漆,換了一種顏色,那麼的它此時的狀態,顏色被改變;若是車被賣給另一我的,那麼它此時的狀態,車的全部者也被改變了。post

代碼示例:學習

    public class Car //這是一個類
    {
        public Car(string owner,string brand,string model,string color)
        {
            this.Owner = owner;
            this.Brand = brand;
            this.Model = model;
            this.Color = color;
        }

        public string Owner { get; set; }

        public string Brand { get; set; }

        public string Model { get; set; }

        public string Color { get; set; }
    }


        public static void Main(string[] args)
        {
            var car = new Car("張三", "寶馬", "B01", "黑色");//這是一個對象
            car.Color = "紅色";//狀態被改變
            car.Owner = "李四";//狀態被改變
        }

2、行爲(也能夠簡單的稱之爲方法、函數):一個對象主動或被動去執行某種動做,好比:張三這我的,他吃飯,他看書,他睡覺等都是一種行爲,包括我如今寫博客也是一種行爲。行爲又分主動與被動,主動是指一個對象主觀意識的動做,好比:張三吃飯就是主動,而被動則是需另外一個對象來命令它來執行某種動做,好比:汽車啓動,啓動是一個行爲,但它不能本身啓動,須要駕駛人去經過汽車給定的啓動方法與步驟來請求汽車執行啓動,又或者說是取款機,取款機提供一個取款的行爲,而具體何時來取,取多少,均由人來告訴它。this

代碼示例:設計

    public class Car //這是一個類
    {
        public Car(string owner,string brand,string model,string color)
        {
            this.Owner = owner;
            this.Brand = brand;
            this.Model = model;
            this.Color = color;
        }

        public string Owner { get; set; }

        public string Brand { get; set; }

        public string Model { get; set; }

        public string Color { get; set; }

        public string Status { get; private set; }


        public Driver Driver { get; set; }

        public void Start() //啓動方法,被動
        {
            if (this.Driver!=null)
            {
                this.Status = "運行中";
            }
            else
            {
                throw new InvalidOperationException("沒有駕駛員,不能自動啓動!");
            }
        }

        public void Stop() //啓動方法,被動
        {
            this.Status = "中止";
        }
    }


    public class Driver
    {
        public string Name { get; set; }

        public Driver(string name)
        {
            this.Name = name;
        }

        public void  Drive(Car car)//駕駛,主動
        {
            car.Driver = this; //坐在車上
            car.Start();//啓動汽車,並運行
            car.Stop();//到達終點,中止汽車
        }
    }

    public class APP9
    {
        public static void Main(string[] args)
        {
            var car = new Car("張三", "寶馬", "B01", "黑色");//這是一個對象
            var driver = new Driver("李四");
            driver.Drive(car);//李四來開張三的車,現實生活中不能隨便借車開哦!~V~
        }
    }

有人看了上面的代碼後,可能再想,不是全部的對象都有行爲吧,既然是行爲,行爲又表明一種動做,那麼也只有能動的對象纔有行爲,不能動的對象就沒有,是這樣嗎?我在寫這篇博文前也思考了這個問題,開始也這樣認爲的,後面仔細一想,不對,應該是全部的對象都有行爲,就拿不動的東西來講吧,好比一張紙,紙自己本是不能動的,但若是你把它扔起來,那麼紙就具有了被動的移動方法,根據愛因斯坦的相對論,沒有絕對的靜止,只有相對的靜止,因此就看在什麼狀況下,參照物是什麼,有點扯遠了哈,迴歸正題,有人可能仍是不服,全部的對象都有行爲方法,那我不是非要對全部的類都定義方法嗎,否則就不符合真正的對象?我認爲不是這樣的,場景決定一個對象的狀態與方法,這也是下面我將要說明的角色定位的問題,這裏我能夠很負責任的告訴你,咱們全部的定義的對象都有行爲,只是你沒有意識到而矣,是什麼呢?那就是構造函數與析構函數,它們就是被動的行爲方法,這也是符合現實生活的對象,任何一個對象都有建立與毀滅,你敢說不是嗎?請舉出例子來吧!

3.對象角色定位

任何一個對象在不一樣的場景中應該有不一樣的狀態及行爲,好比:張三,張三在學校他是學生,具備學生的狀態及行爲,在公司工做他是員工,具備員工的狀態及行爲,取得駕照駕駛汽車,具有駕駛員的狀態及行爲,在圖書館看書,具有讀者的狀態與行爲。由此可知,對象是複雜的,類是具體一些,對象存在多變性,而類則應具有不變性,可能有人不明白,我這裏具體解釋一下,我這裏說的可變性,不是面向對象的那個多態,而是指對象角色的可變性,好比:學生類,那麼它就表示學生,它不可能還表示做者,固然它能夠表示人,但通常人不會這樣表示,而對象則不一樣,正如上面我講的張三的不一樣角色,他不一樣類的實例化,類不支持多重繼承,我以爲對的,由於一個類能夠表明一個角色,一個角色只能作這個角色的事情,好比:學生,他就是學習,老師,他就是教書,有人可能還會說,兼職多個角色,又是員工又是駕駛員,又是老師同時又是學生,是的,確實存在,但上面說過了,兼職的時候一個對象不可能同時作某個事情,好比:又是員工又是駕駛員,難道他同時工做又同時開車,有人說:出租車司機呀!好吧,你歷害,但仍然是角色不一樣,出租車司機開車就是工做,當他不工做開車時,他就是駕駛員。好了,說了這麼多,看是來看一下代碼示例吧!

    public class Person //人
    {
        public string IdNo{get;set;}

        public string Name { get; set; }

        public string Sex { get; set; }

        public double Height { get; set; }

        public double Weight { get; set; }

        public DateTime BirthDay { get; set; }

    }

    public class Post //文章
    {

        public string Title { get; set; }

        public string Content { get; set; }

        public Author Author { get; set; }
        
        public DateTime CreateDatetime { get; set; }

    }

    public class Author : Person //角色爲做者
    {
        public void Write(Post post)
        {
            //行爲
        }
    }


    public class Book //書
    {
        public string Name { get; set; }

        public DateTime IssuedDate { get; set; }

        public List<Post> Posts;

    }

    public class Library //圖書館
    {
        public string Name { get; set; }

        public List<Book> Books { get; set; }

        public void Borrow(Reader reader, IEnumerable<Book> books) //借出書,被動
        {
            Books.RemoveAll(b=>books.Contains(b));
            //其它操做
        }

        public void Return(Reader reader,IEnumerable<Book> books)//還入書,被動
        {
            Books.AddRange(books);
            //其它操做
        }
    }

    public class Reader : Person //角色爲讀者
    {
        public List<Book> Books { get; set; }

        public IEnumerable<Post> Read(Book book,params int[] pages) //讀書,主動
        {
            var posts = new List<Post>();
            if (pages != null)
            {
                foreach(int i in pages)
                {
                    posts.Add(book.Posts[i]);
                }
            }
            else
            {
                posts = book.Posts;
            }
            return posts;
        }

        public void Borrow(IEnumerable<Book> books, Library library) //主動借書
        {
            library.Borrow(this,books);
            Books.AddRange(books);
        }

        public void Return(IEnumerable<Book> books, Library library)//主動還書
        {
            library.Return(this, books);
            Books.RemoveAll(b => books.Contains(b));
        }

    }

    public class Driver:Person //角色爲駕駛員
    {
        public void Drive(Car car)
        {
            car.Driver = this;
            car.Start();
            car.Stop();
        }
    }

    public class Car
    {
        public Driver Driver { get; set; }

        public string Status{get;private set;}

        public void Start()
        {
            this.Status="運行中";
        }

        public void Stop()
        {
            this.Status="中止";
        }
    }

結 尾

我這裏只是定義,沒有列出運行時代碼。例子比較簡單,你們看一下就行了。最後要說明的是,對象雖然都有狀態與行爲,並且角色不一樣狀態與行爲也隨之不一樣,但在編程的世界裏,咱們能夠只關注咱們所關注的,好比:一個博客系統,咱們只關注做者,閱讀者,回覆者三個角色,從這三個角色應該具有的狀態與行爲進行設計相關的類,這樣就比較符合真實的對象了,也就不會出現你們常見的:狀態類-殭屍類(只有屬性,無方法),方法類-孤魂野鬼類(只有方法,無屬性)

好了,文章到這裏就結束了,面向對象的思想博大精深,很難一會兒所有說明白,但相信只要咱們在編程中多思考多總結就能提高咱們編程覺悟,有朝一日成爲大師。在此向大師、大牛們致敬,向大家學習,學習的道路永遠止境。這篇文章我花了一上午的時間,想了不少,寫得卻不是不少,但都是源自個人想法,若是幫助到你們了,還請支持推薦一下哦,很是感謝!

相關文章
相關標籤/搜索