主頁 > 軟體設計 > 【每天一個java設計模式(完)】 - 四萬字實作23種設計模式(附示例原始碼)

【每天一個java設計模式(完)】 - 四萬字實作23種設計模式(附示例原始碼)

2021-12-27 07:49:03 軟體設計

  • 什么是設計模式:【每天一個java設計模式(零)】 - 設計模式基本概念及七大設計原則

創建型模式

  • 工廠模式:【每天一個java設計模式(一)】 - 工廠模式
  • 抽象工廠模式: 【每天一個java設計模式(二)】 - 抽象工廠模式
  • 單例模式:【每天一個java設計模式(三)】 - 單例模式
  • 原型模式:【每天一個java設計模式(四)】 - 原型模式
  • 建造者模式: 【每天一個java設計模式(五)】 - 建造者模式

結構型模型

  • 配接器模式 : 【每天一個java設計模式(六)】 - 配接器模式
  • 代理模式: 【每天一個java設計模式(七)】 - 代理模式模式
  • 橋接模式:【每天一個java設計模式(八)】 - 橋接模式
  • 裝飾器模式:【每天一個java設計模式(九)】 - 裝飾器模式
  • 外觀模式:【每天一個java設計模式(十)】 - 外觀模式
  • 享元模式:【每天一個java設計模式(十一)】 - 享元模式
  • 組合模式:【每天一個java設計模式(十二)】 - 組合模式

行為型模式

  • 模板模式:【每天一個java設計模式(十三)】 - 模板模式
  • 解釋器模式:【每天一個java設計模式(十四)】 - 解釋器模式
  • 命令模式:【每天一個java設計模式(十五)】 - 命令模式
  • 策略模式:【每天一個java設計模式(十六)】 - 策略模式
  • 狀態模式:【每天一個java設計模式(十七)】 - 狀態模式
  • 觀察者模式:【每天一個java設計模式(十八)】 - 觀察者模式
  • 責任鏈模式:【每天一個java設計模式(十九)】 - 責任鏈模式
  • 備忘錄模式:【每天一個java設計模式(二十)】 - 備忘錄模式
  • 中介者模式:【每天一個java設計模式(二十一)】 - 中介者模式
  • 迭代器模式:【每天一個java設計模式(二十二)】 - 迭代器模式
  • 訪問者模式:【每天一個java設計模式(二十三)】 - 訪問者模式

實體原始碼地址

碼云: https://gitee.com/wy666666/design_pattern
Github:https://github.com/Bryant6/design_pattern

文章目錄

  • 實體原始碼地址
  • 什么是設計模式
  • 工廠模式
  • 抽象工廠模式
  • 單例模式
  • 原型模式
  • 建造者模式
  • 配接器模式
  • 代理模式
  • 橋接模式
  • 裝飾器模式
  • 外觀模式
  • 享元模式
  • 組合模式
  • 模板模式
  • 解釋器模式
  • 命令模式
  • 策略模式
  • 狀態模式
  • 觀察者模式
  • 責任鏈模式
  • 備忘錄模式
  • 中介者模式
  • 迭代器模式
  • 訪問者模式

什么是設計模式

設計模式概述

設計模式是什么?

  • 它是軟體開發人員在軟體開發程序中經過相當長的一段時間的試驗和錯誤總結出來的面臨的一般問題的解決方案;
  • 它是一套被反復使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結;
  • 它是解決特定問題的一系列套路,是前輩們的代碼設計經驗的總結,具有一定的普遍性,可以反復使用,

設計模式能干什么?

  • 實作代碼的可重用性
  • 增加代碼的可維護性
  • 減低代碼的被理解難度
  • 保證代碼的可靠性
  • 增加系統的健壯性
  • 易修改可擴展

設計模式七大設計原則
1. 開閉原則
對擴展開放,對修改關閉,當應用的需求改變時,在不修改軟體物體的源代碼或者二進制代碼的前提下,可以擴展模塊的功能,使其滿足新的需求,它使軟體物體擁有一定的適應性和靈活性的同時具備穩定性和延續性,
2. 單一職責原則
單一職責原則規定一個類應該有且僅有一個引起它變化的原因,否則類應該被拆分,

也就是說,單一職責原則就是自己只負責自己的事,不需要理會別人的事,在面對物件編程中,每個物件只負責自己的任務,這樣的開發方式代碼耦合度較低,較靈活,易擴展,
3. 里氏替換原則
里氏替換原則是面向物件設計的基本原則之一,里氏替換原則規定繼承必須確保超類所擁有的性質在子類中仍然成立,里氏替換原是繼承復用的基礎,它反映了基類與子類之間的關系,是對實作抽象化的具體步驟的規范,是實作開閉原則的方式之一,
4. 依賴倒轉原則
依賴倒轉原則規定針對介面編程,依賴于抽象而不依賴于具體,要面向介面編程,不要面向實作編程,
依賴倒轉原則是實作開閉原則的重要途徑之一,它降低了用戶與實作模塊之間的耦合度,
5. 介面隔離原則
介面隔離原則要求開發者盡量將龐大的介面拆分成更小的更具體的介面,一個類對另一個類的依賴應該建立在最小的介面上,要為各個類建立它們需要的專用介面,而不要試圖去建立一個很龐大的介面供所有依賴它的類去呼叫,
6. 合成復用原則
在軟體復用時,要盡量先使用組合或者聚合等關聯關系來實作,其次才考慮使用繼承關系來實作,如果要使用繼承關系,則必須嚴格遵循里氏替換原則(繼承必須確保超類所擁有的性質在子類中仍然成立),
7. 迪米特原則
迪米特法則又叫作最少知識原則,一個物體應當盡量少地與其他物體之間發生相互作用,使得系統功能模塊相對獨立,如果兩個軟體物體無須直接通信,那么就不應當發生直接的相互呼叫,可以通過第三方轉發該呼叫,

一句話總結設計原則就是要降低物件的耦合度,增加程式的可復用、擴展和維護性,

23種設計模式
根據模式是用來完成什么作業來劃分,可分為創建型模式、結構型模式和行為型模式 3 種型別,
在這里插入圖片描述
其中工廠方法模式、配接器模式、模板方法模式、解釋器模式四種模式,是用于處理類與子類之間的關系,這些關系通過繼承來建立,是靜態的,在編譯時刻便確定下來了,其他的模式都是用于處理物件之間的關系,這些關系可以通過組合或聚合來實作,在運行時刻是可以變化的,

工廠模式

工廠模式是 Java 中最常用的設計模式之一,它屬于創建型模式,提供了一種創建物件的最佳方式,

