前言
策略模式和工厂模式的主要区别在于它们的目的、结构、适用场景以及客户端与模式的关系。
一、目的和结构
策略模式是一种行为型设计模式,旨在定义一系列算法,并将每个算法封装起来,使它们可以互换。策略模式的主要目的是让一组相关的算法可以相互替换,避免了使用条件语句来选择算法,从而使代码更加清晰和可维护。它包含一个策略接口(或抽象类)和多个实现该接口的具体策略类。客户端持有对策略接口的引用,可以在运行时选择或切换策略。
工厂模式是一种创建型设计模式,提供了一种创建对象的接口,而不是直接实例化对象。工厂模式的主要目的是解耦对象的创建过程,使得客户端无需关注对象的具体实现细节。它包含一个工厂接口或抽象类和一个或多个具体工厂类。客户端通过调用工厂方法来获取对象,而不是直接使用new关键字。
二、适用场景
策略模式适用于需要在不同情况下使用不同算法或操作的场景,例如支付系统中不同支付方式的选择、图形处理软件中不同滤镜效果的应用等。它避免了使用大量的条件语句,使得算法的变化独立于使用它们的客户端。
工厂模式适用于对象创建逻辑复杂或需要通过某些特定条件控制对象创建的情况,例如不同数据库的连接对象创建、不同日志记录器的实例化等。工厂模式将对象的创建和使用分离,提高了系统的可扩展性和灵活性。
三、客户端与模式的关系
在策略模式中,客户端通过持有策略接口的引用来选择或切换策略,无需知道具体策略的实现细节。这种设计使得策略的变化不会影响到使用策略的客户端。
在工厂模式中,客户端通过调用工厂方法来获取对象,无需直接使用new关键字来创建对象。这种设计解耦了对象的创建过程,使得客户端无需关心对象的具体实现细节。
综上所述,策略模式和工厂模式虽然都是设计模式,但它们的目的、结构和适用场景有所不同。策略模式关注行为的封装和替换,而工厂模式关注对象的创建和解耦。根据具体的需求和场景选择合适的设计模式可以提高代码的可维护性、灵活性和可扩展性。
四、设计模式实战------策略模式
在策略模式中,我们有一个上下文对象,该对象包含一个指向策略对象的引用。策略对象实现了一个公共接口,该接口定义了所有策略对象都必须实现的方法。上下文对象在运行时可以将策略对象替换为另一个策略对象,从而改变其行为。
4.1 以下是策略模式的一些关键要素:
-
上下文(Context):包含一个指向策略对象的引用。
-
策略(Strategy):定义了所有策略对象都必须实现的方法。
-
具体策略(Concrete Strategy):实现了策略接口的具体算法。
4.2 策略模式类图 :
4.3 下面是一个简单的示例,说明如何使用策略模式:
定义一个策略接口
java
//定义一个策略接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
具体策略(加法)
java
// 加法
public class MathOperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
具体策略(减法)
java
//减法
public class MathOperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
具体策略(乘法)
java
//乘法
public class MathOperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
定义上下文
java
// 上下文类
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
策略模式测试代码
java
//使用策略模式
public class TestStrategyDemo {
public static void main(String[] args) {
Context context = new Context(new MathOperationAdd());
System.out.println("5 + 3 = " + context.executeStrategy(5, 3));
context = new Context(new MathOperationSubtract());
System.out.println("5 - 3 = " + context.executeStrategy(5, 3));
context = new Context(new MathOperationMultiply());
System.out.println("5 * 3 = " + context.executeStrategy(5, 3));
}
}
在上面的示例中,我们定义了一个策略接口 Strategy
,并实现了三个具体策略类 MathOperationAdd
、MathOperationSubtract
和 MathOperationMultiply
。我们还定义了一个上下文类 Context
,它包含一个指向策略对象的引用,并提供了一个执行策略的方法 executeStrategy
。在测试代码中,我们创建了一个上下文对象,并使用不同的策略对象来执行不同的算法。
4.4 使用策略模式的优点:
- 算法的独立性:每个具体策略类都封装了一个独立的算法,这使得算法可以独立于客户端代码进行修改和扩展。
- 避免条件语句:策略模式有助于消除大量的条件语句,提高了代码的可读性和可维护性。
- 运行时动态选择策略:客户端可以在运行时选择合适的策略,从而实现动态的行为变化。
- 代码重用:策略模式可以促使重用算法实现,不需要重复编写相似的代码。
4.5 策略模式的使用场景:
- 排序算法:Java的Comparator接口允许你实现不同的比较策略,以便在不同的排序需求下切换策略。你可以使用策略模式来定义自定义的比较器。
- 集合排序:在Java中,诸如Collections.sort这样的排序方法接受Comparator作为参数,这是一个典型的策略模式示例。
- 数据库连接池:在连接池中,你可以使用策略模式来管理数据库连接的获取和释放策略,以满足不同的并发需求。
- 加密算法:在加密和安全领域,策略模式用于实现不同的加密和解密策略,如AES、RSA、DES等。
- 邮件通知系统:在电子邮件通知系统中,策略模式可以用于选择不同的邮件发送策略,如SMTP、API、本地邮件服务器等。
- 电商促销:电子商务平台可以使用策略模式来实现不同的促销策略,如折扣、满减、买一送一等。
- 缓存策略:在缓存系统中,策略模式可用于定义不同的缓存淘汰策略,如LRU、LFU、FIFO等。