IT评测·应用市场-qidao123.com技术社区
标题:
概念实践极速入门 - 常用的设计模式 - 简单生活例子
[打印本页]
作者:
魏晓东
时间:
5 天前
标题:
概念实践极速入门 - 常用的设计模式 - 简单生活例子
概念实践极速入门 - 常用的设计模式 - 简单生活例子
SOLID 五大设计原则的首字母缩写
单一职责原则 和 开闭原则 就省略啦, 这两个概念很简单, 为了写而写反而轻易误导人~* 鼓励各人字面明白!
// 哎呀还是解释吧
单一(S): 单干一件事; 开闭(O): 拓展开放, 修改关闭!
复制代码
里氏替换原则(L)
仅仅发生在
继续
体系中
子类不能影响父类独有行为
例
:对象构建自由与必要次序规范鸵鸟不能飞但是继续到了鸟具有了飞的行为
错误示范
:对象构建自由与必要次序规范重写飞的方法改成 -> ‘跑’
不能重写父类稳定的行为
接口隔离原则(I)
方式一 对象构建自由与必要次序规范负担非自身职责的行为 抽象为接口, 选择性依赖
方式二 对象构建自由与必要次序规范接口默认行为空实现
依赖倒置原则(D)
高层模块不应该依赖低层模块
高层模块
:业务层, 应该依赖的实现是抽象
高层模块另一种解释
:被调用方
迪米特原则(最少知识原则)- 拓展
核心
:只与直接朋侪对话,减少模块耦合
场景
:订单服务不应直接调用库存DAO
// 错误示范:用户直接查货车司机信息
class User {
void trackDelivery(Order order) {
// 用户竟然能拿到货车司机电话!过度暴露细节
System.out.println("货车司机电话:" + order.getTruck().getDriver().getPhone());
}
}
// 正确做法:用户只能问订单物流状态
class User {
void trackDelivery(Order order) {
// 用户只需和订单对话
System.out.println("物流状态:" + order.getDeliveryStatus());
}
}
// 订单类封装物流细节
class Order {
private Delivery delivery;
String getDeliveryStatus() {
// 内部处理复杂查询:订单→货车→司机→位置
return "司机" + delivery.getDriverName()
+ "正在" + delivery.getCurrentLocation();
}
}
复制代码
合成复用原则 - 拓展
核心
:优先用组合,其次继续
反例
:通过继续扩展日志功能(导致类爆炸)
// 错误示范:继承实现加料
class Americano {}
class AmericanoWithSugar extends Americano {} // 类爆炸开始
class AmericanoWithMilk extends Americano {}
class AmericanoWithSugarAndMilk extends Americano {} // 已经失控...
// 正确示范:组合调料(合成复用)
class Coffee {
private List<String> toppings = new ArrayList<>(); // 组合容器
// 动态加料
public void addTopping(String topping) {
toppings.add(topping);
}
public void show() {
System.out.println("咖啡加料:" + String.join("+", toppings));
}
}
// 使用
Coffee coffee = new Coffee();
coffee.addTopping("糖");
coffee.addTopping("奶油");
coffee.show(); // 输出:咖啡加料:糖+奶油
复制代码
设计模式 - 场景 与 极简择要
一、工厂模式:创建订单
概念
:抽象共同依赖实现,通过子类决定最终逻辑
// 抽象产品接口
public interface Order {
void create();
}
// 具体产品:普通订单
public class NormalOrder implements Order {
@Override
public void create() { System.out.println("创建普通订单"); }
}
// 具体产品:VIP订单
public class VipOrder implements Order {
@Override
public void create() { System.out.println("创建 VIP 订单"); }
}
// 工厂类:根据类型返回订单对象
public class OrderFactory {
public Order createOrder(String type) {
if ("vip".equals(type)) return new VipOrder();
else return new NormalOrder();
}
}
// 使用
Order order = new OrderFactory().createOrder("vip");
order.create();
复制代码
模式作用
:
隐藏订单具体类的创建逻辑,调用方只需通报范例参数。
新增订单范例时(如团购订单),无需修改调用方代码。
二、单例模式:全局日志工具
概念
:资源独占
细节
:全局唯一
public class Logger {
private static Logger instance;
// 私有构造方法
private Logger() {}
// 双重非空检查 + 锁 保证线程安全
public static Logger getInstance() {
if (instance == null) {
synchronized (Logger.class) {
if (instance == null) {
instance = new Logger();
}
}
}
return instance;
}
public void log(String message) {
System.out.println("[LOG] " + message);
}
}
// 使用
Logger.getInstance().log("订单创建成功");
复制代码
模式作用
:确保整个系统共享同一个日志实例,避免重复创建文件句柄或网络毗连。
三、建造者模式:构建复杂订单对象
概念
:对象构建自由 与 必要次序规则
public class OrderDetail {
private String orderId; // 必要参数
private String userId;
private List<String> items;
// 私有构造器,只能通过 Builder 创建
private OrderDetail(Builder builder) {
this.orderId = builder.orderId;
this.userId = builder.userId;
this.items = builder.items;
}
// 建造者内部类
public static class Builder {
private String orderId;
private String userId;
private List<String> items = new ArrayList<>();
public Builder orderId(String orderId) {
this.orderId = orderId;
return this;
}
public Builder userId(String userId) { /* ... */ }
public Builder addItem(String item) { /* ... */ }
public OrderDetail build() {
// 通过异常强制限制
if (orderId == null) throw new IllegalArgumentException("orderId必填");
return new OrderDetail(this);
}
}
}
// 使用
OrderDetail order = new OrderDetail.Builder()
.orderId("123") // 这下不得不填了 总结: 选填和必填的结合
.userId("user1")
.addItem("手机")
.addItem("耳机")
.build();
复制代码
模式作用
办理多参数构造的混乱(尤其是可选参数),强制必要参数填写。
链式调用更直观(对比含 5 个参数的构造方法)。
四、代理模式:支付前的权限校验
概念
:控制访问,代替直接访问
细节
:代理与被代理实现同一接口
// 抽象支付接口
public interface Payment {
void pay(int amount);
}
// 具体支付类
public class Alipay implements Payment {
@Override
public void pay(int amount) {
System.out.println("支付宝支付:" + amount + "元");
}
}
// 代理类:添加权限校验
public class PaymentProxy implements Payment {
private Payment realPayment;
public PaymentProxy(Payment realPayment) {
this.realPayment = realPayment;
}
@Override
public void pay(int amount) {
if (checkPermission()) {
realPayment.pay(amount);
} else {
System.out.println("无权支付");
}
}
private boolean checkPermission() {
// 模拟权限检查
return true;
}
}
// 使用
Payment payment = new PaymentProxy(new Alipay());
payment.pay(100);
复制代码
模式作用
不修改 Alipay 源码的情况下,增长权限校验逻辑。
符合
开闭原则
(对扩睁开放,对修改关闭)。
五、观察者模式:吃瓜群众
概念
:具有实时报告的行为监控
细节
:双方在打架, 吃瓜人就是观察者, 当打出什么来了(状态变动), 就去报警;
:第二个例子就是订阅,当有什么活动了,就通知
// 主题接口
interface FightSubject {
void addObserver(Onlooker o);
void notifyObservers(String msg);
}
// 具体打架事件
class Fight implements FightSubject {
private List<Onlooker> people = new ArrayList<>();
public void fightHappen(String result) {
System.out.println("打架结果: " + result);
notifyObservers(result);
}
@Override
public void addObserver(Onlooker o) { people.add(o); }
@Override
public void notifyObservers(String msg) {
people.forEach(o -> o.update(msg));
}
}
// 观察者
class Onlooker {
public void update(String msg) {
if (msg.contains("倒地")) {
System.out.println("吃瓜群众: 报警!有人受伤");
}
}
}
// 使用
Fight fight = new Fight();
fight.addObserver(new Onlooker());
fight.fightHappen("张三把李四打倒在地");
复制代码
模式作用
解耦 打架模块 和 报警模块(支付成功后不需要直接调用库存、用户服务的方法)。
新增吃瓜群众时,无需修改打架代码。
六、适配器模式:兼容老插座
// 旧欧洲充电器(已有,圆头)
class EuropeanCharger {
void roundPlug() {
System.out.println("⚡欧洲圆头充电中");
}
}
// 美国插座标准(目标接口,方头)
interface USSocket {
void squarePlug();
}
// 适配器:让欧洲充电器插入美国插座
class ChargerAdapter implements USSocket {
private EuropeanCharger charger;
public ChargerAdapter(EuropeanCharger charger) {
this.charger = charger;
}
@Override
public void squarePlug() {
System.out.print("[适配器转换圆头→方头] ");
charger.roundPlug(); // 实际调用旧接口
}
}
// 使用
EuropeanCharger euroCharger = new EuropeanCharger();
USSocket adapter = new ChargerAdapter(euroCharger);
adapter.squarePlug(); // 输出: [适配器转换圆头→方头] ⚡欧洲圆头充电中
复制代码
模式作用
:让旧插座无需修改即可接入新插座,办理兼容性标题。
七、装饰器模式:咖啡 与 加糖加奶
// 基础咖啡接口
interface Coffee {
double cost();
String desc();
}
// 具体组件:黑咖啡
class BlackCoffee implements Coffee {
public double cost() { return 10.0; }
public String desc() { return "黑咖啡"; }
}
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
}
// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
public double cost() {
return decoratedCoffee.cost() + 2.0; // 加糖多2元
}
public String desc() {
return decoratedCoffee.desc() + "+糖";
}
}
// 具体装饰器:加奶
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public double cost() {
return decoratedCoffee.cost() + 5.0; // 加奶多5元
}
public String desc() {
return decoratedCoffee.desc() + "+奶";
}
}
// 使用
Coffee coffee = new BlackCoffee();
coffee = new SugarDecorator(coffee); // 加糖
coffee = new MilkDecorator(coffee); // 再加奶
System.out.println(coffee.desc() + ",价格:" + coffee.cost());
// 输出:黑咖啡+糖+奶,价格:17.0
复制代码
模式作用
动态增长新功能,无需修改 黑咖啡 原始代码。
八、门面模式:一键影院模式
概念
:封装和和谐同一访问的入口
// 子系统1:电灯
class Light {
void on() { System.out.println("打开电灯"); }
}
// 子系统2:空调
class AirConditioner {
void set25℃() { System.out.println("空调设置25℃"); }
}
// 子系统3:投影仪
class Projector {
void down() { System.out.println("降下投影幕布"); }
}
// 门面:一键启动家庭影院模式
class HomeTheaterFacade {
private Light light = new Light();
private AirConditioner ac = new AirConditioner();
private Projector projector = new Projector();
void movieMode() {
light.on(); // 先开灯避免磕碰
ac.set25℃(); // 设置舒适温度
projector.down(); // 最后降幕布
System.out.println("➤ 影院模式就绪");
}
}
// 使用
HomeTheaterFacade facade = new HomeTheaterFacade();
facade.movieMode();
// 输出:
// 打开电灯
// 空调设置25℃
// 降下投影幕布
// ➤ 影院模式就绪
复制代码
模式作用
调用方只需和 HomeTheaterFacade 交互,无需了解 空调 投影仪 的细节。
九、计谋模式:不如停路边
概念
:算法独立于客户端使用而变革
// 策略接口:停车计费规则
interface ParkingFeeStrategy {
double calculateFee(int hours);
}
// 具体策略1:商场普通计费(首小时5元,后续每小时3元)
class MallStrategy implements ParkingFeeStrategy {
public double calculateFee(int hours) {
return 5 + Math.max(0, hours - 1) * 3;
}
}
// 具体策略2:医院惠民计费(每天上限15元)
class HospitalStrategy implements ParkingFeeStrategy {
public double calculateFee(int hours) {
int days = hours / 24;
int remainder = hours % 24;
return days * 15 + Math.min(remainder * 2, 15); // 每小时2元
}
}
// 上下文:停车计费器
class ParkingFeeCalculator {
private ParkingFeeStrategy strategy;
// 初始化策略
public ParkingFeeCalculator(ParkingFeeStrategy strategy) {
this.strategy = strategy;
}
// 提供改变策略的 setter 方法
public void setStrategy(ParkingFeeStrategy strategy) {
this.strategy = strategy;
}
public void printFee(int hours) {
System.out.println("停车" + hours + "小时,费用:" + strategy.calculateFee(hours) + "元");
}
}
// 使用
ParkingFeeCalculator calculator = new ParkingFeeCalculator(new MallStrategy());
calculator.printFee(5); // 输出:停车5小时,费用:17.0元
calculator.setStrategy(new HospitalStrategy());
calculator.printFee(30); // 输出:停车30小时,费用:15 * 1 + 15=30元
复制代码
模式作用
通过 算法类 ParkingFeeCalculator 指定具体实现计谋,避免 if-else 硬编码
十、模板方法模式:界说订单处理流程
概念
:在父类界说必须算法骨架,允许子类重写特定步骤而不改变团体结构
// 抽象模板类
public abstract class OrderProcessor {
// 模板方法(final防止子类覆盖流程)
public final void processOrder() {
validate();
calculateTotal();
saveToDatabase();
notifyUser();
}
protected abstract void calculateTotal();
protected void validate() {
System.out.println("通用校验:订单ID非空");
}
protected void saveToDatabase() {
System.out.println("保存订单到数据库");
}
protected void notifyUser() {
System.out.println("发送短信通知用户");
}
}
// 具体实现:VIP订单处理
public class VipOrderProcessor extends OrderProcessor {
@Override
protected void calculateTotal() {
System.out.println("VIP订单计算:原价9折");
}
}
// 使用
OrderProcessor processor = new VipOrderProcessor();
processor.processOrder();
复制代码
模式作用
固定订单处理流程(校验 → 盘算 → 生存 → 通知),子类只实现差异部分(如盘算逻辑)。
11. 责任链模式:审批流程
概念
:解耦请求发送者和接收者,使多个对象都有机会处理请求,形成链式处理(不等于链式编程)
// 抽象处理器:请假审批人
abstract class LeaveHandler {
protected LeaveHandler next;
void setNext(LeaveHandler next) { this.next = next; }
abstract void handleRequest(int days);
}
// 具体处理器:组长(处理≤3天)
class GroupLeader extends LeaveHandler {
void handleRequest(int days) {
if (days <= 3) {
System.out.println("组长批准" + days + "天假");
} else if (next != null) {
next.handleRequest(days); // 转交上级
}
}
}
// 具体处理器:经理(处理≤7天)
class Manager extends LeaveHandler {
void handleRequest(int days) {
if (days <= 7) {
System.out.println("经理批准" + days + "天假");
} else if (next != null) {
next.handleRequest(days); // 转交上级
}
}
}
// 具体处理器:总监(处理任何天数)
class Director extends LeaveHandler {
void handleRequest(int days) {
System.out.println("总监特批" + days + "天假");
}
}
// 使用
LeaveHandler leader = new GroupLeader();
LeaveHandler manager = new Manager();
LeaveHandler director = new Director();
leader.setNext(manager); // 组长→经理
manager.setNext(director);// 经理→总监,(递进式处理)
leader.handleRequest(2); // 组长批准2天假
leader.handleRequest(5); // 组长→经理批准5天假
leader.handleRequest(15); // 组长→经理→总监特批15天假
复制代码
模式作用
解耦风控校验步骤,动态调解校验次序或增删校验规则。
总结
一、分类 与 核心
1、创建型模式
核心价值典型场景工厂模式隐藏对象创建细节,实现范例解耦多种支付方式创建单例模式避免重复实例化日志工具…(记载全部)建造者模式分离复杂对象的构建与表现,强制必要参数含可选参数/必选的对象构建
2、结构型模式
核心典型场景代理模式控制访问扩展,符合开闭原则支付权限校验…适配器模式办理接口不兼容标题新旧系统对接(插座转换案例)装饰器模式动态添加功能,避免继续导致的类爆炸咖啡加料…门面模式简化复杂子系统调用,提供同一入口一键影院模式集成多个设备
3、行为型模式
核心典型场景观察者模式解耦事件发布与订阅,实现松耦合通信订单状态变动通知计谋模式算法独立演化,支持运行时切换多场景停车计费计谋责任链模式动态组合处理流程,避免硬编码条件判定多级审批/风控校验链模板方法模式固化流程框架,允许子类定制具体步骤尺度化订单处理流程
二、模式选择
1、对象创建
简单对象创建 →
工厂模式
含复杂构造过程 →
建造者模式
全局唯一实例 →
单例模式
2、结构扩展
接口转换 →
适配器模式
功能动态叠加 →
装饰器模式
简化复杂调用 →
门面模式
访问控制 →
代理模式
3、行为管理
事件驱动 →
观察者模式
算法切换 →
计谋模式
流程审批 →
责任链模式
尺度化流程 →
模板方法模式
建议
识别
:将易变部分抽象为计谋/责任链,例
支付方式、校验规则
鉴戒太过
:简单场景直接new对象,复杂场景再思量引入设计模式
优先组合
:装饰器模式替代多层继续,保持系统弹性
遵循最少知识
:模块间通过接口通信(例订单服务调用库存Service而非直接操作DAO)
end…
假如这篇文章帮到你, 帮忙点个关注呗, 不想那那那点赞或收藏也行鸭 (。•̀ᴗ-)✧ ~
'(இ﹏இ`。)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/)
Powered by Discuz! X3.4