在工廠模式中,我們在創建物件時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的介面來指向新創建的物件,即定義一個創建物件的介面,讓其子類自己決定實體化哪一個工廠類,工廠模式使其創建程序延遲到子類進行,

使用工廠模式,用戶只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體創建程序;只需要知道產品的抽象類,無須關心其他實作類,滿足迪米特法則、依賴倒置原則和里氏替換原則,

可以通過以下步驟來實作一個工廠模式:

  1. 創建一個介面
  2. 創建實作介面的實作類
  3. 創建一個工廠,生成基于給定資訊的物體類的物件,
  4. 使用該工廠,通過傳遞型別資訊來獲取物體類的物件,

下面的例子中,我們假設一個工廠可以生產手機、電腦和飛機三種產品,我們使用工廠模式來實作手機、電腦、飛機的創建,

1. 創建一個介面
這個介面表示一種產品,但具體是什么我們并不知道,
介面中宣告一個方法,表示生產一個產品,

// 表示一種產品
public interface Product {
    //表示生產一件產品的方法
    void product();
}

2. 創建實作介面的實作類
假設目前只有手機、電腦和飛機三種產品,分別創建手機、電腦和飛機三個實作類實作產品介面,并實作其中常見產品的的方法,

//手機
public class Phone implements Product {
    @Override
    public void product() {
        System.out.println("生產了一個牛逼的智能手機");
    }
}
//電腦
public class Computer implements Product {
    @Override
    public void product() {
        System.out.println("生產了一臺程式員都想要的電腦");
    }
}
//飛機
public class Plane implements Product {
    @Override
    public void product() {
        System.out.println("生產了一架飛機,隨時帶你起飛");
    }
}

3. 創建一個工廠,生成基于給定資訊的物體類的物件,
工廠類,用于生產出具體的產品,

//工廠類
public class Factory {
    //通過productType獲取產品物件
    public Product getProduct(String productType){
        if(productType.equals("手機")){
            return new Phone();
        }else if(productType.equals("電腦")){
            return new Computer();
        }else if(productType.equals("飛機")){
            return new Plane();
        }else {
            System.out.println("傳入產品型別有誤!");
        }
        return null;
    }
}

4. 使用該工廠,通過傳遞型別資訊來獲取物體類的物件,
使用工廠,生產出產品,

public class FactoryMain {
    public static void main(String[] args) {
        //創建一個工廠
        Factory factory = new Factory();

        //通過工廠獲取手機物件,并創建一個手機
        Product phone = factory.getProduct("手機");
        phone.product();

        //通過工廠獲取電腦物件,并創建一個電腦
        Product computer = factory.getProduct("電腦");
        computer.product();

        //通過工廠獲取飛機物件,并創建一個飛機
        Product plane = factory.getProduct("飛機");
        plane.product();
    }

在這里插入圖片描述

在這個例子中,我們可以看到用戶只需要知道產品的名稱,就可以得到想要的產品,而不需要關心它具體是怎樣實作的,比如,用戶想要得到一架飛機,他只需要通過工廠Factory,然后呼叫它的getProduct方法,就可以得到一架飛機,然后就可以帶他起飛了,他并不需要知道飛機師怎么創建出來的,

抽象工廠模式

工廠方法模式只考慮生產同等級的產品,但是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,抽象工廠模式是圍繞一個超級工廠創建其他工廠,該超級工廠又稱為其他工廠的工廠,

抽象工廠模式是一種為訪問類提供一個創建一組相關或相互依賴物件的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構,

抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產一個等級的產品,而抽象工廠模式可生產多個等級的產品,

下面給出抽象工廠的實體:

假設現在有一個工廠可以生產一些產品(手機、電腦、飛機),另一個工廠可以對生產出來的產品上色(紅色、綠色、彩虹色),我們通過抽象工廠的方式來實作具體工廠的創建,以及產品的生產,

1. 創建一個介面Product
這個介面表示一種產品(手機、電腦、飛機),但具體是什么我們并不知道,
介面中宣告一個方法,表示生產一個產品,

//產品介面
public interface Product {
    void product();
}

2. 創建Product介面的實作類
三個實作類Phone、Computer、Plane分別表示手機、電腦、飛機這三種產品,

//手機類
public class Phone implements Product {
    @Override
    public void product() {
        System.out.println("生產了一個牛逼的智能手機");
    }
}
//電腦類
public class Computer implements Product {
    @Override
    public void product() {
        System.out.println("生產了一臺程式員都想要的電腦");
    }
}
//飛機類
public class Plane implements Product {
    @Override
    public void product() {
        System.out.println("生產了一架飛機,隨時帶你起飛");
    }
}

3. 創建另一個介面Color
這個介面表示不同的顏色(紅色、綠色、彩色),
介面中宣告一個方法表示給產品賦予一種顏色,

//顏色介面
public interface Color {
    void coloring();
}

4. 創建Color介面的實作類
三個實作類Red、Green、Rainbow分別表示三種不同的顏色(紅色、綠色、彩色),

//紅色
public class Red implements Color {
    @Override
    public void coloring() {
        System.out.println("為產品增添了一層中國紅");
    }
}
//綠色
public class Green implements Color {
    @Override
    public void coloring() {
        System.out.println("為產品賦予大自然之綠");
    }
}
//彩虹色
public class Rainbow implements Color {
    @Override
    public void coloring() {
        System.out.println("五彩斑斕,那是彩虹的顏色");
    }
}

5. 為 Color 和 Product物件創建抽象工廠AbstractFactory 來獲取工廠
可以通過抽象工廠獲取具體的產品工廠和顏色工廠

//抽象工廠類
public abstract class AbstractFactory {
    //生產產品的工廠
    public abstract Product createProduct(String productType);

    //為產品上色的工廠
    public abstract Color drawColor(String colorType);
}

6. 創建抽象工廠 AbstractFactory 的實作類,基于給定的資訊生成物體類的物件,
ProductFactory是生產產品的工廠,用戶生產出手機、電腦和飛機,
ColorFactory 是顏色工廠,用來給產品上色,

//生產產品的工廠
public class ProductFactory extends AbstractFactory {
    @Override
    public Product createProduct(String productType) {
        if(productType.equals("手機")){
            return new Phone();
        }else if(productType.equals("電腦")){
            return new Computer();
        }else if(productType.equals("飛機")){
            return new Plane();
        }else {
            System.out.println("傳入產品型別有誤!");
        }
        return null;
    }

    @Override
    public Color drawColor(String colorType) {
        return null;
    }
}
//產品上色的工廠
public class ColorFactory extends AbstractFactory {
    @Override
    public Product createProduct(String productType) {
        return null;
    }

