面向对象设计模式详解(Java版)----结构型模式(7种)
面向对象设计模式详解(Java版)----三大类
1. 适配器模式
说明:将一个类的接口转换成客户期望的另一个接口,使不兼容的类能协同工作。像电源转接头,常见于复用旧接口或整合第三方库。
作用:接口转换,让不兼容的类协同工作。
场景:旧系统接口适配,不同格式数据转换,充电器转接头。
关键点:类适配器(继承)与对象适配器(组合),目标接口、适配者与适配器三者协作。
代码示例(第三方外卖接口适配):
interface OrderSystem {
void submitOrder(String item);
}
class LegacyThirdPartyAPI {
public void sendRequest(String data) {
System.out.println("发送:" + data);
}
}
class OrderAdapter implements OrderSystem {
private LegacyThirdPartyAPI api = new LegacyThirdPartyAPI();
public void submitOrder(String item) {
api.sendRequest("{\"food\":\"" + item + "\"}");
}
}
public class AdapterDemo {
public static void main(String[] args) {
OrderSystem os = new OrderAdapter();
os.submitOrder("汉堡"); // 发送:{"food":"汉堡"}
}
}
2. 装饰器模式
说明:动态地给对象附加额外职责,是继承的有力替代。通过包装层层叠加功能,避免为每种组合创建子类,如Java I/O流中套接缓冲功能。
作用:动态添加功能,比继承更灵活。
场景:Java I/O流(BufferedReader包装FileReader),咖啡加料(牛奶或糖)。
关键点:抽象组件、具体组件、装饰器抽象类与具体装饰器,支持嵌套包装。
代码示例(汉堡加料):
interface Burger {
String getDesc();
double getPrice();
}
class PlainBurger implements Burger {
public String getDesc() {
return "汉堡";
}
public double getPrice() {
return 10;
}
}
abstract class ToppingDecorator implements Burger {
protected Burger burger;
}
class Cheese extends ToppingDecorator {
public Cheese(Burger b) {
this.burger = b;
}
public String getDesc() {
return burger.getDesc() + "+芝士";
}
public double getPrice() {
return burger.getPrice() + 2;
}
}
public class DecoratorDemo {
public static void main(String[] args) {
Burger burger = new Cheese(new PlainBurger());
// 汉堡+芝士 价格:12.0
System.out.println(burger.getDesc() + " 价格:" + burger.getPrice());
}
}
3. 代理模式
说明:为对象提供替身以控制对该对象的访问。可延迟加载大对象、检查访问权限或记录日志,与装饰器外观相似但侧重控制而非增强。
作用:控制对象访问,延迟加载,权限校验。
场景:虚拟代理(图片懒加载),保护代理(权限控制),远程代理(RPC)。
关键点:抽象主题、真实主题与代理类,JDK动态代理或CGLIB,区分控制与增强。
代码示例(点餐权限控制):
interface OrderService {
void order(String food);
}
class RealOrderService implements OrderService {
public void order(String food) {
System.out.println("下单:" + food);
}
}
class OrderProxy implements OrderService {
private RealOrderService real = new RealOrderService();
private String userRole;
public OrderProxy(String role) {
this.userRole = role;
}
public void order(String food) {
if ("VIP".equals(userRole)){
real.order(food);
}else{
System.out.println("无权限");
}
}
}
public class ProxyDemo {
public static void main(String[] args) {
OrderService os = new OrderProxy("VIP");
os.order("汉堡"); // 下单:汉堡
OrderService os2 = new OrderProxy("普通");
os2.order("汉堡"); // 无权限
}
}
4. 外观模式
说明:为复杂子系统提供统一简化的高层接口,隐藏内部混乱依赖。客户端只与外观交互,降低使用门槛,如一键拍照封装调焦、曝光等步骤。
作用:简化复杂子系统调用,降低耦合。
场景:复杂第三方库封装,MVC中的Service层,一键电脑启动。
关键点:外观类(门面)与多个子系统类,不封装子系统内部逻辑,体现迪米特法则。
代码示例(一键点餐):
class Grill {
void grillMeat() {
System.out.println("烤肉");
}
}
class Fry {
void fryPotato() {
System.out.println("炸薯条");
}
}
class Pour {
void pourDrink() {
System.out.println("倒可乐");
}
}
class OrderFacade {
private Grill grill = new Grill();
private Fry fry = new Fry();
private Pour pour = new Pour();
public void makeMeal() {
grill.grillMeat();
fry.fryPotato();
pour.pourDrink();
System.out.println("套餐完成");
}
}
public class FacadeDemo {
public static void main(String[] args) {
OrderFacade facade = new OrderFacade();
facade.makeMeal();
// 烤肉 炸薯条 倒可乐 套餐完成
}
}
5. 桥接模式
说明:将抽象部分与实现部分分离,使两者可独立变化而不互相影响。通过组合代替多维度继承,解决类爆炸问题,如不同形状与颜色的自由组合。
作用:分离抽象与实现,独立变化,避免类爆炸。
场景:跨平台应用(不同系统下不同形状窗口),遥控器与设备。
关键点:抽象类持有实现接口引用,组合优于继承,两个独立变化维度。
代码示例(餐品与口味分离):
interface Flavor {
String getFlavor();
}
class Spicy implements Flavor {
public String getFlavor() {
return "辣味";
}
}
class Sweet implements Flavor {
public String getFlavor() {
return "甜味";
}
}
abstract class Food {
protected Flavor flavor;
Food(Flavor f) {
this.flavor = f;
}
abstract String getName();
}
class ChickenWing extends Food {
public ChickenWing(Flavor f) {
super(f);
}
String getName() {
return flavor.getFlavor() + "鸡翅";
}
}
public class BridgeDemo {
public static void main(String[] args) {
Food food = new ChickenWing(new Spicy());
System.out.println(food.getName()); // 辣味鸡翅
}
}
6. 组合模式
说明:将对象组织成树形结构以表示部分‑整体层次,让客户端统一对待单个对象和组合对象。典型如文件系统中文件夹与文件操作无差异。
作用:统一处理叶子节点与容器节点,表示树形结构。
场景:文件系统(文件与文件夹),UI布局(容器与控件),组织架构树。
关键点:组件抽象类(统一操作),叶子节点与容器节点(持有子节点列表),透明模式或安全模式。
代码示例(套餐组合):
import java.util.*;
interface MealItem {
double getPrice();
}
class SingleItem implements MealItem {
private double price;
SingleItem(double p) {
price = p;
}
public double getPrice() {
return price;
}
}
class Combo implements MealItem {
private List<MealItem> items = new ArrayList<>();
public void add(MealItem item) {
items.add(item);
}
public double getPrice() {
return items.stream().mapToDouble(MealItem::getPrice).sum() * 0.9;
}
}
public class CompositeDemo {
public static void main(String[] args) {
Combo combo = new Combo();
combo.add(new SingleItem(10));
combo.add(new SingleItem(8));
System.out.println("套餐价格:" + combo.getPrice()); // 套餐价格:16.2
}
}
7. 享元模式
说明:通过共享技术高效支持大量细粒度对象,减少内存占用。区分可共享的内部状态与随环境变化的外部状态,如文本编辑器复用相同字符对象。
作用:减少内存占用,共享细粒度对象。
场景:文本编辑器字符对象,游戏子弹或树木,线程池中的线程。
关键点:区分内部状态(共享)与外部状态(不共享),享元工厂管理对象池。
代码示例(汉堡配料共享):
import java.util.*;
class Ingredient {
private String name;
Ingredient(String n) {
name = n;
}
public String getName() {
return name;
}
}
class IngredientFactory {
private static Map<String, Ingredient> pool = new HashMap<>();
public static Ingredient get(String name) {
if (!pool.containsKey(name)) {
pool.put(name, new Ingredient(name));
}
return pool.get(name);
}
}
public class FlyweightDemo {
public static void main(String[] args) {
Ingredient cheese1 = IngredientFactory.get("芝士");
Ingredient cheese2 = IngredientFactory.get("芝士");
System.out.println(cheese1 == cheese2); // true
}
}
更多推荐
所有评论(0)