Java设计模式——策略模式 vs 工厂模式:解锁软件设计 “超能力”,码农必备!
一、策略模式(Strategy Pattern):算法的灵活切换
(一)策略模式的核心概念
想象你正坐镇“代码指挥中心”,面对瞬息万变的战场形势(运行时复杂状况),需要随时切换作战“策略”(算法),同时保证“指挥系统”(客户端代码)稳如泰山。这时,策略模式(Strategy Pattern) 便如同天降奇兵。
作为行为型设计模式(Behavioral Pattern)的代表,策略模式将各类算法封装进独立的“策略类”中,藏于代码宝库,按需调用。无论战况如何变化,只需更换“策略锦囊”即可应对,严格遵守“开闭原则”(Open-Closed Principle),扩展轻松,修改无忧。
策略模式的结构如下表所示:
| 组件 | 描述 | 示例 | 图示示意 |
|---|---|---|---|
| 抽象策略类 | 定义通用策略行为接口,是具体策略类遵循的“模板”,规定核心方法。 | PromotionStrategy 接口,定义 applyPromotion 方法。 | [长方形框代表抽象策略类,内部标注方法名] |
| 具体策略类 | 实现抽象策略类,承载独特算法逻辑,各显神通。 | FullReductionStrategy(满减)、DiscountStrategy(折扣)。 | [多个小长方形框代表具体策略类,指向抽象策略类,标注各自算法] |
| 上下文类 | 持有策略类引用,按场景调用方法,像“指挥官”调配策略。 | ShoppingCart,依据总价调用策略计算最终价格。 | [圆形框代表上下文类,箭头指向抽象策略类,体现关联] |
(二)生活实例:披萨店的“创意大厨”
走进一家个性化披萨店,点一份培根披萨。老板不提供成品,而是给你食材和制作指南,让你自由发挥。多放芝士、精准控火、妙调佐料,这些“操作”即为“策略”。你(客户端)依据口味挑选策略制作披萨,正如策略模式中,客户端根据实际情况灵活调用策略类,以达到个性化目的。
(三)代码实战:电商促销场景
在竞争白热化的电商“战场”,促销策略是核心武器。以下使用 Java 代码构建一个“促销策略库”,展示策略模式的应用。
// 抽象策略接口,定义促销通用规则
interface PromotionStrategy {
double applyPromotion(double totalPrice);
}
// 具体策略:满减策略,达门槛即减钱
class FullReductionStrategy implements PromotionStrategy {
private double fullAmount;
private double reductionAmount;
public FullReductionStrategy(double fullAmount, double reductionAmount) {
this.fullAmount = fullAmount;
this.reductionAmount = reductionAmount;
}
@Override
public double applyPromotion(double totalPrice) {
if (totalPrice >= fullAmount) {
return totalPrice - reductionAmount;
} else {
return totalPrice;
}
}
}
// 具体策略:折扣策略,按折扣率计算
class DiscountStrategy implements PromotionStrategy {
private double discountRate;
public DiscountStrategy(double discountRate) {
this.discountRate = discountRate;
}
@Override
public double applyPromotion(double totalPrice) {
return totalPrice * discountRate;
}
}
// 上下文类,持有策略引用并调度
class ShoppingCart {
private PromotionStrategy promotionStrategy;
private double totalPrice;
public ShoppingCart(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void addItem(double price) {
totalPrice += price;
}
public double calculateFinalPrice() {
return promotionStrategy.applyPromotion(totalPrice);
}
}
// 测试代码,验证策略威力
public class StrategyPatternDemo {
public static void main(String[] args) {
// 场景一:满减策略,满 200 减 50
PromotionStrategy fullReduction = new FullReductionStrategy(200, 50);
ShoppingCart cart1 = new ShoppingCart(fullReduction);
cart1.addItem(100);
cart1.addItem(100);
System.out.println("满减策略下最终价格:" + cart1.calculateFinalPrice());
// 场景二:折扣策略,打 8 折
PromotionStrategy discount = new DiscountStrategy(0.8);
ShoppingCart cart2 = new ShoppingCart(discount);
cart2.addItem(150);
cart2.addItem(50);
System.out.println("折扣策略下最终价格:" + cart2.calculateFinalPrice());
}
}在此架构中,PromotionStrategy 接口如同“魔法法典”,规范促销规则;FullReductionStrategy 和 DiscountStrategy 像“魔法师”执行具体优惠计算;ShoppingCart 则是“指挥官”,依据策略计算花费。若需更换策略,仅需修改传入对象,主代码无需变动。
(四)策略模式的优势
- 扩展性强:若电商想增加“积分抵现金”策略,只需编写一个实现接口的新类,现有代码结构稳固。
- 切换灵活:支持运行时动态切换策略。无论是购物节还是新品首发,客户端代码均可从容应对业务变化。
二、工厂模式(Factory Pattern):对象的创建工坊
(一)工厂模式的核心概念
在软件设计的另一角,工厂模式(Factory Pattern) 扎根于创建型设计模式(Creational Pattern)。它像一座“神奇工坊”:你(客户端)递交“订单”(创建对象请求),“工匠”(工厂类)按“秘方”(预设逻辑)制造“珍宝”(对象),隐藏复杂过程。客户端只需直接使用对象,无需关心创建细节,从而显著提升易用性与可维护性。
工厂模式的结构如下表所示:
| 组件 | 描述 | 示例 | 图示示意 |
|---|---|---|---|
| 抽象产品类 | 定义产品通用行为属性,作具体产品“模板”。 | Shape 接口,draw 方法定义绘制规范。 | [长方形框代表抽象产品类,内部写方法] |
| 具体产品类 | 实现抽象产品类,具实际功能特性。 | Circle(圆)、Rectangle(矩形)。 | [多个小框代表具体产品类,指向抽象产品类] |
| 抽象工厂类 | 定义创建产品的抽象方法,把控流程“大方向”。 | ShapeFactory 接口,createShape 方法定规则。 | [大圆形框代表抽象工厂类,写方法] |
| 具体工厂类 | 实现抽象工厂类,按逻辑造具体产品。 | CircleFactory、RectangleFactory。 | [小圆形框代表具体工厂类,指向抽象工厂与对应产品] |
(二)生活对照:传统披萨店的“高效出餐”
在传统披萨店点一份培根披萨,坐下等待即可。后厨如同“披萨工厂”,师傅依流程配料、烘焙,很快美味上桌。你(客户端)不管制作过程,只享美味。这就是工厂模式的日常体现。
(三)代码落地:图形绘制场景
在图形绘制软件中,利用工厂模式管理图形创建,代码如下:
// 抽象产品接口,定义图形绘制规范
interface Shape {
void draw();
}
// 具体产品:圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 具体产品:矩形
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 抽象工厂接口,定义生产规矩
interface ShapeFactory {
Shape createShape();
}
// 具体工厂:圆形工厂
class CircleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}
// 具体工厂:矩形工厂
class RectangleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new Rectangle();
}
}
// 测试代码,验证工厂产出
public class FactoryPatternDemo {
public static void main(String[] args) {
// 生产圆形
ShapeFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw();
// 生产矩形
ShapeFactory rectangleFactory = new RectangleFactory();
Shape rectangle = rectangleFactory.createShape();
rectangle.draw();
}
}在此“艺术工坊”中,Shape 接口如“绘画宝典”,Circle 和 Rectangle 展现独特画风,ShapeFactory 控制流程。客户端通过工厂获取图形,无需关心细节,实现彻底解耦。若需增加“三角形”,只需按套路扩展代码,现有逻辑不受影响。
(四)工厂模式的优势
- 创建与使用分离:客户端在前台使用对象,工厂在后台创建。后台修改创建逻辑(“装修”),前台无需变动,系统稳定性高。
- 创建逻辑统一:创建规则、资源调配集中在工厂类中,优化参数或逻辑时只需内部微调,管理清晰高效。
三、终极对决:策略模式 vs 工厂模式
为了更清晰地区分二者,以下从多个维度进行对比:
| 对比维度 | 策略模式(Strategy Pattern) | 工厂模式(Factory Pattern) |
|---|---|---|
| 设计初衷 | 聚焦算法的灵活切换与封装,应对业务规则多变,让系统低成本适应变化。 | 着眼对象创建的便利性,隔离复杂创建过程,提升系统易用性与可维护性。 |
| 角色职责 | 策略类实现算法,上下文类调度策略。策略类精研算法,上下文类负责调配。 | 工厂类把控创建,产品类展示功能。工厂类负责生产,产品类待发挥功能。 |
| 应用场景 | 算法频繁切换处,如金融产品利息计算(活期、定期等切换)、支付渠道选择。 | 对象创建复杂需管理处,如游戏角色创建(不同种族、职业)、数据库连接获取。 |
总结
看完这场“巅峰对决”,相信大家对策略模式和工厂模式已有了清晰的认识。在实际项目中,切勿“乱点鸳鸯谱”,应根据实际需求按需“配对”:
- 若需动态切换算法,请选择策略模式。
- 若需屏蔽创建细节,请选择工厂模式。
合理运用设计模式,能让代码“战斗力”飙升,助你成为优秀的软件架构师。
说明:本文基于标准 Java SE 环境编写,设计模式为核心软件工程理论,适用于大多数面向对象编程语言及版本。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。