    @Override
    public Color drawColor(String colorType) {
        if(colorType.equals("紅色")){
            return new Red();
        }else if(colorType.equals("綠色")){
            return new Green();
        }else if(colorType.equals("彩虹色")){
            return new Rainbow();
        }else {
            System.out.println("傳入產品型別有誤!");
        }
        return null;
    }
}

7. 創建一個工廠創造器/生成器類,來獲取具體工廠,

//工廠生成器
public class FactoryProducer {
    public static AbstractFactory getFactory(String type){
        if(type.equals("產品廠")){
            return new ProductFactory();
        } else if(type.equals("顏色廠")){
            return new ColorFactory();
        }
        return null;
    }
}

8. 使用 FactoryProducer 來獲取 AbstractFactory,通過傳遞型別資訊來獲取物體類的物件,
用過抽象工廠創建出兩個具體工廠,在通過具體工廠生產出產品和顏色物件,

public class FactoryMain {
    public static void main(String[] args) {
        //獲取生產產品的工廠
        AbstractFactory product = FactoryProducer.getFactory("產品廠");
        //獲取增加顏色的工廠
        AbstractFactory color = FactoryProducer.getFactory("顏色廠");

        //生產一部手機
        Product phone = product.createProduct("手機");
        phone.product();
        //為手機上色
        Color red = color.drawColor("紅色");
        red.coloring();

    }
}

便于理解,下面給出幾個類的關系圖:
在這里插入圖片描述

單例模式

單例模式是 Java 中最簡單的設計模式之一,這種型別的設計模式屬于創建型模式,指一個類只有一個實體,且該類能自行創建這個實體的一種模式,

單例模式有 3 個特點:

  • 單例類只有一個實體物件;
  • 該單例物件必須由單例類自行創建;
  • 單例類對外提供一個訪問該單例的全域訪問點,

通常有兩種方式用來實作單例模式:懶漢式、餓漢式

懶漢式
懶漢式不在類加載的時候生成實體,只有當第一次呼叫 getlnstance 方法時才去創建這個單例,

//懶漢式
public class LazySingle {
    private static LazySingle instance;

    private LazySingle(){}

    public static synchronized LazySingle getInstance(){
        if (instance == null){
            instance = new LazySingle();
        }

        return instance;
    }
}

餓漢式
餓漢式中類一旦加載就創建一個單例,保證在呼叫 getInstance 方法之前單例已經存在了,

//餓漢式
public class HungrySingle {

    private final static HungrySingle instance = new HungrySingle();

    private HungrySingle(){}

    public static HungrySingle getInstance(){
        return instance;
    }
}

測驗

public class SingleMain {
    public static void main(String[] args) {
        LazySingle lazySingle1 = LazySingle.getInstance();
        LazySingle lazySingle2 = LazySingle.getInstance();

        System.out.println("懶漢式創建的第一個物件:" + lazySingle1);
        System.out.println("懶漢式創建的第二個物件:" + lazySingle2);
        System.out.println(lazySingle1 == lazySingle2);

        HungrySingle hungrySingle1 = HungrySingle.getInstance();
        HungrySingle hungrySingle2 = HungrySingle.getInstance();

        System.out.println("餓漢式創建的第一個物件:" + hungrySingle1);
        System.out.println("餓漢式創建的第二個物件:" + hungrySingle2);
        System.out.println(hungrySingle1 == hungrySingle2);

    }
}

在這里插入圖片描述
可以看到,不管是懶漢式還是餓漢式多次創建的都是物件完全一樣,這也就體現了單例模式只會創建一個實體的特點,

原型模式

原型模式是用于創建重復的物件,同時又能保證性能,這種型別的設計模式屬于創建型模式,

它是用一個已經創建的實體作為原型,通過復制該原型物件來創建一個和原型相同或相似的新物件,在這里,原型實體指定了要創建的物件的種類,用這種方式創建物件非常高效,不需要知道物件創建的細節,

Java中提供了物件的 clone() 方法,所以實作原型模式很簡單,他主要就包括了深克隆和淺克隆兩種方式,

如果中java中的克隆不能很了解的話,可以參考我寫的這篇文章:java中淺克隆與深克隆決議

原型模式的實作

  1. 創建一個原型類
public class Product implements Cloneable {

    Product(){
        System.out.println("創建一個原型物件");
    }

    public Object clone() throws CloneNotSupportedException {
        System.out.println("克隆一個原型物件");
        return super.clone();
    }
}
  1. 通過淺克隆實作物件的拷貝
public class PrototypeMain {
    public static void main(String[] args) throws CloneNotSupportedException {
        Product product = new Product();
        System.out.println(product);

        Product productCloned = (Product) product.clone();

        System.out.println(productCloned);
    }
}

在這里插入圖片描述

淺克隆和深克隆的實作請參考:java中淺克隆與深克隆決議

建造者模式

在軟體開發程序中有時需要創建一個復雜的物件,這個復雜物件通常由多個子部件按一定的步驟組合而成,

建造者模式使用多個簡單的物件一步一步構建成一個復雜的物件,它是將一個復雜的物件分解為多個簡單的物件,然后一步一步構建而成,它將變與不變相分離,即產品的組成部分是不變的,但每一部分是可以靈活選擇的,

建造者模式的實作

假設我們要構造一臺電腦,包括主機、顯示幕、鍵鼠套裝三個部分,那么我們可以通過以下方式來實作建造者模式,

1. 創建一個電腦類
類中包括主機、顯示幕、鍵鼠套裝三個屬性,以及他們的set方法和一個show方法,

//電腦類
public class Computer {
    private String mainFrame;   //主機
    private String display;     //顯示幕
    private String keyboard;     //鍵鼠套裝

    public void setMainFrame(String mainFrame) {
        this.mainFrame = mainFrame;
    }

    public void setDisplay(String display) {
        this.display = display;
    }

    public void setKeyboard(String keyboard) {
        this.keyboard = keyboard;
    }

    public void showMessage(){
        System.out.println("這是一臺電腦,");
    }
}

2. 創建建造者類
類中包含創建產品各個子部件的方法,

public class Builder extends AbstractBuilder {
    @Override
    public void buildMainFrame() {
        computer.setMainFrame("建造好了主機");
    }

    @Override
    public void buildDisplay() {
        computer.setDisplay("建造好了顯示幕");
    }

    @Override
    public void buildKeyboard() {
        computer.setKeyboard("建造好了鍵鼠套裝");
    }
}

abstract class AbstractBuilder {
    //創建一個電腦物件
    Computer computer = new Computer();

