欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java設(shè)計(jì)模式-創(chuàng)新互聯(lián)

目錄
  • 第 1 章 內(nèi)容介紹
    • 設(shè)計(jì)模式的目的
  • 第 2 章 設(shè)計(jì)模式七大原則
    • 2.1 設(shè)計(jì)模式的目的
    • 2.2 設(shè)計(jì)模式七大原則
    • 2.3 單一職責(zé)原則
      • 2.3.1基本介紹
      • 2.3.2應(yīng)用實(shí)例
      • 2.3.3單一職責(zé)原則注意事項(xiàng)和細(xì)節(jié)
    • 2.4 接口隔離原則(Interface Segregation Principle)
      • 2.4.1基本介紹
      • 2.4.2應(yīng)用實(shí)例
      • 2.4.3應(yīng)傳統(tǒng)方法的問(wèn)題和使用接口隔離原則改進(jìn)
    • 2.5 依賴(lài)倒轉(zhuǎn)原則
      • 2.5.1基本介紹
      • 2.5.2應(yīng)用實(shí)例
      • 2.5.3依賴(lài)關(guān)系傳遞的三種方式和應(yīng)用案例
      • 2.5.4依賴(lài)倒轉(zhuǎn)原則的注意事項(xiàng)和細(xì)節(jié)
    • 2.6 里氏替換原則
      • 2.6.1OO 中的繼承性的思考和說(shuō)明
      • 2.6.2基本介紹
      • 2.6.3一個(gè)程序引出的問(wèn)題和思考
      • 2.6.4解決方法
    • 2.7 開(kāi)閉原則
      • 2.7.1基本介紹
      • 2.7.2看下面一段代碼
      • 2.7.3方式 1 的優(yōu)缺點(diǎn)
      • 2.7.4改進(jìn)的思路分析
    • 2.8 迪米特法則
      • 2.8.1基本介紹
      • 2.8.2應(yīng)用實(shí)例
      • 2.8.3應(yīng)用實(shí)例改進(jìn)
      • 2.8.4迪米特法則注意事項(xiàng)和細(xì)節(jié)
    • 2.9 合成復(fù)用原則(Composite Reuse Principle)
      • 2.9.1基本介紹
    • 2.10 設(shè)計(jì)原則核心思想
  • 第 3 章UML 類(lèi)圖
    • 3.1 UML 基本介紹
    • 3.2 UML 圖
    • 3.3 UML 類(lèi)圖
    • 3.4 類(lèi)圖—依賴(lài)關(guān)系(Dependence)
    • 3.5 類(lèi)圖—泛化關(guān)系(generalization)
    • 3.6 類(lèi)圖—實(shí)現(xiàn)關(guān)系(Implementation)
    • 3.7 類(lèi)圖—關(guān)聯(lián)關(guān)系(Association)
    • 3.8 類(lèi)圖—聚合關(guān)系(Aggregation)
      • 3.8.1基本介紹
      • 3.8.2應(yīng)用實(shí)例
    • 3.9 類(lèi)圖—組合關(guān)系(Composition)
      • 3.9.1基本介紹
      • 3.9.2應(yīng)用案例
  • 第 4 章設(shè)計(jì)模式概述
    • 4.1 掌握設(shè)計(jì)模式的層次
    • 4.2 設(shè)計(jì)模式介紹
    • 4.3 設(shè)計(jì)模式類(lèi)型
  • 第 5 章單例設(shè)計(jì)模式
    • 5.1 單例設(shè)計(jì)模式介紹
    • 5.2 單例設(shè)計(jì)模式八種方式
    • 5.3 餓漢式(靜態(tài)常量)
    • 5.4 餓漢式(靜態(tài)代碼塊)
    • 5.5 懶漢式(線(xiàn)程不安全)
    • 5.6 懶漢式(線(xiàn)程安全,同步方法)
    • 5.7 懶漢式(線(xiàn)程安全,同步代碼塊)
    • 5.8 雙重檢查
    • 5.10 枚舉
    • 5.11 單例模式在 JDK 應(yīng)用的源碼分析
      • 5.11.1 單例模式在 JDK 應(yīng)用的源碼分析
    • 5.12 單例模式注意事項(xiàng)和細(xì)節(jié)說(shuō)明

站在用戶(hù)的角度思考問(wèn)題,與客戶(hù)深入溝通,找到寧夏網(wǎng)站設(shè)計(jì)與寧夏網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶(hù)體驗(yàn)好的作品,建站類(lèi)型包括:成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋寧夏地區(qū)。第 1 章 內(nèi)容介紹 設(shè)計(jì)模式的目的

編寫(xiě)軟件過(guò)程中,程序員面臨著來(lái)自 耦合性,內(nèi)聚性以及可維護(hù)性,可擴(kuò)展性,重用性,靈活性等多方面的挑戰(zhàn),設(shè)計(jì)模式是為了讓程序(軟件),具有更好

  1. 代碼重用性 (即:相同功能的代碼,不用多次編寫(xiě))
  2. 可讀性 (即:編程規(guī)范性, 便于其他程序員的閱讀和理解)
  3. 可擴(kuò)展性 (即:當(dāng)需要增加新的功能時(shí),非常的方便,稱(chēng)為可維護(hù))
  4. 可靠性 (即:當(dāng)我們?cè)黾有碌墓δ芎?,?duì)原來(lái)的功能沒(méi)有影響)
  5. 使程序呈現(xiàn)高內(nèi)聚,低耦合的特性
第 2 章 設(shè)計(jì)模式七大原則 2.1 設(shè)計(jì)模式的目的

編寫(xiě)軟件過(guò)程中,程序員面臨著來(lái)自 耦合性,內(nèi)聚性以及可維護(hù)性,可擴(kuò)展性,重用性,靈活性等多方面的挑戰(zhàn),設(shè)計(jì)模式是為了讓程序(軟件),具有更好

  1. 代碼重用性 (即:相同功能的代碼,不用多次編寫(xiě))
  2. 可讀性 (即:編程規(guī)范性, 便于其他程序員的閱讀和理解)
  3. 可擴(kuò)展性 (即:當(dāng)需要增加新的功能時(shí),非常的方便,稱(chēng)為可維護(hù))
  4. 可靠性 (即:當(dāng)我們?cè)黾有碌墓δ芎?,?duì)原來(lái)的功能沒(méi)有影響)
  5. 使程序呈現(xiàn)高內(nèi)聚,低耦合的特性
2.2 設(shè)計(jì)模式七大原則

設(shè)計(jì)模式原則,其實(shí)就是程序員在編程時(shí),應(yīng)當(dāng)遵守的原則,也是各種設(shè)計(jì)模式的基礎(chǔ)(即:設(shè)計(jì)模式為什么這樣設(shè)計(jì)的依據(jù))
** 設(shè)計(jì)模式常用的七大原則有:**

  1. 單一職責(zé)原則
  2. 接口隔離原則
  3. 依賴(lài)倒轉(zhuǎn)(倒置)原則
  4. 里氏替換原則
  5. 開(kāi)閉原則
  6. 迪米特法則
  7. 合成復(fù)用原則
2.3 單一職責(zé)原則 2.3.1基本介紹

對(duì)類(lèi)來(lái)說(shuō)的,即一個(gè)類(lèi)應(yīng)該只負(fù)責(zé)一項(xiàng)職責(zé)。如類(lèi) A 負(fù)責(zé)兩個(gè)不同職責(zé):職責(zé) 1,職責(zé)2。當(dāng)職責(zé)1 需求變更而改變 A 時(shí),可能造成職責(zé) 2 執(zhí)行錯(cuò)誤,所以需要將類(lèi) A 的粒度分解為 A1,A2

2.3.2應(yīng)用實(shí)例

