23種設計方法(Java實現)
每個設計模式已經實現
https://gitee.com/longzhiquan/design_patterns23
1. 創建模式
1.1 單例模式 (single)
定義:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
適用:當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時
1.2 原型模式 (prototype)
定義:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象
適用:當要實例化的類是在運行時刻指定時;或者需要創建多個對象並且這些對象內部狀態相差不大
Demo1
package pattern.prototype.demo1;
import java.util.Date;
public class Video implements Cloneable{
private String name;
private Date date;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Video() {
}
public Video(String name, Date date) {
this.name = name;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", date=" + date +
'}';
}
}
package pattern.prototype.demo1;
import java.util.Date;
public class Test {
//有對象Date的問題
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
Video v1 = new Video("hhh",date);
System.out.println(v1.hashCode());
System.out.println(v1.toString());
Video v2 = (Video) v1.clone();
System.out.println(v2.hashCode());
System.out.println(v2.toString());
}
}
Demo2:
package pattern.prototype.demo2;
import java.util.Date;
public class Video implements Cloneable{
private String name;
private Date date;
//解決Date問題
@Override
protected Object clone() throws CloneNotSupportedException {
Object object = super.clone();
Video v = (Video) object;
v.date = (Date) this.date.clone();
return object;
}
public Video() {
}
public Video(String name, Date date) {
this.name = name;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", date=" + date +
'}';
}
}
package pattern.prototype.demo2;
import java.util.Date;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
Video v1 = new Video("hhh",date);
System.out.println(v1.hashCode());
System.out.println(v1.toString());
Video v2 = (Video) v1.clone();
System.out.println(v2.hashCode());
System.out.println(v2.toString());
date.setTime(12345678);
System.out.println(v1.hashCode());
System.out.println(v1.toString());
System.out.println(v2.hashCode());
System.out.println(v2.toString());
}
}
1.3 工廠模式 (factory)
定義:定義一個用於創建對象的接口,讓子類決定實例化哪一個類。使一個類的實例化延遲到其子類
適用:當一個類不知道它所必須創建的對象的類的時候
1.4 抽象工廠模式 (factory/abstract factory)
定義:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類
適用:一個系統要獨立於它的產品的創建、組合和表示時
與工廠模式的區別:工廠模式的一個工廠接口的子類只能實例化一個產品;抽象工廠能實例多個產品
1.5 構造者模式 (builder)
定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
適用:當創建復雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時
Demo1:
package pattern.builder.demo1;
public abstract class Builder {
abstract void buildA(); //第一步
abstract void buildB(); //第二步
abstract void buildC(); //第三步
abstract Product geProduct();
}
package pattern.builder.demo1;
//工作者
public class Worker extends Builder {
private Product product;
public Worker(){
product = new Product();
}
@Override
void buildA() {
product.setBuildA("1");
}
@Override
void buildB() {
product.setBuildB("2");
}
@Override
void buildC() {
product.setBuildC("3");
}
@Override
Product geProduct() {
return product;
}
}
package pattern.builder.demo1;
//指揮者
public class Director {
public Product build(Builder builder){
builder.buildA();
builder.buildB();
builder.buildC();
return builder.geProduct();
}
}
package pattern.builder.demo1;
public class Product{
private String buildA;
private String buildB;
private String buildC;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
'}';
}
}
package pattern.builder.demo1;
public class Test {
public static void main(String[] args) {
Director director = new Director();
Product build = director.build(new Worker());
System.out.println(build);
}
}
Demo2:
package pattern.builder.demo2;
public abstract class Builder {
abstract Builder buildA(String a);
abstract Builder buildB(String a);
abstract Builder buildC(String b);
abstract Product build();
}
package pattern.builder.demo2;
public class Product {
private String buildA = "1";
private String buildB = "2";
private String buildC = "3";
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
'}';
}
}
package pattern.builder.demo2;
public class Worker extends Builder{
private Product product;
public Worker(){
product = new Product();
}
@Override
Builder buildA(String a) {
product.setBuildA(a);
return this;
}
@Override
Product build() {
return product;
}
@Override
Builder buildB(String b) {
product.setBuildB(b);
return this;
}
@Override
Builder buildC(String c) {
product.setBuildC(c);
return this;
}
}
package pattern.builder.demo2;
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
Product product = worker
.buildA("5")
.buildC("6")
.build();
System.out.println(product);
}
}
2. 結構模式
2.1 適配器模式 (adapter)
定義:將一個類的接口轉換成客戶希望的另外一個接口,Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
角色:適配器(Adapter)、被適配類、對象(Adaptee)
理解:客戶需要Target,現實只有Adaptee,可以用一個實現Target協議的適配器通過類繼承或者對象組合類獲得被Adaptee。
2.2 外觀模式 (facade)
定義:為子系統中一組不同的接口提供統一的接口,一致的界面。
外觀(Facade)模式包含以下主要角色。
- 外觀(Facade)角色:為多個子系統對外提供一個共同的接口。
- 子系統(Sub System)角色:實現系統的部分功能,客戶可以通過外觀角色訪問它。
- 客戶(Client)角色:通過一個外觀角色訪問各個子系統的功能。
2.3 橋接模式 (bridge)
可以將抽象化部分與實現化部分分開,取消二者的繼承關系,改用組合關系。
橋接(Bridge)模式包含以下主要角色。
- 抽象化(Abstraction)角色:定義抽象類,並包含一個對實現化對象的引用。
- 擴展抽象化(Refined Abstraction)角色:是抽象化角色的子類,實現父類中的業務方法,並通過組合關系調用實現化角色中的業務方法。
- 實現化(Implementor)角色:定義實現化角色的接口,供擴展抽象化角色調用。
- 具體實現化(Concrete Implementor)角色:給出實現化角色接口的具體實現。
package pattern.bridge;
public interface Branch {
void info();
}
package pattern.bridge;
public abstract class Computer {
private Branch branch;
public Computer(Branch branch){
this.branch = branch;
}
public void info(){
branch.info();
}
}
class Desktop extends Computer{
public Desktop(Branch branch) {
super(branch);
}
@Override
public void info() {
super.info();
System.out.println("台式機");
}
}
class Laptop extends Computer{
public Laptop(Branch branch) {
super(branch);
}
@Override
public void info() {
super.info();
System.out.println("筆記本");
}
}
package pattern.bridge;
public class Huawei implements Branch{
@Override
public void info() {
System.out.println("華為");
}
}
package pattern.bridge;
public class Xiaomi implements Branch {
@Override
public void info() {
System.out.println("小米");
}
}
package pattern.bridge;
public class Test {
public static void main(String[] args) {
Computer computer = new Laptop(new Huawei());
computer.info();
}
}
2.4 裝飾者模式 (decorator)
定義:動態的給對象添加一些額外的功能,就增加功能來說,裝飾比生成子類更為靈活。
角色:組件接口(Component)、具體的組件、繼承至Component的修飾接口(Decorator)、具體的修飾
2.5 代理模式 (proxy)
代理模式的定義:由於某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作為訪問對象和目標對象之間的中介。
角色:客戶端(Client)、目標接口(subject)代理對象(Proxy)、真正的目標對象(RealSubject)
2.5 demo1
package pattern.proxy.demo1;
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
package pattern.proxy.demo1;
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房東出租房");
}
}
package pattern.proxy.demo1;
public class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
host.rent();
}
public void see(){
System.out.println("看房");
}
}
package pattern.proxy.demo1;
public interface Rent {
public void rent();
}
2.5 demo2
package pattern.proxy.demo2;
public class Client {
public static void main(String[] args) {
UserServiceImp userServiceImp = new UserServiceImp();
UserProxy userProxy = new UserProxy();
userProxy.setUserServiceImp(userServiceImp);
userProxy.add();
}
}
package pattern.proxy.demo2;
public class UserProxy implements UseService{
private UserServiceImp userServiceImp;
public void setUserServiceImp(UserServiceImp userServiceImp) {
this.userServiceImp = userServiceImp;
}
@Override
public void add() {
log("1");
userServiceImp.add();
}
@Override
public void delete() {
log("2");
userServiceImp.delete();
}
@Override
public void update() {
log("4");
userServiceImp.update();
}
@Override
public void query() {
log("3");
userServiceImp.query();
}
public void log(String msg){
System.out.println(msg);
}
}
package pattern.proxy.demo2;
public class UserServiceImp implements UseService{
@Override
public void add() {
System.out.println("add");
}
@Override
public void delete() {
System.out.println("delete");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void query() {
System.out.println("query");
}
}
package pattern.proxy.demo2;
public interface UseService {
void add();
void delete();
void update();
void query();
}
2.6 組合模式(composite)
組合(Composite)模式的定義:有時又叫作部分-整體模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示“部分-整體”的關系,使用戶對單個對象和組合對象具有一致的訪問性。
組合模式包含以下主要角色。
- 抽象構件(Component)角色:它的主要作用是為樹葉構件和樹枝構件聲明公共接口,並實現它們的默認行為。在透明式的組合模式中抽象構件還聲明訪問和管理子類的接口;在安全式的組合模式中不聲明訪問和管理子類的接口,管理工作由樹枝構件完成。
- 樹葉構件(Leaf)角色:是組合中的葉節點對象,它沒有子節點,用於實現抽象構件角色中 聲明的公共接口。
- 樹枝構件(Composite)角色:是組合中的分支節點對象,它有子節點。它實現了抽象構件角色中聲明的接口,它的主要作用是存儲和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
2.7 享元模式(Flyweight)
享元(Flyweight)模式的定義:運用共享技術來有効地支持大量細粒度對象的復用。它通過共享已經存在的又橡來大幅度減少需要創建的對象數量、避免大量相似類的開銷,從而提高系統資源的利用率。
- 抽象享元角色(Flyweight):是所有的具體享元類的基類,為具體享元規范需要實現的公共接口,非享元的外部狀態以參數的形式通過方法傳入。
- 具體享元(Concrete Flyweight)角色:實現抽象享元角色中所規定的接口。
- 非享元(Unsharable Flyweight)角色:是不可以共享的外部狀態,它以參數的形式注入具體享元的相關方法中。
- 享元工廠(Flyweight Factory)角色:負責創建和管理享元角色。當客戶對象請求一個享元對象時,享元工廠檢査系統中是否存在符合要求的享元對象,如果存在則提供給客戶;如果不存在的話,則創建一個新的享元對象。
3. 行為模式
3.1 策略模式 (strategy)
策略(Strategy)模式的定義:該模式定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不同的對象對這些算法進行管理。
策略模式的主要角色如下。
- 抽象策略(Strategy)類:定義了一個公共接口,各種不同的算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實現。
- 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現。
- 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。
3.2 模板方法模式 (template)
模板方法(Template Method)模式的定義如下:定義一個操作中的算法骨架,而將算法的一些步驟延遲到子類中,使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。它是一種類行為型模式。
3.3 命令模式 (command)
可以將系統中的相關操作抽象成命令,使調用者與實現者相關分離,其結構如下。
命令模式包含以下主要角色。
- 抽象命令類(Command)角色:聲明執行命令的接口,擁有執行命令的抽象方法 execute()。
- 具體命令角色(Concrete Command)角色:是抽象命令類的具體實現類,它擁有接收者對象,並通過調用接收者的功能來完成命令要執行的操作。
- 實現者/接收者(Receiver)角色:執行命令功能的相關操作,是具體命令對象業務的真正實現者。
- 調用者/請求者(Invoker)角色:是請求的發送者,它通常擁有很多的命令對象,並通過訪問命令對象來執行相關請求,它不直接訪問接收者。
3.4 訪問者模式(visitor)
唱歌比賽,成功與否
3.5 迭代器模式(iterator)
用一個方法遍歷不同類型的集合或數組數據。
3.6 觀察者模式(observer)
不同公司調用相同的天氣公司的接口
3.7 中介者模式(mediator)
一個具體類發送命令給中介,中介調用另一個具體類執行
3.8 備忘錄模式(memento)
備忘錄(Memento)模式的定義:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,以便以后當需要時能將該對象恢復到原先保存的狀態。該模式又叫快照模式。
- 發起人(Originator)角色:保存狀態對象。
- 備忘錄(Memento)角色:負責保存好記錄,即發起人的內部狀態。
- 管理者(Caretaker)角色:對備忘錄進行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內容進行訪問與修改。
3.9 解釋器模式(interpreter)(難)
解釋器(Interpreter)模式的定義:給分析對象定義一個語言,並定義該語言的文法表示,再設計一個解析器來解釋語言中的句子。也就是說,用編譯語言的方式來分析應用中的實例。這種模式實現了文法表達式處理的接口,該接口解釋一個特定的上下文。
3.10 狀態模式(state)
狀態(State)模式的定義:對有狀態的對象,把復雜的“判斷邏輯”提取到不同的狀態對象中,允許狀態對象在其內部狀態發生改變時改變其行為。
3.11 職責鏈模式 (chain of responsibility)
購買物品,第一個沒有權限就輪到下一個人。