    //構造主機
    public abstract void buildMainFrame();

    //構造顯示幕
    public abstract void buildDisplay();

    //構造鍵鼠套裝
    public abstract void buildKeyboard();

    //回傳電腦物件
    public Computer returnComputer(){
        return computer;
    }
}

3. 創建指揮者類
呼叫建造者中的方法完成復雜物件的創建,

public class Leader {
    private Builder builder;

    public Leader(Builder builder){
        this.builder = builder;
    }

    public Computer build(){
        builder.buildMainFrame();
        builder.buildDisplay();
        builder.buildKeyboard();
        return builder.returnComputer();
    }
}

4. 使用

public class BuilderMain {
    public static void main(String[] args) {
        Builder builder = new Builder();
        Leader leader = new Leader(builder);

        Computer computer = leader.build();
        computer.showMessage();
    }
}

配接器模式

當某種業務功能已經實作,但它們與當前系統的介面不兼容,如果重新開發成本又很高,這時用配接器模式能很好地解決這些問題,

配接器模式是作為兩個不兼容的介面之間的橋梁,屬于結構型模式,它結合了兩個獨立介面的功能,

將一個類的介面轉換成需要的另外一個介面,使得原本由于介面不兼容而不能一起作業的那些類能一起作業,

配接器模式的實作:

假設有兩款不同年代的電腦,一臺功率100W,另一臺功率200W,但是現在只有一個100W的充電器,我們要讓它為200W的電腦充電,這時候我們就需要創建一個配接器來完成這個作業,

1. 創建一個充電介面
該提供一個按型別充電的方法,

//提供一個按型別充電的方法
public interface Charge {
    public void charge(String type);
}

2. 創建100W充電器介面
在這個介面中,提供一個方法可以為100W的電腦充電,

//100W充電器介面
public interface W100 {
    public void charge100W();
}

3. 創建100W充電介面的實作類

//100W充電的實作類
public class W100Impl implements W100 {
    @Override
    public void charge100W() {
        System.out.println("使用100W充電器給電腦充電");
    }
}

4. 創建配接器

//配接器
public class ChargeAdapter implements Charge {
    W100 w100;

    public ChargeAdapter(String type){
        if(type.equals("100w")){
            w100 = new W100Impl();
        }
    }

    @Override
    public void charge(String type) {
        w100.charge100W();
    }
}

5. 創建200W充電器物體

//配接器
//200w充電器
public class W200 implements Charge {

    ChargeAdapter chargeAdapter;
    @Override
    public void charge(String type) {
        if(type.equals("200w")){
            System.out.println("200W充電器正常充電");
        }else if(type.equals("100w")) {
            chargeAdapter = new ChargeAdapter(type);
            chargeAdapter.charge(type);
        }else{
            System.out.println("功率不兼容,充電失敗!!!");
        }
    }
}

6. 測驗充電結果

public class AdapterMain {
    public static void main(String[] args) {
        W200 w200 = new W200();

        //通過配接器使用100w充電器給200w電腦充電
        System.out.print("過配接器使用100w充電器給200w電腦充電:");
        w200.charge("100w");
        //通過配接器使用300w充電器給200w電腦充電
        System.out.print("過配接器使用300w充電器給200w電腦充電:");
        w200.charge("300w");
    }
}

在這里插入圖片描述
從列印結果中我們可以看到,當使用100w充電器給200w電腦充電時,充電成功了;而使用300W充電器時,提示我們功率不兼容,這是因為我們只提供了100W的配接器,沒有300W的配接器,如果想讓300W的充電器給200W的電腦充電,那么就只需要按照上述步驟再添加一個300W配接器即可,

到此,我們實作了配接器模式,成功通過使用配接器讓200W電腦兼容100W充電器,即使原本由于介面不兼容而不能一起作業的那些類能一起作業,

代理模式

由于某些原因需要給某物件提供一個代理以控制對該物件的訪問,這時,訪問物件不適合或者不能直接參考目標物件,代理物件作為訪問物件和目標物件之間的中介,

在代理模式中,一個類代表另一個類的功能,為其他物件提供一種代理以控制對這個物件的訪問,這種型別的設計模式屬于結構型模式,

代理模式的實作

1. 創建一個介面

//介面
public interface Product {
    void show();
}

2. 創建介面的物體類

//介面的物體類
public class RealProduct implements Product {
    @Override
    public void show() {
        System.out.println("獲取到一個真實產品RealProduct!");
    }
}

3. 創建介面的代理類
代理類提供了與真實主題相同的介面,其內部含有對真實主題的參考,它可以訪問、控制或擴展真實主題的功能,在代碼中,一般代理會被理解為代碼增強,實際上就是在原代碼邏輯前后增加一些代碼邏輯,而使呼叫者無感知,

//介面的代理類
public class ProxyProduct implements Product {
    private RealProduct realProduct;

    @Override
    public void show() {
        if(realProduct == null){
            realProduct = new RealProduct();
        }


        pre();          //代理增強方法,處理代理之前要做的事情
        realProduct.show();
        post();         //代理增強方法,處理代理之后要做的事情
    }

    public void pre(){
        System.out.println("代理之前要做的事情");
    }

    public void post(){
        System.out.println("代理之后要做的事情");
    }
}

4. 使用代理類來獲取物體類的物件

public class ProxyMain {
    public static void main(String[] args) {
        ProxyProduct proxyProduct = new ProxyProduct();
        proxyProduct.show();
    }
}

在這里插入圖片描述

橋接模式

在現實生活中,某些類具有兩個或多個維度的變化,如圖形既可按形狀分,又可按顏色分,

橋接模式將抽象部分與它的實作部分分離開來,使他們都可以獨立變化,它是用組合關系代替繼承關系來實作,從而降低了抽象和實作這兩個可變維度的耦合度,

下面我們就通過橋接模式來創建不同顏色不同形狀的圖形,

橋接模式的實作:

1. 創建一個顏色介面

//顏色介面
public interface Color {
    //對傳入的圖形上色
    public void colorByShape();
}

2. 創建三種顏色

//紅色
public class Red implements Color {
    @Override
    public void colorByShape() {
        System.out.print("紅色的");
    }
}
//綠色
public class Green implements Color {
    @Override
    public void colorByShape() {
        System.out.print("綠色的");
    }
}
//彩色
public class Rainbow implements Color {
    @Override
    public void colorByShape() {
        System.out.print("彩色的");
    }
}

3. 創建形狀抽象類

//形狀抽象類
public abstract class Shape {
    Color color;

    public abstract void draw();    //畫形狀

