设计模式结构型模式结构型模式关注的是类和对象之间如何组合如何让系统结构更灵活、更容易扩展。创建型模式解决“对象怎么创建”结构型模式解决“对象怎么组装”。一、结构型模式总览结构型模式主要解决以下问题类和对象之间如何组合成更大的结构如何降低对象之间的耦合如何在不修改原有代码的情况下扩展功能如何让不兼容接口能够一起工作如何减少大量对象带来的内存消耗模式核心思想适合场景适配器 Adapter让不兼容接口能一起工作老接口适配新系统桥接 Bridge抽象和实现分离多维度变化组合 Composite树形结构统一处理文件夹、菜单、组织架构装饰器 Decorator动态增强对象功能IO 流、功能叠加外观 Facade给复杂系统提供简单入口封装复杂子系统享元 Flyweight共享对象减少内存大量重复对象代理 Proxy控制对目标对象的访问权限、缓存、远程代理结构型模式整体理解图结构型模式接口适配适配器 Adapter多维度解耦桥接 Bridge整体部分统一组合 Composite功能动态增强装饰器 Decorator简化复杂系统外观 Facade共享减少内存享元 Flyweight控制对象访问代理 Proxy二、适配器模式 Adapter1. 核心思想把一个类的接口转换成客户端想要的另一个接口。简单说原来接口不兼容加一个“转换头”。生活例子Type-C 转 USB 转接头港版插头转国标插座读卡器把 SD 卡转换成 USB 接口2. 适合场景旧系统接口不能直接修改新系统需要使用旧类的功能第三方接口和自己系统接口不一致想复用已有代码但接口不匹配3. 配图理解客户端需要 TypeC 接口UsbToTypeCAdapter 适配器UsbCharger 旧接口完成 USB 充电4. Java 示例java代码解读复制代码interface TypeC { void chargeWithTypeC(); } class UsbCharger { public void chargeWithUsb() { System.out.println(使用 USB 充电); } } class UsbToTypeCAdapter implements TypeC { private UsbCharger usbCharger; public UsbToTypeCAdapter(UsbCharger usbCharger) { this.usbCharger usbCharger; } public void chargeWithTypeC() { System.out.println(适配器转换 Type-C 到 USB); usbCharger.chargeWithUsb(); } } public class Main { public static void main(String[] args) { UsbCharger usbCharger new UsbCharger(); TypeC adapter new UsbToTypeCAdapter(usbCharger); adapter.chargeWithTypeC(); } }5. 优缺点优点可以复用旧代码解决接口不兼容问题客户端不需要知道适配细节符合开闭原则可以在不改旧类的情况下新增适配能力缺点适配器太多会让系统结构复杂只是接口转换不应该滥用如果旧接口设计很差适配器只能缓解问题不能彻底解决问题6. 记忆口诀适配器接口不合加个转换器。三、桥接模式 Bridge1. 核心思想将抽象部分和实现部分分离使它们可以独立变化。简单说两个维度都在变化时不要疯狂继承而是用组合把它们桥接起来。2. 适合场景适合两个或多个维度都在变化的场景。例如手机有两个变化维度品牌华为、小米、苹果颜色黑色、白色、蓝色如果不用桥接可能要写黑色华为手机白色华为手机蓝色华为手机黑色小米手机白色小米手机蓝色小米手机类数量会迅速膨胀。3. 配图理解4. Java 示例java代码解读复制代码interface Color { String getColor(); } class Black implements Color { public String getColor() { return 黑色; } } class White implements Color { public String getColor() { return 白色; } } abstract class Phone { protected Color color; public Phone(Color color) { this.color color; } public abstract void show(); } class HuaweiPhone extends Phone { public HuaweiPhone(Color color) { super(color); } public void show() { System.out.println(color.getColor() 华为手机); } } class XiaomiPhone extends Phone { public XiaomiPhone(Color color) { super(color); } public void show() { System.out.println(color.getColor() 小米手机); } } public class Main { public static void main(String[] args) { Phone phone new HuaweiPhone(new Black()); phone.show(); } }5. 优缺点优点避免类爆炸抽象和实现可以独立扩展比继承更加灵活符合组合优于继承的思想缺点理解难度比简单继承高需要正确识别系统中的多个变化维度设计过度时会让简单问题复杂化6. 记忆口诀桥接模式两个维度各自变化中间架桥。四、组合模式 Composite1. 核心思想把对象组织成树形结构让客户端可以用统一方式处理单个对象和组合对象。简单说单个对象和一组对象对外表现得像同一种东西。2. 适合场景文件和文件夹公司部门和员工菜单和子菜单树形目录组织架构3. 配图理解根目录 Folder文件 a.txt图片文件夹 Folder1.png2.png文档文件夹 Folder方案.docx4. Java 示例java代码解读复制代码import java.util.ArrayList; import java.util.List; interface FileSystemNode { void show(); } class FileNode implements FileSystemNode { private String name; public FileNode(String name) { this.name name; } public void show() { System.out.println(文件 name); } } class FolderNode implements FileSystemNode { private String name; private ListFileSystemNode children new ArrayList(); public FolderNode(String name) { this.name name; } public void add(FileSystemNode node) { children.add(node); } public void show() { System.out.println(文件夹 name); for (FileSystemNode child : children) { child.show(); } } } public class Main { public static void main(String[] args) { FolderNode root new FolderNode(根目录); root.add(new FileNode(a.txt)); FolderNode img new FolderNode(图片); img.add(new FileNode(1.png)); img.add(new FileNode(2.png)); root.add(img); root.show(); } }5. 优缺点优点适合树形结构客户端可以统一处理叶子节点和容器节点扩展方便层级结构清晰缺点对类型限制不够严格树形结构太复杂时调试困难如果叶子对象和容器对象差异太大统一接口可能会显得勉强6. 记忆口诀组合模式整体和部分一样对待。五、装饰器模式 Decorator1. 核心思想在不改变原有对象结构的情况下动态地给对象增加新的功能。简单说原来的对象不改用一层一层“包装”来增强功能。生活例子奶茶加珍珠、加椰果、加布丁咖啡加牛奶、加糖、加冰手机壳给手机增加防摔、支架、卡包功能2. 适合场景想给对象动态增加功能不想通过继承创建大量子类功能可以一层一层叠加Java IO 流例如 BufferedInputStream 包装 FileInputStream3. 配图理解普通咖啡牛奶装饰器糖装饰器普通咖啡 牛奶 糖4. Java 示例java代码解读复制代码interface Coffee { String getDescription(); double cost(); } class SimpleCoffee implements Coffee { public String getDescription() { return 普通咖啡; } public double cost() { return 10; } } abstract class CoffeeDecorator implements Coffee { protected Coffee coffee; public CoffeeDecorator(Coffee coffee) { this.coffee coffee; } } class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee coffee) { super(coffee); } public String getDescription() { return coffee.getDescription() 牛奶; } public double cost() { return coffee.cost() 3; } } class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee coffee) { super(coffee); } public String getDescription() { return coffee.getDescription() 糖; } public double cost() { return coffee.cost() 1; } } public class Main { public static void main(String[] args) { Coffee coffee new SimpleCoffee(); coffee new MilkDecorator(coffee); coffee new SugarDecorator(coffee); System.out.println(coffee.getDescription()); System.out.println(价格 coffee.cost()); } }5. 优缺点优点比继承更加灵活可以动态增加功能多个装饰器可以自由组合符合开闭原则缺点装饰层数太多时代码理解成本会变高调试时不容易看清楚对象被包装了几层如果装饰器设计不好容易让结构复杂化6. 记忆口诀装饰器模式不改原对象外面套功能。六、外观模式 Facade1. 核心思想给复杂子系统提供一个简单统一的入口让客户端不用关心内部复杂细节。简单说里面很复杂外面给你一个简单按钮。生活例子一键开启影院模式关灯打开电视打开音响拉上窗帘用户不需要一个一个操作只需要点击“影院模式”。2. 适合场景子系统很复杂客户端不想直接接触很多类想降低客户端和子系统之间的耦合给旧系统封装一个简单入口3. 配图理解客户端HomeTheaterFacade 外观类灯光系统电视系统音响系统窗帘系统4. Java 示例java代码解读复制代码class Light { public void off() { System.out.println(关灯); } } class TV { public void on() { System.out.println(打开电视); } } class SoundSystem { public void on() { System.out.println(打开音响); } } class Curtain { public void close() { System.out.println(拉上窗帘); } } class HomeTheaterFacade { private Light light; private TV tv; private SoundSystem soundSystem; private Curtain curtain; public HomeTheaterFacade() { this.light new Light(); this.tv new TV(); this.soundSystem new SoundSystem(); this.curtain new Curtain(); } public void watchMovie() { System.out.println(开启影院模式); light.off(); curtain.close(); tv.on(); soundSystem.on(); } } public class Main { public static void main(String[] args) { HomeTheaterFacade facade new HomeTheaterFacade(); facade.watchMovie(); } }5. 优缺点优点简化客户端调用降低客户端和子系统之间的耦合隐藏系统内部复杂细节让系统更容易使用缺点外观类可能会变得很庞大如果外观类封装得太死灵活性会下降不适合替代所有子系统接口6. 记忆口诀外观模式复杂系统给个简单门面。七、享元模式 Flyweight1. 核心思想通过共享对象来减少内存占用。简单说相同的对象不要重复创建能共用就共用。生活例子游戏地图里有很多树树的类型、颜色、图片资源可能是一样的但是每棵树的位置不同如果每棵树都保存完整数据会非常浪费内存。享元模式会把相同的部分共享起来只把不同的部分单独保存。2. 适合场景系统中有大量相似对象对象创建成本高很多对象的内部状态可以共享游戏场景、字符串常量池、缓存池、连接池3. 关键概念享元模式一般会把对象状态分成两类内部状态可以共享例如树的类型、颜色、图片外部状态不能共享例如树的位置坐标4. 配图理解5. Java 示例java代码解读复制代码import java.util.HashMap; import java.util.Map; class TreeType { private String name; private String color; public TreeType(String name, String color) { this.name name; this.color color; } public void display(int x, int y) { System.out.println(树类型 name 颜色 color 位置( x , y )); } } class TreeFactory { private static MapString, TreeType treeTypes new HashMap(); public static TreeType getTreeType(String name, String color) { String key name _ color; if (!treeTypes.containsKey(key)) { treeTypes.put(key, new TreeType(name, color)); System.out.println(创建新的树类型 key); } return treeTypes.get(key); } } class Tree { private int x; private int y; private TreeType treeType; public Tree(int x, int y, TreeType treeType) { this.x x; this.y y; this.treeType treeType; } public void display() { treeType.display(x, y); } } public class Main { public static void main(String[] args) { TreeType greenTree TreeFactory.getTreeType(松树, 绿色); Tree tree1 new Tree(10, 20, greenTree); Tree tree2 new Tree(30, 40, greenTree); Tree tree3 new Tree(50, 60, greenTree); tree1.display(); tree2.display(); tree3.display(); } }6. 优缺点优点减少对象数量节省内存适合大量重复对象场景可以提高系统性能缺点代码复杂度会增加需要区分内部状态和外部状态如果对象差异很大就不适合使用7. 记忆口诀享元模式共享重复对象省内存。八、代理模式 Proxy1. 核心思想给目标对象提供一个代理对象由代理对象控制对目标对象的访问。简单说你不直接找本人而是先找代理人。生活例子明星经纪人房产中介代购访问网站时的代理服务器代理对象可以在真正调用目标对象之前或之后增加额外逻辑比如权限校验、缓存、日志、延迟加载。