設計模式就像做菜的食譜,告訴我們遇到常見問題時該用什么"烹飪方法"。今天我就用最生活化的例子,帶大家輕松掌握23種設計模式的精髓。
一、創建型模式(5種):怎么"造東西"
1. 單例模式:公司的CEO
問題:一個公司只需要一個CEO
解決:
public class CEO {private static CEO instance;private CEO() {} // 防止外部newpublic static CEO getInstance() {if (instance == null) {instance = new CEO();}return instance;}
}
生活類比:不管問多少個人"誰是CEO",得到的都是同一個人
2. 工廠方法:奶茶店點單
問題:顧客不需要知道奶茶怎么做
解決:
interface MilkTea {void make();
}class BubbleTea implements MilkTea {public void make() { System.out.println("加珍珠"); }
}class MilkTeaShop {public MilkTea orderTea(String type) {if ("bubble".equals(type)) {return new BubbleTea();}// 其他口味...}
}
生活類比:告訴店員要珍珠奶茶,店員幫你做好,你不用管制作過程
3. 抽象工廠:家具套裝
問題:要買整套風格匹配的家具
解決:
interface FurnitureFactory {Chair createChair();Table createTable();
}class ModernFactory implements FurnitureFactory {public Chair createChair() { return new ModernChair(); }public Table createTable() { return new ModernTable(); }
}
生活類比:買"北歐風"套裝,確保沙發、茶幾風格統一
4. 建造者模式:組裝電腦
問題:配電腦有很多可選配件,組合復雜
解決:
class Computer {private String CPU;private String GPU;// 其他配件...// 建造者內部類public static class Builder {private String CPU;private String GPU;public Builder setCPU(String cpu) {this.CPU = cpu;return this; // 返回Builder自己,實現鏈式調用}public Builder setGPU(String gpu) {this.GPU = gpu;return this;}public Computer build() {Computer computer = new Computer();computer.CPU = this.CPU;computer.GPU = this.GPU;return computer;}}
}// 使用
Computer myPC = new Computer.Builder().setCPU("i7").setGPU("RTX 3080").build();
生活類比:去電腦城配機,告訴老板:"我要i7CPU,3080顯卡,16G內存...",老板幫你組裝好整機
5.?原型模式:復印簡歷
問題:創建重復對象成本高
解決:
class Resume implements Cloneable {private String name;private String experience;// 實現克隆方法public Resume clone() {try {return (Resume)super.clone();} catch (CloneNotSupportedException e) {return null;}}
}// 使用
Resume original = new Resume();
Resume copy = original.clone();
生活類比:復印簡歷原件,不用每次都手寫一份新的
二、結構型模式(7種):怎么"組裝東西"
1. 適配器:電源轉換插頭
問題:中國插頭沒法用美國插座
解決:
class ChinesePlug {void charge() { System.out.println("中國插頭充電"); }
}interface AmericanSocket {void power();
}class Adapter implements AmericanSocket {private ChinesePlug plug;public Adapter(ChinesePlug plug) {this.plug = plug;}public void power() {plug.charge();}
}
生活類比:轉換插頭讓不同標準的電器能工作
2. 裝飾器:給奶茶加料
問題:想靈活添加珍珠、椰果等配料
解決:
abstract class MilkTea {abstract String getDescription();abstract double cost();
}class BubbleDecorator extends MilkTea {private MilkTea milkTea;public BubbleDecorator(MilkTea milkTea) {this.milkTea = milkTea;}public String getDescription() {return milkTea.getDescription() + "+珍珠";}public double cost() {return milkTea.cost() + 2.0;}
}
生活類比:先要杯原味奶茶,再說"加珍珠","再加布丁"
3. 橋接模式:遙控器與電器
問題:遙控器要控制多種電器
解決:
// 實現部分
interface Device {void turnOn();void turnOff();
}class TV implements Device {public void turnOn() { System.out.println("電視開機"); }public void turnOff() { System.out.println("電視關機"); }
}// 抽象部分
abstract class RemoteControl {protected Device device;public RemoteControl(Device device) {this.device = device;}abstract void power();
}class BasicRemote extends RemoteControl {public BasicRemote(Device device) {super(device);}public void power() {device.turnOn();}
}
生活類比:同一個遙控器可以控制電視、空調等不同電器
4. 組合模式:公司組織架構
問題:統一處理單個對象和對象集合
解決:
interface Employee {void showDetails();
}class Developer implements Employee {private String name;public void showDetails() {System.out.println("開發員:" + name);}
}class Department implements Employee {private List<Employee> employees = new ArrayList<>();public void addEmployee(Employee e) {employees.add(e);}public void showDetails() {for (Employee e : employees) {e.showDetails();}}
}
生活類比:查看部門信息會自動展示所有成員信息
5. 享元模式:共享單車
問題:大量相似對象消耗內存
解決:
class Bike {private String color; // 內部狀態(可共享)private String rider; // 外部狀態(不可共享)public Bike(String color) {this.color = color;}public void ride(String rider) {this.rider = rider;System.out.println(rider + "騎走" + color + "單車");}
}class BikeFactory {private static Map<String, Bike> pool = new HashMap<>();public static Bike getBike(String color) {if (!pool.containsKey(color)) {pool.put(color, new Bike(color));}return pool.get(color);}
}
生活類比:共享單車公司不會為每個用戶造新車,而是大家共用
6.? 代理模式:房產中介
問題:不想/不能直接訪問對象
解決:
interface House {void sell();
}class Owner implements House {public void sell() {System.out.println("房主賣房");}
}class Agent implements House {private House house;public Agent(House house) {this.house = house;}public void sell() {System.out.println("中介帶看房");house.sell();System.out.println("中介收傭金");}
}
生活類比:通過中介買房,不用直接聯系房東
?
三、行為型模式(11種):怎么做事情
1. 觀察者:微信群通知
問題:消息要實時通知所有群成員
解決:
class WeChatGroup {private List<Member> members = new ArrayList<>();public void addMember(Member m) {members.add(m);}public void notifyMembers(String msg) {for (Member m : members) {m.receive(msg);}}
}class Member {void receive(String msg) {System.out.println("收到消息:" + msg);}
}
生活類比:群里發消息,所有成員手機都會響
2. 策略:出行導航
問題:根據情況選擇不同路線
解決:
interface RouteStrategy {void buildRoute();
}class DrivingStrategy implements RouteStrategy {public void buildRoute() { System.out.println("開車路線"); }
}class WalkingStrategy implements RouteStrategy {public void buildRoute() { System.out.println("步行路線"); }
}class Navigator {private RouteStrategy strategy;public void setStrategy(RouteStrategy s) {this.strategy = s;}public void execute() {strategy.buildRoute();}
}
生活類比:高德地圖可以切換"駕車"、"步行"等不同導航模式
3. 責任鏈模式:審批流程
問題:請求需要多級處理
解決:
abstract class Approver {protected Approver next;public void setNext(Approver next) {this.next = next;}abstract void processRequest(int amount);
}class Manager extends Approver {public void processRequest(int amount) {if (amount <= 1000) {System.out.println("經理批準");} else if (next != null) {next.processRequest(amount);}}
}class CEO extends Approver {public void processRequest(int amount) {System.out.println("CEO批準");}
}// 使用
Approver chain = new Manager();
chain.setNext(new CEO());
chain.processRequest(5000); // CEO批準
生活類比:報銷流程,金額小的組長批,大的要經理批
4. 命令模式:餐廳點餐
問題:將請求封裝為對象
解決:
interface Command {void execute();
}class OrderCommand implements Command {private Chef chef;private String dish;public OrderCommand(Chef chef, String dish) {this.chef = chef;this.dish = dish;}public void execute() {chef.cook(dish);}
}class Waiter {private List<Command> orders = new ArrayList<>();public void takeOrder(Command cmd) {orders.add(cmd);}public void placeOrders() {for (Command cmd : orders) {cmd.execute();}}
}
生活類比:服務員記下訂單(命令對象),后廚按訂單做菜
5. 迭代器模式:電視頻道切換
問題:統一遍歷不同集合
解決:
interface ChannelIterator {boolean hasNext();String next();
}class TVChannelList {private String[] channels = {"CCTV1", "CCTV5", "HunanTV"};public ChannelIterator iterator() {return new ConcreteIterator();}private class ConcreteIterator implements ChannelIterator {private int position;public boolean hasNext() {return position < channels.length;}public String next() {return channels[position++];}}
}
生活類比:用遙控器上下鍵切換頻道,不用知道頻道如何存儲
6. 中介者模式:機場塔臺
問題:對象間直接交互復雜
解決:
class Airplane {private ControlTower tower;public void requestLanding() {tower.requestLanding(this);}
}class ControlTower {public void requestLanding(Airplane plane) {System.out.println("允許降落");}
}
生活類比:飛機不直接溝通,都通過塔臺協調
7. 備忘錄模式:游戲存檔
問題:需要保存和恢復對象狀態
解決:
class Game {private int level;public GameMemento save() {return new GameMemento(level);}public void load(GameMemento memento) {this.level = memento.getLevel();}
}class GameMemento {private final int level;public GameMemento(int level) {this.level = level;}public int getLevel() {return level;}
}
生活類比:游戲存檔讀檔功能
8. 狀態模式:紅綠燈切換
問題:對象行為隨狀態改變
解決:
interface TrafficLightState {void handle();
}class RedLight implements TrafficLightState {public void handle() {System.out.println("紅燈停");}
}class TrafficLight {private TrafficLightState state;public void setState(TrafficLightState state) {this.state = state;}public void change() {state.handle();}
}
生活類比:交通燈自動按紅→綠→黃變化
9. 模板方法模式:沖泡飲料
問題:固定流程中的步驟變化
解決:
abstract class Beverage {// 模板方法(固定流程)final void prepare() {boilWater();brew();pourInCup();addCondiments();}abstract void brew();abstract void addCondiments();void boilWater() {System.out.println("燒水");}void pourInCup() {System.out.println("倒入杯子");}
}class Coffee extends Beverage {void brew() { System.out.println("沖泡咖啡"); }void addCondiments() { System.out.println("加糖和牛奶"); }
}
生活類比:泡茶和泡咖啡步驟類似,但具體操作不同
10. 訪問者模式:醫生問診
問題:對一組對象執行多種操作
解決:
interface Patient {void accept(Doctor visitor);
}class ChildPatient implements Patient {public void accept(Doctor visitor) {visitor.visit(this);}
}interface Doctor {void visit(ChildPatient patient);void visit(AdultPatient patient);
}class Pediatrician implements Doctor {public void visit(ChildPatient patient) {System.out.println("檢查兒童生長發育");}public void visit(AdultPatient patient) {System.out.println("成人不看兒科");}
}
生活類比:不同專科醫生對病人做不同檢查