    public void setColor(Color color) {
        this.color = color;
    }
}

4. 創建三種具體的形狀

//圓形
public class Circle extends Shape {
    @Override
    public void draw() {
        this.color.colorByShape();
        System.out.println("圓形的");
    }
}
//三角形
public class Triangle extends Shape {
    @Override
    public void draw() {
        this.color.colorByShape();
        System.out.println("三角形的");
    }
}
//矩形
public class Rectangle extends Shape {
    @Override
    public void draw() {
        this.color.colorByShape();
        System.out.println("矩形的");
    }
}

5. 給形狀上顏色(橋接)

public class BridgeMain {
    public static void main(String[] args) {
        Color red = new Red();      //紅色
        Shape circle = new Circle();        //圓形
        circle.setColor(red);
        circle.draw();              //畫紅色的圓形

        Color rainbow = new Rainbow();      //彩色
        Shape triangle = new Triangle();    //三角形
        triangle.setColor(rainbow);
        triangle.draw();            //畫彩色的三角形
    }
}

在這里插入圖片描述

裝飾器模式

裝飾器模式允許向一個現有的物件添加新的功能,同時又不改變其結構,裝飾器模式屬于結構型模式,它是作為現有的類的一個包裝,

使用給手機添加不同的功能為例,來實作裝飾器模式:

裝飾器模式的實作

1. 創建一個產品介面

//產品介面
public interface Product {
    public void function();     //產品的功能
}

2. 創建一個手機類實作產品介面

//手機物體
public class Phone implements Product {
    public Phone(){
        System.out.println("創建一個手機");
    }
    @Override
    public void function() {
        System.out.println("手機可以用來打電話");
    }
}

3. 創建一個裝飾器類實作產品介面

//裝飾器
public class Decorator implements Product {
    private Product product;

    public Decorator(Product product){
        this.product = product;
    }
    @Override
    public void function() {
        product.function();
    }
}

4. 創建一個手機裝飾器,為手機增加功能

//手機裝飾器
public class PhoneDecorator extends Decorator {
    public PhoneDecorator(Product product) {
        super(product);
    }

    @Override
    public void function() {
        super.function();
        addFunction();
    }

    public void addFunction(){
        System.out.println("給手機增加一個發短信的功能");
    }
}

5. 原手機和使用手機裝飾器后的手機功能比較

public class DecoratorMain {
    public static void main(String[] args) {
        Product phone = new Phone();
        phone.function();
        System.out.println("=========================");

        Product new_phone = new PhoneDecorator(phone);
        new_phone.function();
    }
}

在這里插入圖片描述

外觀模式

外觀模式隱藏系統的復雜性,并向客戶端提供了一個客戶端可以訪問系統的介面,這種型別的設計模式屬于結構型模式,它向現有的系統添加一個介面,來隱藏系統的復雜性,

外觀模式的實作
假設我們解決一個問題需要經過設計、建模、運行三個階段,我們使用外觀模式來隱藏這三個階段,只給用戶提供一個解決問題的介面,

1. 創建設計類

//設計
public class Design {
    public void design(){
        System.out.println("一:設計");
    }
}

2. 創建模型類

//建模
public class Model {
    public void model(){
        System.out.println("二:建模");
    }
}

3. 創建運行類

//運行
public class Run {
    public void run(){
        System.out.println("三: 運行");
    }
}

4. 創建外觀類

public class Facade {
    private Design design = new Design();
    private Model model = new Model();
    private Run run = new Run();

    public void method(){
        design.design();
        model.model();
        run.run();
        System.out.println("問題解決了");
    }
}

5. 使用外觀類解決問題

public class FacadeMain {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.method();
    }
}

在這里插入圖片描述

享元模式

享元模式主要用于減少創建物件的數量,以減少記憶體占用和提高性能,這種型別的設計模式屬于結構型模式,它提供了減少物件數量從而改善應用所需的物件結構的方式,

享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則創建新物件,在有大量物件時,有可能會造成記憶體溢位,我們把其中共同的部分抽象出來,如果有相同的業務請求,直接回傳在記憶體中已有的物件,避免重新創建,

享元模式的實作:

1. 創建手機類

//手機類
public class Phone {
    private String brand;       //品牌
    private int cost;           //價格

    public Phone(String brand){
        this.brand = brand;
    }

    public void setCost(int cost) {
        this.cost = cost;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "brand='" + brand + '\'' +
                ", cost=" + cost +
                '}';
    }
}

2. 創建手機工廠類

public class PhoneFactory {
    private static final HashMap<String,Phone> pool = new HashMap<>();

    public static Phone getPhone(String brand){
        Phone phone = pool.get(brand);

        if(phone == null){
            phone = new Phone(brand);
            pool.put(brand,phone);
            System.out.println("創建了一個" + brand + "手機");
        }

        return phone;

    }
}

3. 使用享元模式

public class FlyWeightMain {
    public static void main(String[] args) {
        String[] brands = {"華為","vivo","oppo","小米","華為","vivo","oppo","小米","華為"};
        for(int i=0;i<brands.length;i++){
            Phone phone = PhoneFactory.getPhone(brands[i]);
            phone.setCost((int) (Math.random() * 5000));
            System.out.println(phone.toString());
        }

    }
}

在這里插入圖片描述
可以看到我們好像創建和很多手機實體,但是只真正創建了4個物件,其他的都是對物件的重復使用,

組合模式

組合模式,又叫部分整體模式,是用于把一組相似的物件當作一個單一的物件,組合模式依據樹形結構來組合物件,用來表示部分以及整體層次,這種型別的設計模式屬于結構型模式,它創建了物件組的樹形結構,

這種模式創建了一個包含自己物件組的類,該類提供了修改相同物件組的方式,

我們通過下面的實體來演示組合模式的用法,

組合模式的實作:
假設現在有一個學校,學校中校長管理一些老師,老師管理一些學生,我們通過實體演示了這個學校中人員的層次結構,

  1. 創建一個Person類
//表示一個人
public class Person {
    private String type;        //職位
    private String name;        //姓名
    private List<Person> person_list;       //管理的人員

    public Person(String type, String name) {
        this.type = type;
        this.name = name;
        person_list = new ArrayList<>();
    }

    public void add(Person person){
        person_list.add(person);
    }

    public void remove(Person person){
        person_list.remove(person);
    }

    public List<Person> getPerson_list(){
        return person_list;
    }

