創四個主要的 Class (電腦、螢幕、機殼、主機板)和一些小部件的 Class 來了解 Composition 使用情境
Motherboard.java
public class Motherboard { private String model;
private String manufacturer;
private String bios;
private int ramSlots;
private int cardSlots; public Motherboard(String model, String manufacturer, String bios, int ramSlots, int cardSlots) {
this.model = model;
this.manufacturer = manufacturer;
this.bios = bios;
this.ramSlots = ramSlots;
this.cardSlots = cardSlots;
} public void loadProgram(String programName){
System.out.println("Program " + programName + " is now loading..." );
}
public String getModel() {
return model;
} public String getManufacturer() {
return manufacturer;
} public String getBios() {
return bios;
} public int getRamSlots() {
return ramSlots;
} public int getCardSlots() {
return cardSlots;
}
}
monitor.java
public class Monitor {
private String model;
private String manufacturer;
private int size;
private Resolution nativeResolution; public Monitor(String model, String manufacturer, int size, Resolution nativeResolution) {
this.model = model;
this.manufacturer = manufacturer;
this.size = size;
this.nativeResolution = nativeResolution;
} public void drawPixelAt(int x, int y, String color){
System.out.println("Drawing pixel at " + x + "," + y + " in color " + color);
} public String getModel() {
return model;
} public String getManufacturer() {
return manufacturer;
} public int getSize() {
return size;
} public Resolution getNativeResolution() {
return nativeResolution;
}
}
可以看到第4個 field 是一個 Resolution Class
此時還沒寫到,下一個會寫
但這就是 composition
需要的時候可以透過 monitor 來調用 resolution 的 filed 跟 method
後面會展示
resolution.java
public class Resolution {
private int width;
private int height; public Resolution(int width, int height) {
this.width = width;
this.height = height;
} public int getWidth() {
return width;
} public int getHeight() {
return height;
}
}
case.java
public class Case {
private String model;
private String manufacturer;
private String powerSupply;
private Dimensions dimensions; public Case(String model, String manufacturer, String powerSupply, Dimensions dimensions) {
this.model = model;
this.manufacturer = manufacturer;
this.powerSupply = powerSupply;
this.dimensions = dimensions;
} public void pressPowerButton(){
System.out.println("Power button was pressed");
} public String getModel() {
return model;
} public String getManufacturer() {
return manufacturer;
} public String getPowerSupply() {
return powerSupply;
} public Dimensions getDimensions() {
return dimensions;
}
}
第 4 個 field 也是 Class
dimension.java
public class Dimensions {
private int width;
private int height;
private int depth; public Dimensions(int width, int height, int depth) {
this.width = width;
this.height = height;
this.depth = depth;
} public int getWidth() {
return width;
} public int getHeight() {
return height;
} public int getDepth() {
return depth;
}
}
computer.java
public class Computer {
private Case theCase;
private Monitor monitor;
private Motherboard motherboard; public Computer(Case theCase, Monitor monitor, Motherboard motherboard) {
this.theCase = theCase;
this.monitor = monitor;
this.motherboard = motherboard;
} public Case getTheCase() {
return theCase;
} public Monitor getMonitor() {
return monitor;
} public Motherboard getMotherboard() {
return motherboard;
}
}
main.java
public class main { public static void main(String[] args) {
Case theCase = new Case("Tx650","Lian Li", "Gold", new Dimensions(120,50,80));
Monitor theMonitor = new Monitor("Corporation 24", "BenQ", 17, new Resolution(1920, 1080));
Motherboard theMotherboard = new Motherboard("M32", "ASUS", "ASUS", 4, 8);
Computer mine_computer = new Computer(theCase, theMonitor, theMotherboard); mine_computer.getTheCase().pressPowerButton();
mine_computer.getMotherboard().loadProgram("Super Mario");
mine_computer.getMonitor().drawPixelAt(720, 480, "yellow");
}}
參數用到 Class 時,是可以直接在參數寫入 new Class
所以 new Computer(也可以在參數直接 new 3 個 Class)
只是這樣的話會看起來太擠,為了可讀性還是拆開來。
輸出結果:
Power button was pressed
Program Super Mario is now loading…
Drawing pixel at 720,480 in color yellow
這邊5個 Class
沒有用到任何 Inheritance
但還是成功調用了不同 Class 中的 method
這邊的 getTheCase()
就等於直接調用了 new 出來的 case
在 Computer 中的 filed 就是如此設定 private Case theCase;
而 get 返回的也是此 field
其他兩個 get 也是如此
Saurav 同學解釋了 Composition 跟 Inheritance 的差異
Composition follows HAS-A relationship
Inheritance follows IS-A relationship
For example:-
Bathroom HAS-A Tub — — — — — — — — — — → Composition
Dog IS-A Animal — — — — — — — — — — — — → Inheritance
You cannot say Bathroom IS-A Tub, it simply doesn’t make sense, hence when we have HAS-A relationship, we use Composition.
Similarly, Dog IS-A animal, Dog HAS-A animal makes no sense.
優化
computer.java
public class Computer {
private Case theCase;
private Monitor monitor;
private Motherboard motherboard; public Computer(Case theCase, Monitor monitor, Motherboard motherboard) {
this.theCase = theCase;
this.monitor = monitor;
this.motherboard = motherboard;
} public void powerUp(){
theCase.pressPowerButton();
System.out.println("Power of computer is up now.");
} public void showProgram(String programName){
motherboard.loadProgram(programName);
monitor.drawPixelAt(1080,720,"Black background");
System.out.println("Window of program is opened.");
}
}
刪除了 3個 get
直接在 method 裡面調用 field(Class)
main.java
mine_computer.powerUp();
mine_computer.showProgram("Super Mario");
輸出結果:
Power button was pressed
Power of computer is up now.
Program Super Mario is now loading…
Drawing pixel at 1080,720 in color Black background
Window of program is opened.
小挑戰:
Create a single room of a house using composition.
Think about the things that should be included in the room.
Maybe physical parts of the house but furniture as well
Add at least one method to access an object via a getter and
then that objects public method as you saw in the previous video
then add at least one method to hide the object e.g. not using a getter
but to access the object used in composition within the main class
like you saw in this video.
此題為自由發揮
我寫的放在本篇使用代碼中的 room
main 換題目我就清代碼留一個紀錄
main.java
public class main { public static void main(String[] args) {
Door theDoor = new Door("Wood");
Bed theBed = new Bed(2, "King");
BookCase theBookCase = new BookCase();
Room theRoom = new Room(theDoor, theBed, theBookCase); theRoom.close_door();
theRoom.getTheDoor().lock_door();
theRoom.putBook("Red hat girl");
theRoom.putBook("Black hat boy");
theRoom.getTheBookCase().checkBook();
theRoom.getTheBed().getPillowNumber();
theRoom.getTheBed().getComfortersSize();
theRoom.open_door();
}
}
輸出結果:
The door is close.
The door is lock now.
Bookcase has: Red hat girl . Black hat boy .
Pillow has 2
Comforters size is King
The door is open.