概念部分
1 實際開發中不要去繼承實現好的類,而應該去繼續抽象類或者接口
2 抽象類
普通類的基礎上擴充了一些抽象方法,即只聲明而未實現的方法
抽象方法用abstract關鍵字聲明,不包含方法體,無具體實現,不能直接產生實例化對象。
使用原則:
必須有子類、子類必須覆寫所有抽象方法、方法覆寫的權限全用public;
抽象類的對象可通過對象多態性利用子類爲其實例化。
實例化子類時一定要先調用父類構造方法。
3 對象實例化
核心步驟:類加載->類對象的空間開闢->類對象中的屬性初始化(構造方法)
4 模板設計模式
模板方法定義了一個算法的步驟,並允許子類爲一個或多個步驟提供具體實現。
最具代表性的是Servlet用。
一個完整的模板模式超類定義:
//基類聲明爲抽象類的原因是便於修改;其子類必須實現其具體操作
abstract class AbstractClass{
//模板方法,被聲明爲final以免子類改變這個算法的順序
final void templateMethod(){
}
//具體操作延遲到子類中實現
abstract void primitiveOperation1();
abstract void primitiveOperation2();
//具體操作且共用的方法定義在超類中,可以被模板方法或子類直接使用
final void concreateOperation(){
//實現
}
//鉤子方法是一類“默認不做事的方法”,子類可以視情況決定是否覆蓋它們。
void hook(){
//鉤子方法
}
}
5 接口
可以約定子類的實現並且避免單繼承侷限。
接口優先原則!
接口就是一個抽象方法和全局常量(不常見)的集合。
interface關鍵字定義,接口實現用implements關鍵字。
一個子類可以實現多個接口。
對於接口的子類必須覆寫接口中全部抽象方法,隨後可由子類向上轉型通過實例化子類來得到接口的實例化對象。
接口中只允許public權限,無論屬性或方法。
當子類需要同時實現接口和繼承抽象類時,先extends,再implements。
例:class MessageImpl extends News implements IMessage
實際開發中三大核心應用環境:
定義操作標準、表示能力、分佈式開發中暴露遠程服務方法
6 工廠設計模式
開發中程序的修改不應該影響客戶端,程序->JVM->操作系統,new是最大的耦合原因,解耦就要引入第三方Factory。
JDK中用到工廠模式的典型操作:
Collection中的iterator方法(集合類中的迭代器)
java.util包中相關sql操作。
7 代理設計模式
兩個子類共同實現一個接口,其中一個子類負責真實業務實現,另一個子類完成輔助真實業務主題的操作。
本質:所有的真實業務操作都會有一個與之輔助的工具類共同完成。
8 抽象類與接口的區別***
結構組成上:前者~普通類+抽象方法;後者~抽象方法+全局常量
權限上:前者~各種權限;後者~僅可用public
子類使用上:前者~extends繼承;後者~implements實現
關係上:前者~一個抽象類可以實現若干個接口;後者~接口不能繼承抽象類,但接口可繼承多個父接口
子類限制:前者~一個子類只能繼承一個;後者~一個子類可實現多個
總結:開發中優先用接口,避免單繼承限制;抽象類是模板有層次感,接口更關心行爲與混合。
需記程序
1 寫星巴克師傅沖茶和泡咖啡的例子~模板模式方法
//首先是超類實現
abstract class CaffeineBeverage{
//用final修飾主要是不想讓子類改變順序
//這是一個整體的做飲料方法
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
//如果用戶想要才調用加調料方法
if (customerWantsCondiments()){
addCondiments();
}
}
//寫出需要特殊實現的各個抽象方法
abstract void brew();
abstract void addCondiments();
//這兩個方法時通用法,所以在超類中實現
void boilWater(){
System.out.println("Boiling Water...");
}
void pourInCup(){
System.out.println("Pouring into cup...");
}
//鉤子方法,超類中通常是默認實現,子類可以選擇性覆寫
boolean customerWantsCondiments(){
return true;
}
}
//子類實現
class Tea extends CaffeineBeverage{
@Override
void brew() {
System.out.println("Steeping the tea...");
}
@Override
void addCondiments() {
System.out.println("Adding Lemon...");
}
}
class Coffee extends CaffeineBeverage{
@Override
void brew() {
System.out.println("Dripping Coffee through filter...");
}
@Override
void addCondiments() {
System.out.println("Adding Sugar and Milk...");
}
//在此覆寫鉤子函數,實現自定義功能
public boolean customerWantsCondiments(){
String answer = getUserInput();
if (answer.equals("Y")){
return true;
}else {
return false;
}
}
private String getUserInput(){
String answer = null;
System.out.println("Can you want to add milk or sugar(Y/N)?");
Scanner input = new Scanner(System.in);
answer = input.nextLine();
return answer;
}
}
//測試類
public class Test{
public static void main(String[] args) {
CaffeineBeverage tea = new Tea();
CaffeineBeverage coffee = new Coffee();
System.out.println("\nMaking tea...");
tea.prepareRecipe();
System.out.println("\nMaking coffee...");
coffee.prepareRecipe();
}
}
2 寫多個子類實現一個接口的例子
//定義一個USB標準
interface USB{
public void setup(); //安裝USB驅動
public void work(); //進行工作
}
//定義電腦類
class Computer{
public void plugin(USB usb){
usb.setup();
usb.work();
}
}
//定義USB子類
class UDisk implements USB{
@Override
public void setup() {
System.out.println("安裝U盤驅動");
}
@Override
public void work() {
System.out.println("U盤開始工作");
}
}
class PrintDisk implements USB{
@Override
public void setup() {
System.out.println("安裝打印機驅動");
}
@Override
public void work() {
System.out.println("打印機開始工作");
}
}
public class Test{
public static void main(String[] args) {
Computer computer = new Computer();
computer.plugin(new UDisk());
computer.plugin(new PrintDisk());
}
}
3 寫工廠設計模式,喫水果的例子
//定義一個喫水果的操作
interface IFruit{
public void eat();
}
//定義工廠類
class Factory{
public static IFruit getInstance(String className){
if (className.equals("apple")){
return new Apple();
}
if (className.equals("lemon")){
return new Lemon();
}
return null;
}
}
//子類實現
class Apple implements IFruit{
@Override
public void eat() {
System.out.println("可以喫蘋果啦");
}
}
class Lemon implements IFruit{
@Override
public void eat() {
System.out.println("可以變成檸檬精啦");
}
}
public class Test{
public static void main(String[] args) {
//如果沒有傳遞參數,工廠也不要生產
if (args.length==0){
System.out.println("沒有傳遞參數,程序退出");
System.exit(1); //退出程序
}
IFruit fruit = Factory.getInstance(args[0]);
fruit.eat();
}
}
4 寫代理設計模式,找代理買口紅的例子
interface ISubject{
public void buyLipstick(); //核心功能是買口紅
}
//有目標要做事情的類,也就是買家
class RealSubject implements ISubject{
@Override
public void buyLipstick() {
System.out.println("買三支紀梵希小羊皮");
}
}
//做真實操作業務的類,也就是微信代理
class ProxySubject implements ISubject{
private ISubject subject; //真實業務對象
//構造方法,確認當前對象
public ProxySubject(ISubject subject){
this.subject = subject;
}
public void produceLipstick(){
System.out.println("生產紀梵希小羊皮三支");
}
public void aftersale(){
System.out.println("紀梵希售後團隊");
}
@Override
public void buyLipstick() {
this.produceLipstick(); //真實業務前的準備,即先生產出口紅
this.subject.buyLipstick(); //真實業務,代購去買口紅
this.aftersale(); //操作後的首尾,口紅的售後問題
}
}
class Factory{
public static ISubject getInstance(){
return new ProxySubject(new RealSubject());
}
}
public class Test{
public static void main(String[] args) {
ISubject subject = Factory.getInstance();
subject.buyLipstick();
}
}