    @Override
    public String toString() {
        return "Person{" +
                "type='" + type + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
  1. 實體來演示組合模式
public class CompositeMain {
    public static void main(String[] args) {
        Person master = new Person("校長","王校長");

        Person teacher1 = new Person("老師","張老師");
        Person teacher2 = new Person("老師","李老師");

        Person student1 = new Person("學生","學生1");
        Person student2 = new Person("學生","學生2");
        Person student3 = new Person("學生","學生3");

        master.add(teacher1);
        master.add(teacher2);

        teacher1.add(student1);
        teacher1.add(student2);
        teacher1.add(student3);

        teacher2.add(student1);
        teacher2.add(student2);
        teacher2.add(student3);

        System.out.println(master);
        for(Person leadPerson:master.getPerson_list()){
            System.out.println(leadPerson);
            for(Person student:leadPerson.getPerson_list()){
                System.out.println(student);
            }
        }

    }
}

在這里插入圖片描述

模板模式

模板模式中,一個抽象類公開定義了執行它的方法的方式/模板,它的子類可以按需要重寫方法實作,但呼叫將以抽象類中定義的方式進行,這種型別的設計模式屬于行為型模式,

模板模式的實作:

  1. 創建抽象模板類
//模板類
public abstract class TemplateClass {
    public void templateMethod(){
        specificMethod();
        method1();
        method1();
    }

    public void specificMethod(){
        System.out.println("模板中規定的特殊方法");
    }

    public abstract void method1();

    public abstract void method2();
}
  1. 創建兩個具體的類,實作模板的兩種方式

方式一

public class ConcreteClass1 extends TemplateClass {
    @Override
    public void method1() {
        System.out.println("根據模板指定的方案一的第一步");
    }

    @Override
    public void method2() {
        System.out.println("根據模板指定的方案一的第二步");
    }
}

方式二

public class ConcreteClass2 extends TemplateClass {
    @Override
    public void method1() {
        System.out.println("根據模板指定的方案二的第一步");
    }

    @Override
    public void method2() {
        System.out.println("根據模板指定的方案二的第二步");
    }
}
  1. 測驗模板模式
public class TemplateMain {
    public static void main(String[] args) {
        TemplateClass template1 = new ConcreteClass1();
        template1.templateMethod();

        TemplateClass template2 = new ConcreteClass2();
        template2.templateMethod();
    }
}

在這里插入圖片描述

解釋器模式

解釋器模式提供了評估語言的語法或運算式的方式,它屬于行為型模式,這種模式實作了一個運算式介面,該介面解釋一個特定的背景關系,

解釋器模式主要包括以下幾個部分:

  • 抽象運算式角色:定義解釋器的介面,約定解釋器的解釋操作,主要包含解釋方法 interpret(),
  • 終結符運算式角色:是抽象運算式的子類,用來實作文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結運算式與之相對應,
  • 非終結符運算式角色:也是抽象運算式的子類,用來實作文法中與非終結符相關的操作,文法中的每條規則都對應于一個非終結符運算式,
  • 環境角色:通常包含各個解釋器需要的資料或是公共的功能,一般用來傳遞被所有解釋器共享的資料,后面的解釋器可以從這里獲取這些值,
  • 客戶端:主要任務是將需要分析的句子或運算式轉換成使用解釋器物件描述的抽象語法樹,然后呼叫解釋器的解釋方法,當然也可以通過環境角色間接訪問解釋器的解釋方法,

解釋器模式的實作:
假設你現在要買一臺聯想的16寸的電腦,其他品牌和尺寸的不考慮,我們現在使用解釋器模式來表達它,

1. 抽象運算式介面

//抽象運算式介面
public interface Expression {
    public boolean interpret(String context);
}

2. 終結符運算式

//終結符運算式
public class TerminalExpression implements Expression {
    private String message;

    public TerminalExpression(String message){
        this.message = message;
    }

    @Override
    public boolean interpret(String context) {
        if(context.equals(message)){
            return true;
        }else{
            return false;
        }
    }
}

3. 非終結符運算式

public class AndExpression implements Expression {
    private Expression brand = null;
    private Expression size = null;

    public AndExpression(Expression brand, Expression size) {
        this.brand = brand;
        this.size = size;
    }

    @Override
    public boolean interpret(String context) {
        String[] info = context.split(" ");
        return brand.interpret(info[0]) && size.interpret(info[1]);     //當品牌和尺寸都滿足的時候才買
    }
}

4. 環境角色

//背景關系環境類
public class Context {
    private String brand = "聯想";
    private String size = "16寸";
    private Expression expression = null;

    public Context(){
        Expression brand = new TerminalExpression(this.brand);
        Expression size = new TerminalExpression(this.size);
        expression = new AndExpression(brand,size);
    }

    public void result(String context){
        boolean target = expression.interpret(context);
        if(target){
            System.out.println(context + ":是我想要的電腦,買了");
        }else{
            System.out.println(context + ": 不滿足我的要求");
        }
    }
}

5. 客戶端

public class InterpretMain {
    public static void main(String[] args) {
        Context context = new Context();
        context.result("戴爾 13寸");
        context.result("華碩 16寸");
        context.result("聯想 13寸");
        context.result("聯想 16寸");
    }
}

在這里插入圖片描述

命令模式

命令模式是一種資料驅動的設計模式,它屬于行為型模式,請求以命令的形式包裹在物件中,并傳給呼叫物件,呼叫物件尋找可以處理該命令的合適的物件,并把該命令傳給相應的物件,該物件執行命令,

命令模式也就是一個用戶發送請求,呼叫者接收命令,再將命令發送給接受者,最后接收者作出相應的程序

命令模式的實作:

1. 創建接受者

public class Receiver {
    public void action(){
        System.out.println("接受者執行方法");
    }
}

2. 創建命令

public class Command {
    private Receiver receiver;

    public Command(){
        receiver = new Receiver();
    }

    public void execute(){
        System.out.println("命令傳到了接收者");
        receiver.action();
    }
}

3. 創建呼叫者

public class Invoker {
    private Command command;
    public Invoker(Command command){
        this.command = command;
    }

    public void send(){
        System.out.println("呼叫者收到命令");
        command.execute();
    }
}

4. 用戶發出請求

public class CommandMain {
    public static void main(String[] args) {
        Command command = new Command();
        Invoker invoker = new Invoker(command);
        System.out.println("用戶發起請求");
        invoker.send();
    }
}

在這里插入圖片描述

策略模式

策略模式的定義:該模式定義了一系列演算法,并將每個演算法封裝起來,使它們可以相互替換,且演算法的變化不會影響使用演算法的客戶,策略模式屬于物件行為模式,它通過對演算法進行封裝,把使用演算法的責任和演算法的實作分割開來,并委派給不同的物件對這些演算法進行管理,

下面我們通過加減乘的運算來實作策略模式,

策略模式的實作;

1. 創建一個策略介面

public interface Strategy {
    public int operate(int x,int y);
}

2. 創建策略介面的三個實作類,分別表示加減乘運算

public class AddStrategy implements Strategy {
    @Override
    public int operate(int x, int y) {
        return x + y;
    }
}
public class SubStrategy implements Strategy {
    @Override
    public int operate(int x, int y) {
        return x - y;
    }
}
public class MultStrategy implements Strategy {
    @Override
    public int operate(int x, int y) {
        return x * y;
    }
}

3. 使用 Context 來查看當它改變策略 時的行為變化,

public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int execute(int x,int y){
        return strategy.operate(x,y);
    }
}

4. 使用策略模式完成加減乘運算

public class StrategyMain {
    public static void main(String[] args) {
        int x = 24;
        int y = 8;
        Context context1 = new Context(new AddStrategy());
        int add = context1.execute(x,y);
        System.out.println("x = 24, y = 8, x+y=" + add);

        Context context2 = new Context(new SubStrategy());
        int sub = context2.execute(x,y);
        System.out.println("x = 24, y = 8, x-y=" + sub);

        Context context3 = new Context(new MultStrategy());
        int mult = context3.execute(x,y);
        System.out.println("x = 24, y = 8, x*y=" + mult);
    }
}

在這里插入圖片描述

狀態模式

狀態模式中,類的行為是基于它的狀態改變的,允許物件在內部狀態發生改變時改變它的行為,物件看起來好像修改了它的類,這種型別的設計模式屬于行為型模式,

在狀態模式中,我們創建表示各種狀態的物件和一個行為隨著狀態物件改變而改變的 context 物件,

狀態模式的實作:

1. 創建狀態的抽象類

//抽象狀態類
public abstract class State {
   public abstract void handle(Context context);
}

2. 創建抽象類的兩個具體狀態

//狀態A
public class Astate extends State {
   @Override
   public void handle(Context context) {
       System.out.println("當前狀態為A,A狀態執行結束,改變狀態為B");
       context.setState(new Bstate());
   }
}
//狀態B
public class Bstate extends State {
   @Override
   public void handle(Context context) {
       System.out.println("當前狀態為B,B狀態執行結束,改變狀態為A");
       context.setState(new Astate());
   }
}

3. 創建Context

public class Context {
   private State state;