以交通工具案例`

  1. 方案 1
public class SingleResponsibility1 {public static void main(String[] args) {Vehicle vehicle = new Vehicle();
            vehicle.run("摩托車(chē)");
            vehicle.run("汽車(chē)");
            vehicle.run("飛機(jī)");
        }
    }

       // 交通工具類(lèi)
// 方式 1
// 1. 在方式 1 的 run 方法中,違反了單一職責(zé)原則
// 2. 解決的方案非常的簡(jiǎn)單,根據(jù)交通工具運(yùn)行方法不同,分解成不同類(lèi)即可
        class Vehicle {public void run(String vehicle) {System.out.println(vehicle + " 在公路上運(yùn)行....");
            }
        }
  1. 方案 2
public class SingleResponsibility2 {public static void main(String[] args) {RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("摩托車(chē)");
        roadVehicle.run("汽車(chē)");
        AirVehicle airVehicle = new AirVehicle();
        airVehicle.run("飛機(jī)");
    }
}

//方案 2 的分析
//1. 遵守單一職責(zé)原則
//2. 但是這樣做的改動(dòng)很大,即將類(lèi)分解,同時(shí)修改客戶(hù)端
//3. 改進(jìn):直接修改 Vehicle 類(lèi),改動(dòng)的代碼會(huì)比較少=>方案 3
class RoadVehicle {public void run(String vehicle) {System.out.println(vehicle + "公路運(yùn)行");
    }
}

class AirVehicle {public void run(String vehicle) {System.out.println(vehicle + "天空運(yùn)行");
    }
}

class WaterVehicle {public void run(String vehicle) {System.out.println(vehicle + "水中運(yùn)行");
    }
}
  1. 方案 3
package com.atguigu.principle.singleresponsibility;

public class SingleResponsibility3 {public static void main(String[] args) {		Vehicle2 vehicle2  = new Vehicle2();
		vehicle2.run("汽車(chē)");
		vehicle2.runWater("輪船");
		vehicle2.runAir("飛機(jī)");
	}

}


//方式3的分析
//1. 這種修改方法沒(méi)有對(duì)原來(lái)的類(lèi)做大的修改,只是增加方法
//2. 這里雖然沒(méi)有在類(lèi)這個(gè)級(jí)別上遵守單一職責(zé)原則,但是在方法級(jí)別上,仍然是遵守單一職責(zé)
class Vehicle2 {public void run(String vehicle) {//處理
		
		System.out.println(vehicle + " 在公路上運(yùn)行....");
		
	}
	
	public void runAir(String vehicle) {System.out.println(vehicle + " 在天空上運(yùn)行....");
	}
	
	public void runWater(String vehicle) {System.out.println(vehicle + " 在水中行....");
	}
	
	//方法2.
	//..
	//..
	
	//...
}
2.3.3單一職責(zé)原則注意事項(xiàng)和細(xì)節(jié)
  1. 降低類(lèi)的復(fù)雜度,一個(gè)類(lèi)只負(fù)責(zé)一項(xiàng)職責(zé)。
  2. 提高類(lèi)的可讀性,可維護(hù)性
  3. 降低變更引起的風(fēng)險(xiǎn)
  4. 通常情況下,我們應(yīng)當(dāng)遵守單一職責(zé)原則,只有邏輯足夠簡(jiǎn)單,才可以在代碼級(jí)違反單一職責(zé)原則;只有類(lèi)中方法數(shù)量足夠少,可以在方法級(jí)別保持單一職責(zé)原則
2.4 接口隔離原則(Interface Segregation Principle) 2.4.1基本介紹
  1. 客戶(hù)端不應(yīng)該依賴(lài)它不需要的接口,即一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上
  2. 先看一張圖
    在這里插入圖片描述
  3. 類(lèi) A 通過(guò)接口 Interface1 依賴(lài)類(lèi) B,類(lèi) C 通過(guò)接口 Interface1 依賴(lài)類(lèi) D,如果接口Interface1 對(duì)于類(lèi)A和類(lèi)C來(lái)說(shuō)不是最小接口,那么類(lèi) B 和類(lèi) D 必須去實(shí)現(xiàn)他們不需要的方法。
  4. 按隔離原則應(yīng)當(dāng)這樣處理:
    將接口 Interface1 拆分為獨(dú)立的幾個(gè)接口(這里我們拆分成 3 個(gè)接口),類(lèi) A 和類(lèi)C 分別與他們需要的接口建立依賴(lài)關(guān)系。也就是采用接口隔離原則
2.4.2應(yīng)用實(shí)例
  1. 類(lèi) A 通過(guò)接口 Interface1 依賴(lài)類(lèi) B,類(lèi) C 通過(guò)接口 Interface1 依賴(lài)類(lèi) D,請(qǐng)編寫(xiě)代碼完成此應(yīng)用實(shí)例。
  2. 看代碼-沒(méi)有使用接口隔離原則代碼
public class Segregation1 {public static void main(String[] args) {// TODO Auto-generated method stub

	}

}

//接口
interface Interface1 {void operation1();
	void operation2();
	void operation3();
	void operation4();
	void operation5();
}

class B implements Interface1 {public void operation1() {System.out.println("B 實(shí)現(xiàn)了 operation1");
	}
	
	public void operation2() {System.out.println("B 實(shí)現(xiàn)了 operation2");
	}
	public void operation3() {System.out.println("B 實(shí)現(xiàn)了 operation3");
	}
	public void operation4() {System.out.println("B 實(shí)現(xiàn)了 operation4");
	}
	public void operation5() {System.out.println("B 實(shí)現(xiàn)了 operation5");
	}
}

class D implements Interface1 {public void operation1() {System.out.println("D 實(shí)現(xiàn)了 operation1");
	}
	
	public void operation2() {System.out.println("D 實(shí)現(xiàn)了 operation2");
	}
	public void operation3() {System.out.println("D 實(shí)現(xiàn)了 operation3");
	}
	public void operation4() {System.out.println("D 實(shí)現(xiàn)了 operation4");
	}
	public void operation5() {System.out.println("D 實(shí)現(xiàn)了 operation5");
	}
}

class A {//A 類(lèi)通過(guò)接口Interface1 依賴(lài)(使用) B類(lèi),但是只會(huì)用到1,2,3方法
	public void depend1(Interface1 i) {i.operation1();
	}
	public void depend2(Interface1 i) {i.operation2();
	}
	public void depend3(Interface1 i) {i.operation3();
	}
}
  
class C {//C 類(lèi)通過(guò)接口Interface1 依賴(lài)(使用) D類(lèi),但是只會(huì)用到1,4,5方法
	public void depend1(Interface1 i) {i.operation1();
	}
	public void depend4(Interface1 i) {i.operation4();
	}
	public void depend5(Interface1 i) {i.operation5();
	}
}
2.4.3應(yīng)傳統(tǒng)方法的問(wèn)題和使用接口隔離原則改進(jìn)
  1. 類(lèi) A 通過(guò)接口 Interface1 依賴(lài)類(lèi) B,類(lèi) C 通過(guò)接口 Interface1 依賴(lài)類(lèi) D,如果接口Interface1 對(duì)于類(lèi)A和類(lèi)C來(lái)說(shuō)不是最小接口,那么類(lèi) B 和類(lèi) D 必須去實(shí)現(xiàn)他們不需要的方法
  2. 將接口 Interface1 拆分為獨(dú)立的幾個(gè)接口,類(lèi) A 和類(lèi) C 分別與他們需要的接口建立依賴(lài)關(guān)系。也就是采用接口隔離原則
  3. 接口 Interface1 中出現(xiàn)的方法,根據(jù)實(shí)際情況拆分為三個(gè)接口
    在這里插入圖片描述
  4. 代碼實(shí)現(xiàn)
package com.atguigu.principle.segregation.improve;

public class Segregation1 {public static void main(String[] args) {// TODO Auto-generated method stub
		// 使用一把
		A a = new A();
		a.depend1(new B()); // A類(lèi)通過(guò)接口去依賴(lài)B類(lèi)
		a.depend2(new B());
		a.depend3(new B());

		C c = new C();

		c.depend1(new D()); // C類(lèi)通過(guò)接口去依賴(lài)(使用)D類(lèi)
		c.depend4(new D());
		c.depend5(new D());

	}

}

// 接口1
interface Interface1 {void operation1();

}

// 接口2
interface Interface2 {void operation2();

	void operation3();
}

// 接口3
interface Interface3 {void operation4();

	void operation5();
}

class B implements Interface1, Interface2 {public void operation1() {System.out.println("B 實(shí)現(xiàn)了 operation1");
	}

	public void operation2() {System.out.println("B 實(shí)現(xiàn)了 operation2");
	}

	public void operation3() {System.out.println("B 實(shí)現(xiàn)了 operation3");
	}

}

class D implements Interface1, Interface3 {public void operation1() {System.out.println("D 實(shí)現(xiàn)了 operation1");
	}

	public void operation4() {System.out.println("D 實(shí)現(xiàn)了 operation4");
	}

	public void operation5() {System.out.println("D 實(shí)現(xiàn)了 operation5");
	}
}

class A {// A 類(lèi)通過(guò)接口Interface1,Interface2 依賴(lài)(使用) B類(lèi),但是只會(huì)用到1,2,3方法
	public void depend1(Interface1 i) {i.operation1();
	}

	public void depend2(Interface2 i) {i.operation2();
	}

	public void depend3(Interface2 i) {i.operation3();
	}
}

class C {// C 類(lèi)通過(guò)接口Interface1,Interface3 依賴(lài)(使用) D類(lèi),但是只會(huì)用到1,4,5方法
	public void depend1(Interface1 i) {i.operation1();
	}

	public void depend4(Interface3 i) {i.operation4();
	}

	public void depend5(Interface3 i) {i.operation5();
	}
}
2.5 依賴(lài)倒轉(zhuǎn)原則 2.5.1基本介紹

依賴(lài)倒轉(zhuǎn)原則(Dependence Inversion Principle)是指:

  1. 高層模塊不應(yīng)該依賴(lài)低層模塊,二者都應(yīng)該依賴(lài)其抽象
  2. 抽象不應(yīng)該依賴(lài)細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴(lài)抽象
  3. 依賴(lài)倒轉(zhuǎn)(倒置)的中心思想是面向接口編程
  4. 依賴(lài)倒轉(zhuǎn)原則是基于這樣的設(shè)計(jì)理念:相對(duì)于細(xì)節(jié)的多變性,抽象的東西要穩(wěn)定的多。以抽象為基礎(chǔ)搭建的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)的架構(gòu)要穩(wěn)定的多。在 java 中,抽象指的是接口或抽象類(lèi),細(xì)節(jié)就是具體的實(shí)現(xiàn)類(lèi)
  5. 使用接口或抽象類(lèi)的目的是制定好規(guī)范,而不涉及任何具體的操作,把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實(shí)現(xiàn)類(lèi)去完成
2.5.2應(yīng)用實(shí)例

請(qǐng)編程完成 Person 接收消息 的功能。

  1. 實(shí)現(xiàn)方案 1 + 分析說(shuō)明
public class DependecyInversion {public static void main(String[] args) {Person person = new Person();
		person.receive(new Email());
	}

}


class Email {public String getInfo() {return "電子郵件信息: hello,world";
	}
}

//完成Person接收消息的功能
//方式1分析
//1. 簡(jiǎn)單,比較容易想到
//2. 如果我們獲取的對(duì)象是 微信,短信等等,則新增類(lèi),同時(shí)Perons也要增加相應(yīng)的接收方法
//3. 解決思路:引入一個(gè)抽象的接口IReceiver, 表示接收者, 這樣Person類(lèi)與接口IReceiver發(fā)生依賴(lài)
//   因?yàn)镋mail, WeiXin 等等屬于接收的范圍,他們各自實(shí)現(xiàn)IReceiver 接口就ok, 這樣我們就符號(hào)依賴(lài)倒轉(zhuǎn)原則
class Person {public void receive(Email email ) {System.out.println(email.getInfo());
	}
}
  1. 實(shí)現(xiàn)方案 2(依賴(lài)倒轉(zhuǎn)) + 分析說(shuō)明
package com.atguigu.principle.inversion.improve;

public class DependecyInversion {public static void main(String[] args) {//客戶(hù)端無(wú)需改變
		Person person = new Person();
		person.receive(new Email());
		
		person.receive(new WeiXin());
	}

}

//定義接口
interface IReceiver {public String getInfo();
}

class Email implements IReceiver {public String getInfo() {return "電子郵件信息: hello,world";
	}
}

//增加微信
class WeiXin implements IReceiver {public String getInfo() {return "微信信息: hello,ok";
	}
}

//方式2
class Person {//這里我們是對(duì)接口的依賴(lài)
	public void receive(IReceiver receiver ) {System.out.println(receiver.getInfo());
	}
}
2.5.3依賴(lài)關(guān)系傳遞的三種方式和應(yīng)用案例
  1. 接口傳遞
    應(yīng)用案例代碼
  2. 構(gòu)造方法傳遞
    應(yīng)用案例代碼
  3. setter 方式傳遞
    應(yīng)用案例代碼
  4. 代碼演示
package com.atguigu.principle.inversion.improve;

public class DependencyPass {public static void main(String[] args) {// TODO Auto-generated method stub
		ChangHong changHong = new ChangHong();
//		OpenAndClose openAndClose = new OpenAndClose();
//		openAndClose.open(changHong);
		
		//通過(guò)構(gòu)造器進(jìn)行依賴(lài)傳遞
//		OpenAndClose openAndClose = new OpenAndClose(changHong);
//		openAndClose.open();
		//通過(guò)setter方法進(jìn)行依賴(lài)傳遞
		OpenAndClose openAndClose = new OpenAndClose();
		openAndClose.setTv(changHong);
		openAndClose.open();

	}

}

// 方式1: 通過(guò)接口傳遞實(shí)現(xiàn)依賴(lài)
// 開(kāi)關(guān)的接口
// interface IOpenAndClose {// public void open(ITV tv); //抽象方法,接收接口
// }
//
// interface ITV { //ITV接口
// public void play();
// }
// 
// class ChangHong implements ITV {//
//	@Override
//	public void play() {//		// TODO Auto-generated method stub
//		System.out.println("長(zhǎng)虹電視機(jī),打開(kāi)");
//	}
//	 
// }
 實(shí)現(xiàn)接口
// class OpenAndClose implements IOpenAndClose{// public void open(ITV tv){// tv.play();
// }
// }

// 方式2: 通過(guò)構(gòu)造方法依賴(lài)傳遞
// interface IOpenAndClose {// public void open(); //抽象方法
// }
// interface ITV { //ITV接口
// public void play();
// }
// class OpenAndClose implements IOpenAndClose{// public ITV tv; //成員
// public OpenAndClose(ITV tv){ //構(gòu)造器
// this.tv = tv;
// }
// public void open(){// this.tv.play();
// }
// }


// 方式3 , 通過(guò)setter方法傳遞
interface IOpenAndClose {public void open(); // 抽象方法

	public void setTv(ITV tv);
}

interface ITV {// ITV接口
	public void play();
}

class OpenAndClose implements IOpenAndClose {private ITV tv;

	public void setTv(ITV tv) {this.tv = tv;
	}

	public void open() {this.tv.play();
	}
}

class ChangHong implements ITV {@Override
	public void play() {// TODO Auto-generated method stub
		System.out.println("長(zhǎng)虹電視機(jī),打開(kāi)");
	}
	 
}
2.5.4依賴(lài)倒轉(zhuǎn)原則的注意事項(xiàng)和細(xì)節(jié)
  1. 低層模塊盡量都要有抽象類(lèi)或接口,或者兩者都有,程序穩(wěn)定性更好.
  2. 變量的聲明類(lèi)型盡量是抽象類(lèi)或接口, 這樣我們的變量引用和實(shí)際對(duì)象間,就存在一個(gè)緩沖層,利于程序擴(kuò)展和優(yōu)化
  3. 繼承時(shí)遵循里氏替換原則
2.6 里氏替換原則 2.6.1OO 中的繼承性的思考和說(shuō)明
  1. 繼承包含這樣一層含義:父類(lèi)中凡是已經(jīng)實(shí)現(xiàn)好的方法,實(shí)際上是在設(shè)定規(guī)范和契約,雖然它不強(qiáng)制要求所有的子類(lèi)必須遵循這些契約,但是如果子類(lèi)對(duì)這些已經(jīng)實(shí)現(xiàn)的方法任意修改,就會(huì)對(duì)整個(gè)繼承體系造成破壞。
  2. 繼承在給程序設(shè)計(jì)帶來(lái)便利的同時(shí),也帶來(lái)了弊端。比如使用繼承會(huì)給程序帶來(lái)侵入性,程序的可移植性降低,增加對(duì)象間的耦合性,如果一個(gè)類(lèi)被其他的類(lèi)所繼承,則當(dāng)這個(gè)類(lèi)需要修改時(shí),必須考慮到所有的子類(lèi),并且父類(lèi)修改后,所有涉及到子類(lèi)的功能都有可能產(chǎn)生故障
  3. 問(wèn)題提出:在編程中,如何正確的使用繼承? =>里氏替換原則
2.6.2基本介紹
  1. 里氏替換原則(Liskov Substitution Principle)在 1988 年,由麻省理工學(xué)院的以為姓里的女士提出的。2) 如果對(duì)每個(gè)類(lèi)型為 T1 的對(duì)象 o1,都有類(lèi)型為 T2 的對(duì)象 o2,使得以 T1 定義的所有程序P 在所有的對(duì)象o1都代換成 o2 時(shí),程序 P 的行為沒(méi)有發(fā)生變化,那么類(lèi)型 T2 是類(lèi)型 T1 的子類(lèi)型。換句話(huà)說(shuō),所有引用基類(lèi)的地方必須能透明地使用其子類(lèi)的對(duì)象。
  2. 在使用繼承時(shí),遵循里氏替換原則,在子類(lèi)中盡量不要重寫(xiě)父類(lèi)的方法
  3. 里氏替換原則告訴我們,繼承實(shí)際上讓兩個(gè)類(lèi)耦合性增強(qiáng)了,在適當(dāng)?shù)那闆r下,可以通過(guò)聚合,組合,依賴(lài)來(lái)解決問(wèn)題 。.
2.6.3一個(gè)程序引出的問(wèn)題和思考

該看個(gè)程序, 思考下問(wèn)題和解決思路

public class Liskov {public static void main(String[] args) {// TODO Auto-generated method stub
		A a = new A();
		System.out.println("11-3=" + a.func1(11, 3));
		System.out.println("1-8=" + a.func1(1, 8));

		System.out.println("-----------------------");
		B b = new B();
		System.out.println("11-3=" + b.func1(11, 3));//這里本意是求出11-3
		System.out.println("1-8=" + b.func1(1, 8));// 1-8
		System.out.println("11+3+9=" + b.func2(11, 3));
		
		

	}

}

// A類(lèi)
class A {// 返回兩個(gè)數(shù)的差
	public int func1(int num1, int num2) {return num1 - num2;
	}
}

// B類(lèi)繼承了A
// 增加了一個(gè)新功能:完成兩個(gè)數(shù)相加,然后和9求和
class B extends A {//這里,重寫(xiě)了A類(lèi)的方法, 可能是無(wú)意識(shí)
	public int func1(int a, int b) {return a + b;
	}

	public int func2(int a, int b) {return func1(a, b) + 9;
	}
}
2.6.4解決方法
  1. 我們發(fā)現(xiàn)原來(lái)運(yùn)行正常的相減功能發(fā)生了錯(cuò)誤。原因就是類(lèi) B 無(wú)意中重寫(xiě)了父類(lèi)的方法,造成原有功能出現(xiàn)錯(cuò)誤。在實(shí)際編程中,我們常常會(huì)通過(guò)重寫(xiě)父類(lèi)的方法完成新的功能,這樣寫(xiě)起來(lái)雖然簡(jiǎn)單,但整個(gè)繼承體系的復(fù)用性會(huì)比較差。特別是運(yùn)行多態(tài)比較頻繁的時(shí)候
  2. 通用的做法是:原來(lái)的父類(lèi)和子類(lèi)都繼承一個(gè)更通俗的基類(lèi),原有的繼承關(guān)系去掉,采用依賴(lài),聚合,組合等關(guān)系代替.
  3. 改進(jìn)方案
    在這里插入圖片描述
    代碼實(shí)現(xiàn)
public class Liskov {public static void main(String[] args) {// TODO Auto-generated method stub
		A a = new A();
		System.out.println("11-3=" + a.func1(11, 3));
		System.out.println("1-8=" + a.func1(1, 8));

		System.out.println("-----------------------");
		B b = new B();
		//因?yàn)锽類(lèi)不再繼承A類(lèi),因此調(diào)用者,不會(huì)再func1是求減法
		//調(diào)用完成的功能就會(huì)很明確
		System.out.println("11+3=" + b.func1(11, 3));//這里本意是求出11+3
		System.out.println("1+8=" + b.func1(1, 8));// 1+8
		System.out.println("11+3+9=" + b.func2(11, 3));
		
		
		//使用組合仍然可以使用到A類(lèi)相關(guān)方法
		System.out.println("11-3=" + b.func3(11, 3));// 這里本意是求出11-3
		

	}

}

//創(chuàng)建一個(gè)更加基礎(chǔ)的基類(lèi)
class Base {//把更加基礎(chǔ)的方法和成員寫(xiě)到Base類(lèi)
}

// A類(lèi)
class A extends Base {// 返回兩個(gè)數(shù)的差
	public int func1(int num1, int num2) {return num1 - num2;
	}
}

// B類(lèi)繼承了A
// 增加了一個(gè)新功能:完成兩個(gè)數(shù)相加,然后和9求和
class B extends Base {//如果B需要使用A類(lèi)的方法,使用組合關(guān)系
	private A a = new A();
	
	//這里,重寫(xiě)了A類(lèi)的方法, 可能是無(wú)意識(shí)
	public int func1(int a, int b) {return a + b;
	}

	public int func2(int a, int b) {return func1(a, b) + 9;
	}
	
	//我們?nèi)匀幌胧褂肁的方法
	public int func3(int a, int b) {return this.a.func1(a, b);
	}
}
2.7 開(kāi)閉原則 2.7.1基本介紹
  1. 開(kāi)閉原則(Open Closed Principle)是編程中最基礎(chǔ)、最重要的設(shè)計(jì)原則
  2. 一個(gè)軟件實(shí)體如類(lèi),模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放(對(duì)提供方),對(duì)修改關(guān)閉(對(duì)使用方)。用抽象構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。
  3. 當(dāng)軟件需要變化時(shí),盡量通過(guò)擴(kuò)展軟件實(shí)體的行為來(lái)實(shí)現(xiàn)變化,而不是通過(guò)修改已有的代碼來(lái)實(shí)現(xiàn)變化。
  4. 編程中遵循其它原則,以及使用設(shè)計(jì)模式的目的就是遵循開(kāi)閉原則。
2.7.2看下面一段代碼

? 看一個(gè)畫(huà)圖形的功能。
類(lèi)圖設(shè)計(jì),如下:
在這里插入圖片描述
? 代碼演示

package com.atguigu.principle.ocp;

public class Ocp {public static void main(String[] args) {//使用看看存在的問(wèn)題
		GraphicEditor graphicEditor = new GraphicEditor();
		graphicEditor.drawShape(new Rectangle());
		graphicEditor.drawShape(new Circle());
		graphicEditor.drawShape(new Triangle());
	}

}

//這是一個(gè)用于繪圖的類(lèi) [使用方]
class GraphicEditor {//接收Shape對(duì)象,然后根據(jù)type,來(lái)繪制不同的圖形
	public void drawShape(Shape s) {if (s.m_type == 1)
			drawRectangle(s);
		else if (s.m_type == 2)
			drawCircle(s);
		else if (s.m_type == 3)
			drawTriangle(s);
	}

	//繪制矩形
	public void drawRectangle(Shape r) {System.out.println(" 繪制矩形 ");
	}

	//繪制圓形
	public void drawCircle(Shape r) {System.out.println(" 繪制圓形 ");
	}
	
	//繪制三角形
	public void drawTriangle(Shape r) {System.out.println(" 繪制三角形 ");
	}
}

//Shape類(lèi),基類(lèi)
class Shape {int m_type;
}

class Rectangle extends Shape {Rectangle() {super.m_type = 1;
	}
}

class Circle extends Shape {Circle() {super.m_type = 2;
	}
}

//新增畫(huà)三角形
class Triangle extends Shape {Triangle() {super.m_type = 3;
	}
}
2.7.3方式 1 的優(yōu)缺點(diǎn)
  1. 優(yōu)點(diǎn)是比較好理解,簡(jiǎn)單易操作。
  2. 缺點(diǎn)是違反了設(shè)計(jì)模式的 ocp 原則,即對(duì)擴(kuò)展開(kāi)放(提供方),對(duì)修改關(guān)閉(使用方)。即當(dāng)我們給類(lèi)增加新功能的時(shí)候,盡量不修改代碼,或者盡可能少修改代碼.
  3. 比如我們這時(shí)要新增加一個(gè)圖形種類(lèi) 三角形,我們需要做如下修改,修改的地方較多
  4. 代碼演示
    方式 1 的改進(jìn)的思路分析
2.7.4改進(jìn)的思路分析

思路:把創(chuàng)建 Shape 類(lèi)做成抽象類(lèi),并提供一個(gè)抽象的 draw 方法,讓子類(lèi)去實(shí)現(xiàn)即可,這樣我們有新的圖形種類(lèi)時(shí),只需要讓新的圖形類(lèi)繼承 Shape,并實(shí)現(xiàn) draw 方法即可,使用方的代碼就不需要修->滿(mǎn)足了開(kāi)閉原則
改進(jìn)后的代碼:

package com.atguigu.principle.ocp.improve;

public class Ocp {public static void main(String[] args) {//使用看看存在的問(wèn)題
		GraphicEditor graphicEditor = new GraphicEditor();
		graphicEditor.drawShape(new Rectangle());
		graphicEditor.drawShape(new Circle());
		graphicEditor.drawShape(new Triangle());
		graphicEditor.drawShape(new OtherGraphic());
	}

}

//這是一個(gè)用于繪圖的類(lèi) [使用方]
class GraphicEditor {//接收Shape對(duì)象,調(diào)用draw方法
	public void drawShape(Shape s) {s.draw();
	}

	
}

//Shape類(lèi),基類(lèi)
abstract class Shape {int m_type;
	
	public abstract void draw();//抽象方法
}

class Rectangle extends Shape {Rectangle() {super.m_type = 1;
	}

	@Override
	public void draw() {// TODO Auto-generated method stub
		System.out.println(" 繪制矩形 ");
	}
}

class Circle extends Shape {Circle() {super.m_type = 2;
	}
	@Override
	public void draw() {// TODO Auto-generated method stub
		System.out.println(" 繪制圓形 ");
	}
}

//新增畫(huà)三角形
class Triangle extends Shape {Triangle() {super.m_type = 3;
	}
	@Override
	public void draw() {// TODO Auto-generated method stub
		System.out.println(" 繪制三角形 ");
	}
}

//新增一個(gè)圖形
class OtherGraphic extends Shape {OtherGraphic() {super.m_type = 4;
	}

	@Override
	public void draw() {// TODO Auto-generated method stub
		System.out.println(" 繪制其它圖形 ");
	}
}
2.8 迪米特法則 2.8.1基本介紹
  1. 一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解
  2. 類(lèi)與類(lèi)關(guān)系越密切,耦合度越大
  3. 迪米特法則(Demeter Principle)又叫最少知道原則,即一個(gè)類(lèi)對(duì)自己依賴(lài)的類(lèi)知道的越少越好。也就是說(shuō),對(duì)于被依賴(lài)的類(lèi)不管多么復(fù)雜,都盡量將邏輯封裝在類(lèi)的內(nèi)部。對(duì)外除了提供的 public 方法,不對(duì)外泄露任何信息
  4. 迪米特法則還有個(gè)更簡(jiǎn)單的定義:只與直接的朋友通信
  5. 直接的朋友:每個(gè)對(duì)象都會(huì)與其他對(duì)象有耦合關(guān)系,只要兩個(gè)對(duì)象之間有耦合關(guān)系,我們就說(shuō)這兩個(gè)對(duì)象之間是朋友關(guān)系。耦合的方式很多,依賴(lài),關(guān)聯(lián),組合,聚合等。其中,我們稱(chēng)出現(xiàn)成員變量,方法參數(shù),方法返回值中的類(lèi)為直接的朋友,而出現(xiàn)在局部變量中的類(lèi)不是直接的朋友。也就是說(shuō),陌生的類(lèi)最好不要以局部變量的形式出現(xiàn)在類(lèi)的內(nèi)部。
2.8.2應(yīng)用實(shí)例
  1. 有一個(gè)學(xué)校,下屬有各個(gè)學(xué)院和總部,現(xiàn)要求打印出學(xué)??偛繂T工 ID 和學(xué)院?jiǎn)T工的id
  2. 編程實(shí)現(xiàn)上面的功能, 看代碼演示
  3. 代碼演示
package com.atguigu.principle.demeter;

import java.util.ArrayList;
import java.util.List;

//客戶(hù)端
public class Demeter1 {public static void main(String[] args) {//創(chuàng)建了一個(gè) SchoolManager 對(duì)象
		SchoolManager schoolManager = new SchoolManager();
		//輸出學(xué)院的員工id 和  學(xué)??偛康膯T工信息
		schoolManager.printAllEmployee(new CollegeManager());

	}

}


//學(xué)??偛繂T工類(lèi)
class Employee {private String id;

	public void setId(String id) {this.id = id;
	}

	public String getId() {return id;
	}
}


//學(xué)院的員工類(lèi)
class CollegeEmployee {private String id;

	public void setId(String id) {this.id = id;
	}

	public String getId() {return id;
	}
}


//管理學(xué)院?jiǎn)T工的管理類(lèi)
class CollegeManager {//返回學(xué)院的所有員工
	public ListgetAllEmployee() {Listlist = new ArrayList();
		for (int i = 0; i< 10; i++) {//這里我們?cè)黾恿?0個(gè)員工到 list
			CollegeEmployee emp = new CollegeEmployee();
			emp.setId("學(xué)院?jiǎn)T工id= " + i);
			list.add(emp);
		}
		return list;
	}
}

//學(xué)校管理類(lèi)

//分析 SchoolManager 類(lèi)的直接朋友類(lèi)有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一個(gè)陌生類(lèi),這樣違背了 迪米特法則 
class SchoolManager {//返回學(xué)??偛康膯T工
	public ListgetAllEmployee() {Listlist = new ArrayList();
		
		for (int i = 0; i< 5; i++) {//這里我們?cè)黾恿?個(gè)員工到 list
			Employee emp = new Employee();
			emp.setId("學(xué)??偛繂T工id= " + i);
			list.add(emp);
		}
		return list;
	}

	//該方法完成輸出學(xué)校總部和學(xué)院?jiǎn)T工信息(id)
	void printAllEmployee(CollegeManager sub) {		//分析問(wèn)題
		//1. 這里的 CollegeEmployee 不是  SchoolManager的直接朋友
		//2. CollegeEmployee 是以局部變量方式出現(xiàn)在 SchoolManager
		//3. 違反了 迪米特法則 
		
		//獲取到學(xué)院?jiǎn)T工
		Listlist1 = sub.getAllEmployee();
		System.out.println("------------學(xué)院?jiǎn)T工------------");
		for (CollegeEmployee e : list1) {	System.out.println(e.getId());
		}
		//獲取到學(xué)??偛繂T工
		Listlist2 = this.getAllEmployee();
		System.out.println("------------學(xué)??偛繂T工------------");
		for (Employee e : list2) {	System.out.println(e.getId());
		}
	}
}
2.8.3應(yīng)用實(shí)例改進(jìn)
  1. 前面設(shè)計(jì)的問(wèn)題在于 SchoolManager 中**,CollegeEmployee 類(lèi)并不是 SchoolManager 類(lèi)的直接朋友**(分析)
  2. 按照迪米特法則,應(yīng)該避免類(lèi)中出現(xiàn)這樣非直接朋友關(guān)系的耦合
  3. 對(duì)代碼按照迪米特法則 進(jìn)行改進(jìn). (看老師演示)
  4. 代碼演示
package com.atguigu.principle.demeter.improve;

import java.util.ArrayList;
import java.util.List;

//客戶(hù)端
public class Demeter1 {public static void main(String[] args) {System.out.println("~~~使用迪米特法則的改進(jìn)~~~");
		//創(chuàng)建了一個(gè) SchoolManager 對(duì)象
		SchoolManager schoolManager = new SchoolManager();
		//輸出學(xué)院的員工id 和  學(xué)??偛康膯T工信息
		schoolManager.printAllEmployee(new CollegeManager());

	}

}


//學(xué)校總部員工類(lèi)
class Employee {private String id;

	public void setId(String id) {this.id = id;
	}

	public String getId() {return id;
	}
}


//學(xué)院的員工類(lèi)
class CollegeEmployee {private String id;

	public void setId(String id) {this.id = id;
	}

	public String getId() {return id;
	}
}


//管理學(xué)院?jiǎn)T工的管理類(lèi)
class CollegeManager {//返回學(xué)院的所有員工
	public ListgetAllEmployee() {Listlist = new ArrayList();
		for (int i = 0; i< 10; i++) {//這里我們?cè)黾恿?0個(gè)員工到 list
			CollegeEmployee emp = new CollegeEmployee();
			emp.setId("學(xué)院?jiǎn)T工id= " + i);
			list.add(emp);
		}
		return list;
	}
	
	//輸出學(xué)院?jiǎn)T工的信息
	public void printEmployee() {//獲取到學(xué)院?jiǎn)T工
		Listlist1 = getAllEmployee();
		System.out.println("------------學(xué)院?jiǎn)T工------------");
		for (CollegeEmployee e : list1) {	System.out.println(e.getId());
		}
	}
}

//學(xué)校管理類(lèi)

//分析 SchoolManager 類(lèi)的直接朋友類(lèi)有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一個(gè)陌生類(lèi),這樣違背了 迪米特法則 
class SchoolManager {//返回學(xué)??偛康膯T工
	public ListgetAllEmployee() {Listlist = new ArrayList();
		
		for (int i = 0; i< 5; i++) {//這里我們?cè)黾恿?個(gè)員工到 list
			Employee emp = new Employee();
			emp.setId("學(xué)校總部員工id= " + i);
			list.add(emp);
		}
		return list;
	}

	//該方法完成輸出學(xué)??偛亢蛯W(xué)院?jiǎn)T工信息(id)
	void printAllEmployee(CollegeManager sub) {		//分析問(wèn)題
		//1. 將輸出學(xué)院的員工方法,封裝到CollegeManager
		sub.printEmployee();
	
		//獲取到學(xué)??偛繂T工
		Listlist2 = this.getAllEmployee();
		System.out.println("------------學(xué)校總部員工------------");
		for (Employee e : list2) {	System.out.println(e.getId());
		}
	}
}
2.8.4迪米特法則注意事項(xiàng)和細(xì)節(jié)
  1. 迪米特法則的核心是降低類(lèi)之間的耦合
  2. 但是注意:由于每個(gè)類(lèi)都減少了不必要的依賴(lài),因此迪米特法則只是要求降低類(lèi)間(對(duì)象間)耦合關(guān)系,并不是要求完全沒(méi)有依賴(lài)關(guān)系
2.9 合成復(fù)用原則(Composite Reuse Principle) 2.9.1基本介紹

原則是盡量使用合成/聚合的方式,而不是使用繼承
在這里插入圖片描述

2.10 設(shè)計(jì)原則核心思想
  1. 找出應(yīng)用中可能需要變化之處,把它們獨(dú)立出來(lái),不要和那些不需要變化的代碼混在一起。
  2. 針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程。
  3. 為了交互對(duì)象之間的松耦合設(shè)計(jì)而努力
第 3 章UML 類(lèi)圖 3.1 UML 基本介紹
  1. UML——Unified modeling language UML (統(tǒng)一建模語(yǔ)言),是一種用于軟件系統(tǒng)分析和設(shè)計(jì)的語(yǔ)言工具,它用于幫助軟件開(kāi)發(fā)人員進(jìn)行思考和記錄思路的結(jié)果
  2. UML 本身是一套符號(hào)的規(guī)定,就像數(shù)學(xué)符號(hào)和化學(xué)符號(hào)一樣,這些符號(hào)用于描述軟件模型中的各個(gè)元素和他們之間的關(guān)系,比如類(lèi)、接口、實(shí)現(xiàn)、泛化、依賴(lài)、組合、聚合等,如右圖:
    在這里插入圖片描述
    在這里插入圖片描述
3.2 UML 圖

畫(huà) UML 圖與寫(xiě)文章差不多,都是把自己的思想描述給別人看,關(guān)鍵在于思路和條理,UML 圖分類(lèi):

  1. 用例圖(use case)
  2. 靜態(tài)結(jié)構(gòu)圖:類(lèi)圖、對(duì)象圖、包圖、組件圖、部署圖
  3. 動(dòng)態(tài)行為圖:交互圖(時(shí)序圖與協(xié)作圖)、狀態(tài)圖、活動(dòng)圖
    ? 說(shuō)明:
  4. 類(lèi)圖是描述類(lèi)與類(lèi)之間的關(guān)系的,是 UML 圖中最核心的
  5. 在講解設(shè)計(jì)模式時(shí),我們必然會(huì)使用類(lèi)圖,為了讓學(xué)員們能夠把設(shè)計(jì)模式學(xué)到位,需要先給大家講解類(lèi)圖3) 溫馨提示:如果已經(jīng)掌握 UML 類(lèi)圖的學(xué)員,可以直接聽(tīng)設(shè)計(jì)模式的章節(jié)
3.3 UML 類(lèi)圖
  1. 用于描述系統(tǒng)中的類(lèi)(對(duì)象)本身的組成和類(lèi)(對(duì)象)之間的各種靜態(tài)關(guān)系。
  2. 類(lèi)之間的關(guān)系:依賴(lài)、泛化(繼承)、實(shí)現(xiàn)、關(guān)聯(lián)、聚合與組合。
  3. 類(lèi)圖簡(jiǎn)單舉例
public class Person{//代碼形式->類(lèi)圖
private Integer id;
private String name;
public void setName(String name){this.name=name;
}
public String getName(){return name;
}
}

在這里插入圖片描述

3.4 類(lèi)圖—依賴(lài)關(guān)系(Dependence)

? 只要是在類(lèi)中用到了對(duì)方,那么他們之間就存在依賴(lài)關(guān)系。如果沒(méi)有對(duì)方,連編繹都通過(guò)不了。

public class PersonServiceBean {private PersonDao personDao;//類(lèi)

        public void save(Person person) {}

        public IDCard getIDCard(Integer personid) {}

        public void modify() {Department department = new Department();
        }
    }

    public class PersonDao {}

    public class IDCard {}

    public class Person {}

    public class Department {}

? 對(duì)應(yīng)的類(lèi)圖:
在這里插入圖片描述
? 小結(jié)

  1. 類(lèi)中用到了對(duì)方
  2. 如果是類(lèi)的成員屬性
  3. 如果是方法的返回類(lèi)型
  4. 是方法接收的參數(shù)類(lèi)型
  5. 方法中使用到
3.5 類(lèi)圖—泛化關(guān)系(generalization)

? 泛化關(guān)系實(shí)際上就是繼承關(guān)系,他是依賴(lài)關(guān)系的特例

public abstract class DaoSupport {public void save(Object entity) {}

        public void delete(Object id) {}
    }

    public class PersonServiceBean extends Daosupport {}

? 對(duì)應(yīng)的類(lèi)圖
在這里插入圖片描述
? 小結(jié):

  1. 泛化關(guān)系實(shí)際上就是繼承關(guān)系
  2. 如果 A 類(lèi)繼承了 B 類(lèi),我們就說(shuō) A 和 B 存在泛化關(guān)系
3.6 類(lèi)圖—實(shí)現(xiàn)關(guān)系(Implementation)

實(shí)現(xiàn)關(guān)系實(shí)際上就是A 類(lèi)實(shí)現(xiàn) B 接口,他是依賴(lài)關(guān)系的特例

public interface PersonService {public void delete(Interger id);
    }

    public class PersonServiceBean implements PersonService {public void delete(Interger id) {}
    }

=>類(lèi)圖
在這里插入圖片描述

3.7 類(lèi)圖—關(guān)聯(lián)關(guān)系(Association)

在這里插入圖片描述

3.8 類(lèi)圖—聚合關(guān)系(Aggregation) 3.8.1基本介紹

聚合關(guān)系(Aggregation)表示的是整體和部分的關(guān)系,整體與部分可以分開(kāi)。聚合關(guān)系是關(guān)聯(lián)關(guān)系的特例,所以他具有關(guān)聯(lián)的導(dǎo)航性與多重性。
如:一臺(tái)電腦由鍵盤(pán)(keyboard)、顯示器(monitor),鼠標(biāo)等組成;組成電腦的各個(gè)配件是可以從電腦上分離出來(lái)的,使用帶空心菱形的實(shí)線(xiàn)來(lái)表示:

3.8.2應(yīng)用實(shí)例

在這里插入圖片描述

3.9 類(lèi)圖—組合關(guān)系(Composition) 3.9.1基本介紹

組合關(guān)系:也是整體與部分的關(guān)系,但是整體與部分不可以分開(kāi)。
再看一個(gè)案例:在程序中我們定義實(shí)體:Person 與 IDCard、Head, 那么 Head 和 Person 就是組合,IDCard和Person 就是聚合。
但是如果在程序中 Person 實(shí)體中定義了對(duì) IDCard 進(jìn)行級(jí)聯(lián)刪除,即刪除 Person 時(shí)連同IDCard 一起刪除,那么 IDCard 和 Person 就是組合了.

3.9.2應(yīng)用案例
public class Person {private IDCard card;
        private Head head = new Head();
    }

    public class IDCard {}

    public class Head {}

對(duì)應(yīng)的類(lèi)圖:
在這里插入圖片描述
案例 2

public class Computer {private Mouse mouse = new Mouse(); //鼠標(biāo)可以和 computer 不能分離
        private Moniter moniter = new Moniter();//顯示器可以和 Computer 不能分離

        public void setMouse(Mouse mouse) {this.mouse = mouse;
        }

        public void setMoniter(Moniter moniter) {this.moniter = moniter;
        }
    }

    public class Mouse {}

    public class Moniter {}

對(duì)應(yīng)的類(lèi)圖
在這里插入圖片描述

第 4 章設(shè)計(jì)模式概述 4.1 掌握設(shè)計(jì)模式的層次
  1. 第 1 層:剛開(kāi)始學(xué)編程不久,聽(tīng)說(shuō)過(guò)什么是設(shè)計(jì)模式
  2. 第 2 層:有很長(zhǎng)時(shí)間的編程經(jīng)驗(yàn),自己寫(xiě)了很多代碼,其中用到了設(shè)計(jì)模式,但是自己卻不知道
  3. 第 3 層:學(xué)習(xí)過(guò)了設(shè)計(jì)模式,發(fā)現(xiàn)自己已經(jīng)在使用了,并且發(fā)現(xiàn)了一些新的模式挺好用的
  4. 第 4 層:閱讀了很多別人寫(xiě)的源碼和框架,在其中看到別人設(shè)計(jì)模式,并且能夠領(lǐng)會(huì)設(shè)計(jì)模式的精妙和帶來(lái)的好處。
  5. 第 5 層:代碼寫(xiě)著寫(xiě)著,自己都沒(méi)有意識(shí)到使用了設(shè)計(jì)模式,并且熟練的寫(xiě)了出來(lái)。
4.2 設(shè)計(jì)模式介紹
  1. 設(shè)計(jì)模式是程序員在面對(duì)同類(lèi)軟件工程設(shè)計(jì)問(wèn)題所總結(jié)出來(lái)的有用的經(jīng)驗(yàn),模式不是代碼,而是某類(lèi)問(wèn)題的通用解決方案,設(shè)計(jì)模式(Design pattern)代表了最佳的實(shí)踐。這些解決方案是眾多軟件開(kāi)發(fā)人員經(jīng)過(guò)相當(dāng)長(zhǎng)的一段時(shí)間的試驗(yàn)和錯(cuò)誤總結(jié)出來(lái)的。
  2. 設(shè)計(jì)模式的本質(zhì)提高 軟件的維護(hù)性,通用性和擴(kuò)展性,并降低軟件的復(fù)雜度。
  3. <<設(shè)計(jì)模式>>是經(jīng)典的書(shū),作者是 Erich Gamma、Richard Helm、Ralph Johnson 和John Vlissides Design(俗稱(chēng) “四人組 GOF”)
  4. 設(shè)計(jì)模式并不局限于某種語(yǔ)言,java,php,c++ 都有設(shè)計(jì)模式.
4.3 設(shè)計(jì)模式類(lèi)型

設(shè)計(jì)模式分為三種類(lèi)型,共 23 種

  1. 創(chuàng)建型模式:?jiǎn)卫J?、抽象工廠模式、原型模式、建造者模式、工廠模式。
  2. 結(jié)構(gòu)型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。3) 行為型模式:模版方法模式、命令模式、訪(fǎng)問(wèn)者模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter 模式)、狀態(tài)模式、策略模式、職責(zé)鏈模式(責(zé)任鏈模式)。注意:不同的書(shū)籍上對(duì)分類(lèi)和名稱(chēng)略有差別
第 5 章單例設(shè)計(jì)模式 5.1 單例設(shè)計(jì)模式介紹

所謂類(lèi)的單例設(shè)計(jì)模式,就是采取一定的方法保證在整個(gè)的軟件系統(tǒng)中,對(duì)某個(gè)類(lèi)只能存在一個(gè)對(duì)象實(shí)例,并且該類(lèi)只提供一個(gè)取得其對(duì)象實(shí)例的方法(靜態(tài)方法)。
比如 Hibernate 的 SessionFactory,它充當(dāng)數(shù)據(jù)存儲(chǔ)源的代理,并負(fù)責(zé)創(chuàng)建 Session 對(duì)象。SessionFactory并不是輕量級(jí)的,一般情況下,一個(gè)項(xiàng)目通常只需要一個(gè) SessionFactory 就夠,這是就會(huì)使用到單例模式。

5.2 單例設(shè)計(jì)模式八種方式

單例模式有八種方式:
1) 餓漢式(靜態(tài)常量)
2) 餓漢式(靜態(tài)代碼塊)
3) 懶漢式(線(xiàn)程不安全)
4) 懶漢式(線(xiàn)程安全,同步方法)
5) 懶漢式(線(xiàn)程安全,同步代碼塊)
6) 雙重檢查
7) 靜態(tài)內(nèi)部類(lèi)
8) 枚舉

5.3 餓漢式(靜態(tài)常量)

餓漢式(靜態(tài)常量)應(yīng)用實(shí)例
步驟如下:

  1. 構(gòu)造器私有化 (防止 new )
  2. 類(lèi)的內(nèi)部創(chuàng)建對(duì)象
  3. 向外暴露一個(gè)靜態(tài)的公共方法。getInstance
  4. 代碼實(shí)現(xiàn)
package com.atguigu.singleton.type1;

public class SingletonTest01 {public static void main(String[] args) {//測(cè)試
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
	}

}

//餓漢式(靜態(tài)變量)

class Singleton {	//1. 構(gòu)造器私有化, 外部能new
	private Singleton() {	}
	
	//2.本類(lèi)內(nèi)部創(chuàng)建對(duì)象實(shí)例
	private final static Singleton instance = new Singleton();
	
	//3. 提供一個(gè)公有的靜態(tài)方法,返回實(shí)例對(duì)象
	public static Singleton getInstance() {return instance;
	}
	
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 優(yōu)點(diǎn):這種寫(xiě)法比較簡(jiǎn)單,就是在類(lèi)裝載的時(shí)候就完成實(shí)例化。避免了線(xiàn)程同步問(wèn)題。2) 缺點(diǎn):在類(lèi)裝載的時(shí)候就完成實(shí)例化,沒(méi)有達(dá)到 Lazy Loading 的效果。如果從始至終從未使用過(guò)這個(gè)實(shí)例,則會(huì)造成內(nèi)存的浪費(fèi)
  2. 這種方式基于 classloder 機(jī)制避免了多線(xiàn)程的同步問(wèn)題,不過(guò),instance 在類(lèi)裝載時(shí)就實(shí)例化,在單例模式中大多數(shù)都是調(diào)用 getInstance 方法,但是導(dǎo)致類(lèi)裝載的原因有很多種,因此不能確定有其他的方式(或者其他的靜態(tài)方法)導(dǎo)致類(lèi)裝載,這時(shí)候初始化 instance 就沒(méi)有達(dá)到 lazy loading 的效果
  3. 結(jié)論:這種單例模式可用,可能造成內(nèi)存浪費(fèi)
5.4 餓漢式(靜態(tài)代碼塊)

? 代碼演示:

package com.atguigu.singleton.type2;

public class SingletonTest02 {public static void main(String[] args) {//測(cè)試
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
	}

}

//餓漢式(靜態(tài)變量)

class Singleton {	//1. 構(gòu)造器私有化, 外部能new
	private Singleton() {	}
	

	//2.本類(lèi)內(nèi)部創(chuàng)建對(duì)象實(shí)例
	private  static Singleton instance;
	
	static {// 在靜態(tài)代碼塊中,創(chuàng)建單例對(duì)象
		instance = new Singleton();
	}
	
	//3. 提供一個(gè)公有的靜態(tài)方法,返回實(shí)例對(duì)象
	public static Singleton getInstance() {return instance;
	}
	
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 這種方式和上面的方式其實(shí)類(lèi)似,只不過(guò)將類(lèi)實(shí)例化的過(guò)程放在了靜態(tài)代碼塊中,也是在類(lèi)裝載的時(shí)候,就執(zhí)行靜態(tài)代碼塊中的代碼,初始化類(lèi)的實(shí)例。優(yōu)缺點(diǎn)和上面是一樣的。
  2. 結(jié)論:這種單例模式可用,但是可能造成內(nèi)存浪費(fèi)
5.5 懶漢式(線(xiàn)程不安全)

? 代碼演示:

package com.atguigu.singleton.type3;


public class SingletonTest03 {public static void main(String[] args) {System.out.println("懶漢式1 , 線(xiàn)程不安全~");
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
	}

}

class Singleton {private static Singleton instance;
	
	private Singleton() {}
	
	//提供一個(gè)靜態(tài)的公有方法,當(dāng)使用到該方法時(shí),才去創(chuàng)建 instance
	//即懶漢式
	public static Singleton getInstance() {if(instance == null) {	instance = new Singleton();
		}
		return instance;
	}
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 起到了 Lazy Loading 的效果,但是只能在單線(xiàn)程下使用。
  2. 如果在多線(xiàn)程下,一個(gè)線(xiàn)程進(jìn)入了 if (singleton == null)判斷語(yǔ)句塊,還未來(lái)得及往下執(zhí)行,另一個(gè)線(xiàn)程也通過(guò)了這個(gè)判斷語(yǔ)句,這時(shí)便會(huì)產(chǎn)生多個(gè)實(shí)例。所以在多線(xiàn)程環(huán)境下不可使用這種方式3) 結(jié)論:在實(shí)際開(kāi)發(fā)中,不要使用這種方式.
5.6 懶漢式(線(xiàn)程安全,同步方法)

? 代碼演示:

package com.atguigu.singleton.type4;


public class SingletonTest04 {public static void main(String[] args) {System.out.println("懶漢式2 , 線(xiàn)程安全~");
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
	}

}

// 懶漢式(線(xiàn)程安全,同步方法)
class Singleton {private static Singleton instance;
	
	private Singleton() {}
	
	//提供一個(gè)靜態(tài)的公有方法,加入同步處理的代碼,解決線(xiàn)程安全問(wèn)題
	//即懶漢式
	public static synchronized Singleton getInstance() {if(instance == null) {	instance = new Singleton();
		}
		return instance;
	}
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 解決了線(xiàn)程安全問(wèn)題
  2. 效率太低了,每個(gè)線(xiàn)程在想獲得類(lèi)的實(shí)例時(shí)候,執(zhí)行 getInstance()方法都要進(jìn)行同步。而其實(shí)這個(gè)方法只執(zhí)行一次實(shí)例化代碼就夠了,后面的想獲得該類(lèi)實(shí)例,直接 return 就行了。方法進(jìn)行同步效率太低
  3. 結(jié)論:在實(shí)際開(kāi)發(fā)中,不推薦使用這種方式
5.7 懶漢式(線(xiàn)程安全,同步代碼塊)


不推薦使用

5.8 雙重檢查

? 代碼演示

package com.atguigu.singleton.type6;


public class SingletonTest06 {public static void main(String[] args) {System.out.println("雙重檢查");
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
		
	}

}

// 懶漢式(線(xiàn)程安全,同步方法)
class Singleton {private static volatile Singleton instance;
	
	private Singleton() {}
	
	//提供一個(gè)靜態(tài)的公有方法,加入雙重檢查代碼,解決線(xiàn)程安全問(wèn)題, 同時(shí)解決懶加載問(wèn)題
	//同時(shí)保證了效率, 推薦使用
	
	public static synchronized Singleton getInstance() {if(instance == null) {	synchronized (Singleton.class) {		if(instance == null) {instance = new Singleton();
				}
			}
			
		}
		return instance;
	}
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. Double-Check 概念是多線(xiàn)程開(kāi)發(fā)中常使用到的,如代碼中所示,我們進(jìn)行了兩次if (singleton = = null)檢查,這樣就可以保證線(xiàn)程安全了。
  2. 這樣,實(shí)例化代碼只用執(zhí)行一次,后面再次訪(fǎng)問(wèn)時(shí),判斷 if (singleton == null),直接return 實(shí)例化對(duì)象,也避免的反復(fù)進(jìn)行方法同步.
  3. 線(xiàn)程安全;延遲加載;效率較高
  4. 結(jié)論:在實(shí)際開(kāi)發(fā)中,推薦使用這種單例設(shè)計(jì)模式
    5.9 靜態(tài)內(nèi)部類(lèi)
    ? 代碼演示:
package com.atguigu.singleton.type7;


public class SingletonTest07 {public static void main(String[] args) {System.out.println("使用靜態(tài)內(nèi)部類(lèi)完成單例模式");
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance == instance2); // true
		System.out.println("instance.hashCode=" + instance.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
		
	}

}

// 靜態(tài)內(nèi)部類(lèi)完成, 推薦使用
class Singleton {private static volatile Singleton instance;
	
	//構(gòu)造器私有化
	private Singleton() {}
	
	//寫(xiě)一個(gè)靜態(tài)內(nèi)部類(lèi),該類(lèi)中有一個(gè)靜態(tài)屬性 Singleton
	private static class SingletonInstance {private static final Singleton INSTANCE = new Singleton(); 
	}
	
	//提供一個(gè)靜態(tài)的公有方法,直接返回SingletonInstance.INSTANCE
	
	public static synchronized Singleton getInstance() {		return SingletonInstance.INSTANCE;
	}
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 這種方式采用了類(lèi)裝載的機(jī)制來(lái)保證初始化實(shí)例時(shí)只有一個(gè)線(xiàn)程。
  2. 靜態(tài)內(nèi)部類(lèi)方式在 Singleton 類(lèi)被裝載時(shí)并不會(huì)立即實(shí)例化,而是在需要實(shí)例化時(shí),調(diào)用getInstance 方法,才會(huì)裝載 SingletonInstance 類(lèi),從而完成 Singleton 的實(shí)例化。
  3. 類(lèi)的靜態(tài)屬性只會(huì)在第一次加載類(lèi)的時(shí)候初始化,所以在這里,JVM 幫助我們保證了線(xiàn)程的安全性,在類(lèi)進(jìn)行初始化時(shí),別的線(xiàn)程是無(wú)法進(jìn)入的。
  4. 優(yōu)點(diǎn):避免了線(xiàn)程不安全,利用靜態(tài)內(nèi)部類(lèi)特點(diǎn)實(shí)現(xiàn)延遲加載,效率高
  5. 結(jié)論:推薦使用
5.10 枚舉

? 代碼演示

package com.atguigu.singleton.type8;

public class SingletonTest08 {public static void main(String[] args) {Singleton instance = Singleton.INSTANCE;
		Singleton instance2 = Singleton.INSTANCE;
		System.out.println(instance == instance2);
		
		System.out.println(instance.hashCode());
		System.out.println(instance2.hashCode());
		
		instance.sayOK();
	}
}

//使用枚舉,可以實(shí)現(xiàn)單例, 推薦
enum Singleton {INSTANCE; //屬性
	public void sayOK() {System.out.println("ok~");
	}
}

? 優(yōu)缺點(diǎn)說(shuō)明:

  1. 這借助 JDK1.5 中添加的枚舉來(lái)實(shí)現(xiàn)單例模式。不僅能避免多線(xiàn)程同步問(wèn)題,而且還能防止反序列化重新創(chuàng)建新的對(duì)象。
  2. 這種方式是 Effective Java 作者 Josh Bloch 提倡的方式
  3. 結(jié)論:推薦使用
5.11 單例模式在 JDK 應(yīng)用的源碼分析 5.11.1 單例模式在 JDK 應(yīng)用的源碼分析
  1. 我們 JDK 中,java.lang.Runtime 就是經(jīng)典的單例模式(餓漢式)
  2. 代碼分析+Debug 源碼+代碼說(shuō)明
    在這里插入圖片描述
5.12 單例模式注意事項(xiàng)和細(xì)節(jié)說(shuō)明
  1. 單例模式保證了 系統(tǒng)內(nèi)存中該類(lèi)只存在一個(gè)對(duì)象,節(jié)省了系統(tǒng)資源,對(duì)于一些需要頻繁創(chuàng)建銷(xiāo)毀的對(duì)象,使用單例模式可以提高系統(tǒng)性能
  2. 當(dāng)想實(shí)例化一個(gè)單例類(lèi)的時(shí)候,必須要記住使用相應(yīng)的獲取對(duì)象的方法,而不是使用new
  3. 單例模式使用的場(chǎng)景:需要頻繁的進(jìn)行創(chuàng)建和銷(xiāo)毀的對(duì)象、創(chuàng)建對(duì)象時(shí)耗時(shí)過(guò)多或耗費(fèi)資源過(guò)多(即:重量級(jí)對(duì)象),但又經(jīng)常用到的對(duì)象、工具類(lèi)對(duì)象、頻繁訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)或文件的對(duì)象(比如數(shù)據(jù)源、session 工廠等)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁(yè)題目:java設(shè)計(jì)模式-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://chinadenli.net/article48/ghjep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈、定制網(wǎng)站、云服務(wù)器小程序開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)