   public Context() {
       this.state = new Astate();
   }

   public void setState(State state) {
       this.state = state;
   }

   public State getState() {
       return (state);
   }

   public void handle() {
       state.handle(this);
   }
}

4. 狀態模式測驗

public class StateMain {
   public static void main(String[] args) {
       Context context = new Context();
       context.handle();
       context.handle();
       context.handle();
       context.handle();
       context.handle();
   }
}

在這里插入圖片描述

觀察者模式

觀察者模式的定義:指多個物件間存在一對多的依賴關系,當一個物件的狀態發生改變時,所有依賴于它的物件都得到通知并被自動更新,這種模式有時又稱作發布-訂閱模式、模型-視圖模式,它是物件行為型模式,

觀察者模式存在一個控制主體,和許多的觀察者,當控制主體狀態改變時,所有觀察者也都會做出反應,

觀察者模式的實作;

1. 創建觀察者抽象類

//抽象觀察者
public abstract class Observer {
    public abstract void update();
}

2. 創建三個具體觀察者

//觀察者A
public class AObserver extends Observer {
    @Override
    public void update() {
        System.out.println("觀察者A做出反應");
    }
}
//觀察者B
public class BObserver extends Observer {
    @Override
    public void update() {
        System.out.println("觀察者B做出反應");
    }
}
//觀察者A
public class CObserver extends Observer {
    @Override
    public void update() {
        System.out.println("觀察者C做出反應");
    }
}

3. 創建控制主體

public class Subject {
    private List<Observer> observers = new ArrayList<>();

    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
        notifyAllObservers();
    }

    public void add(Observer observer){
        observers.add(observer);
    }

    public void notifyAllObservers(){
        for(Observer observer:observers){
            observer.update();
        }
    }
}

觀察者模式測驗

public class VisitorMain {
    public static void main(String[] args) {
        Subject subject = new Subject();

        subject.add(new AObserver());
        subject.add(new BObserver());
        subject.add(new CObserver());

        System.out.println("主體狀態改變");
        subject.setState("change");
    }
}

在這里插入圖片描述

責任鏈模式

責任鏈模式的定義:為了避免請求發送者與多個請求處理者耦合在一起,于是將所有請求的處理者通過前一物件記住其下一個物件的參考而連成一條鏈;當有請求發生時,可將請求沿著這條鏈傳遞,直到有物件處理它為止,

在責任鏈模式中,客戶只需要將請求發送到責任鏈上即可,無須關心請求的處理細節和請求的傳遞程序,請求會自動進行傳遞,所以責任鏈將請求的發送者和請求的處理者解耦了,

責任鏈的實作:

1. 創建一個處理者抽象類

//處理者抽象類
public abstract class Handler {
    private Handler nextHandler;

    public Handler getNextHandler() {
        return nextHandler;
    }

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handle(String request);
}

2. 創建三個具體的處理者

//處理者A
public class AHandler extends Handler {
    @Override
    public void handle(String request) {
        if (request.equals("A")){
            System.out.println("A號處理者處理了這個問題");
        }else{
            if (this.getNextHandler() != null){
                this.getNextHandler().handle(request);
            }else{
                System.out.println("這個問題沒有人處理");
            }
        }
    }
}
//處理者B
public class BHandler extends Handler {
    @Override
    public void handle(String request) {
        if (request.equals("B")){
            System.out.println("B號處理者處理了這個問題");
        }else{
            if (this.getNextHandler() != null){
                this.getNextHandler().handle(request);
            }else{
                System.out.println("這個問題沒有人處理");
            }
        }
    }
}
//處理者C
public class CHandler extends Handler {
    @Override
    public void handle(String request) {
        if (request.equals("C")){
            System.out.println("C號處理者處理了這個問題");
        }else{
            if (this.getNextHandler() != null){
                this.getNextHandler().handle(request);
            }else{
                System.out.println("這個問題沒有人處理");
            }
        }
    }
}

3. 構建責任鏈處理問題

public class ChainMain {
    public static void main(String[] args) {
        Handler A = new AHandler();
        Handler B = new BHandler();
        Handler C = new CHandler();

        A.setNextHandler(B);
        B.setNextHandler(C);

        A.handle("A");
        A.handle("B");
        A.handle("C");
        A.handle("D");

    }
}

在這里插入圖片描述

備忘錄模式

備忘錄模式保存一個物件的某個狀態,以便在適當的時候恢復物件,備忘錄模式屬于行為型模式,

在不破壞封裝性的前提下,捕獲一個物件的內部狀態,并在該物件之外保存這個狀態,以便以后當需要時能將該物件恢復到原先保存的狀態,該模式又叫快照模式,

備忘錄模式的實作:

備忘錄模式的主要角色如下:

  • 發起人(Originator)角色:記錄當前時刻的內部狀態資訊,提供創建備忘錄和恢復備忘錄資料的功能,實作其他業務功能,它可以訪問備忘錄里的所有資訊,
  • 備忘錄(Memento)角色:負責存盤發起人的內部狀態,在需要的時候提供這些內部狀態給發起人,
  • 管理者(Caretaker)角色:對備忘錄進行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內容進行訪問與修改,

1. 創建備忘錄類

//備忘錄類
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

2. 創建發起人類

//獲取備忘錄狀態
public class Originator {
    private String state;

    public void setState(String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }

    public Memento saveStateToMemento(){
        return new Memento(state);
    }

    public void getStateFromMemento(Memento Memento){
        state = Memento.getState();
    }
}

3. 創建管理者類

//獲取備忘錄狀態
//恢復備忘錄狀態
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<Memento>();

    public void add(Memento state){
        mementoList.add(state);
    }

    public Memento get(int index){
        return mementoList.get(index);
    }
}

4. 備忘錄模式測驗

public class MementoMain {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker careTaker = new Caretaker();
        originator.setState("狀態:S1");
        originator.setState("狀態:S2");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("狀態:S3");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("狀態:S4");

        System.out.println("當前狀態" + originator.getState());
        originator.getStateFromMemento(careTaker.get(0));
        System.out.println("第一次保存的狀態" + originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        System.out.println("第二次保存的狀態" + originator.getState());
    }
}

在這里插入圖片描述

中介者模式

中介者模式定義一個中介物件來封裝一系列物件之間的互動,使原有物件之間的耦合松散,且可以獨立地改變它們之間的互動,中介者模式又叫調停模式,它是迪米特法則的典型應用,

中介者模式的實作:

1. 創建一個Person類

//一個用戶
public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person(String name){
        this.name  = name;
    }

    public void sendMessage(String message){
        Mediator.send(this,message);
    }
}

創建一個中介類

//中介類
public class Mediator {
    public static void send(Person person,String message){
        System.out.println(new Date().toString() + " | " + person.getName() + ":" + message);
    }
}

模擬聊天

public class MediatorMain {
    public static void main(String[] args) {
        Person person1 = new Person("張三");
        Person person2 = new Person("李四");

        person1.sendMessage("你好啊,李四,最近怎么樣");
        person2.sendMessage("我很好,張三你呢");
    }
}

在這里插入圖片描述

迭代器模式

迭代器模式的定義:提供一個物件來順序訪問聚合物件中的一系列資料,而不暴露聚合物件的內部表示,迭代器模式是一種物件行為型模式,

迭代器模式的實作:

1. 創建一個迭代器介面

//迭代器
public interface Iterator {
    public boolean hasNext();
    public Object next();
}

2. 創建一個容器類,并創建內部類實作迭代器介面

public class Container {

    public String[] names;

    public Container(String[] names) {
        this.names = names;
    }

    public Iterator getIterator(){
        return new PersonIterator();
    }

    private class PersonIterator implements Iterator{

        int index;

        @Override
        public boolean hasNext() {
            if(index< names.length){
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            if(this.hasNext()){
                return names[index++];
            }
            return null;
        }
    }
}

3. 使用迭代器輸出所有內容

public class IteratorMain {
    public static void main(String[] args) {
        String[] names = {"張三","李四","王五","趙六","小七","老八"};
        Container container = new Container(names);
        Iterator iterator = container.getIterator();

        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

在這里插入圖片描述

訪問者模式

訪問者模式中,我們使用了一個訪問者類,它改變了元素類的執行演算法,通過這種方式,元素的執行演算法可以隨著訪問者改變而改變,這種型別的設計模式屬于行為型模式,根據模式,元素物件已接受訪問者物件,這樣訪問者物件就可以處理元素物件上的操作,

訪問者模式包含以下主要角色,

  • 抽象訪問者角色:定義一個訪問具體元素的介面,為每個具體元素類對應一個訪問操作 visit() ,該操作中的引數型別標識了被訪問的具體元素,
  • 具體訪問者角色:實作抽象訪問者角色中宣告的各個訪問操作,確定訪問者訪問一個元素時該做什么,
  • 抽象元素角色:宣告一個包含接受操作 accept() 的介面,被接受的訪問者物件作為 accept() 方法的引數,
  • 具體元素角色:實作抽象元素角色提供的 accept() 操作,其方法體通常都是 visitor.visit(this) ,另外具體元素中可能還包含本身業務邏輯的相關操作,
  • 物件結構角色:是一個包含元素角色的容器,提供讓訪問者物件遍歷容器中的所有元素的方法,通常由 List、Set、Map 等聚合類實作,

訪問者模式的實作:

1. 創建訪問者介面

public interface Visitor {
    void visit(Element element);
}

2. 創建具體訪問者

public class AVisitor implements Visitor {
    @Override
    public void visit(Element element) {
        System.out.println(this.getClass().getName() + "訪問了" + element.getClass().getName());
    }
}
public class BVisitor implements Visitor {
    @Override
    public void visit(Element element) {
        System.out.println(this.getClass().getName() + "訪問了" + element.getClass().getName());
    }
}

3. 創建元素介面

public interface Element {
    void accept(Visitor visitor);
}

4. 創建具體元素

public class AElement implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
public class BElement implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

5. 創建物件結構類

public class Structure {
    private List<Element> elements = new ArrayList<>();

    public void add(Element element){
        elements.add(element);
    }

    public void remove(Element element){
        elements.remove(element);
    }

    public void accept(Visitor visitor){
        for(Element element:elements){
            visitor.visit(element);
        }
    }
}

6. 訪問者模式測驗

public class VisitorMain {
    public static void main(String[] args) {
        Structure structure = new Structure();
        structure.add(new AElement());
        structure.add(new BElement());

        Visitor visitor_A = new AVisitor();
        structure.accept(visitor_A);

        Visitor visitor_B = new BVisitor();
        structure.accept(visitor_B);
    }
}

在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/393983.html

標籤:其他

上一篇:圣誕節熬夜整理一套SSM模板,讓你可以快速搭建環境

下一篇:元旦將至,Html動態特效祝福送給你

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more