代理模式和策略模式都属于设计模式,它们都是解决软件设计中一些特定问题的通用解决方案。虽然它们有一定的相似之处,但它们的关注点和目的不同。下面我们来分别了解一下这两种设计模式的差别。
- 代理模式 (Proxy Pattern): 代理模式涉及到一个代理类(Proxy)和一个实际目标对象(Real Subject)。代理类通常具有与目标对象相同的接口,代理类的主要作用是在访问实际目标对象之前或之后添加一些额外功能,例如缓存、权限控制、日志记录等。代理模式分为几种类型,如静态代理、动态代理和远程代理等。
代理模式的关注点是如何在不改变实际目标对象的基础上添加额外功能,这有助于实现关注点的分离。
2.策略模式 (Strategy Pattern): 策略模式涉及到一个上下文类(Context),一个策略接口(Strategy)以及实现策略接口的一组具体策略类(Concrete Strategies)。策略模式的主要目的是将一组相关算法封装到一系列策略类中,使它们可以互相替换,并让客户端代码可以根据需要选择合适的策略。策略模式有助于将算法的定义和使用分离,提高代码的可扩展性和可维护性。
策略模式的关注点是如何在运行时根据需求动态地选择合适的算法或行为。
总结一下,代理模式关注的是如何在访问实际目标对象时添加额外功能,而策略模式关注的是如何在运行时动态地选择合适的算法或行为。代理模式主要解决的问题是关注点的分离,而策略模式主要解决的问题是算法和行为的可替换性和扩展性。
接下来我将使用代码示例来详细解释代理模式和策略模式的差别。
- 代理模式:
我们以日志记录为例,展示代理模式。假设我们有一个接口UserService
,它有一个方法getUser
用于获取用户信息。
public interface UserService {
User getUser(String id);
}
实现类UserServiceImpl:
public class UserServiceImpl implements UserService {
@Override
public User getUser(String id) {
// 获取用户信息
return new User(id, "Tom");
}
}
现在我们想要为getUser
方法添加日志记录功能,但又不想修改原始的UserServiceImpl
。这时我们可以使用代理模式:
代理类UserServiceProxy
:
public class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public User getUser(String id) {
System.out.println("Logging: Getting user with id: " + id);
User user = userService.getUser(id);
System.out.println("Logging: Got user: " + user);
return user;
}
}
客户端使用代理类:
public class Client {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = new UserServiceProxy(userService);
User user = proxy.getUser("1");
}
}
2.策略模式
我们以排序为例,展示策略模式。假设我们有一个接口SortingStrategy
,它有一个方法sort
用于对整数列表进行排序。
public interface SortingStrategy {
void sort(List<Integer> list);
}
现在我们实现两种不同的排序策略:冒泡排序和快速排序。
冒泡排序:
public class BubbleSortStrategy implements SortingStrategy {
@Override
public void sort(List<Integer> list) {
// 冒泡排序算法实现
}
}
快速排序:
public class QuickSortStrategy implements SortingStrategy {
@Override
public void sort(List<Integer> list) {
// 快速排序算法实现
}
}
我们创建一个上下文类SortContext
,允许客户端根据需要选择合适的策略。
public class SortContext {
private SortingStrategy sortingStrategy;
public void setSortingStrategy(SortingStrategy sortingStrategy) {
this.sortingStrategy = sortingStrategy;
}
public void sort(List<Integer> list) {
sortingStrategy.sort(list);
}
}
客户端可以根据需要选择排序策略:
public class Client {
public static void main(String[] args) {
SortContext context = new SortContext();
// 使用冒泡排序
context.setSortingStrategy(new BubbleSortStrategy());
context.sort(new ArrayList<>(Arrays.asList(4, 2, 3, 1)));
// 使用快速排序
context.setSortingStrategy(new QuickSortStrategy());
context.sort(new ArrayList<>(Arrays.asList(4, 2, 3, 1)));
}
}
总结:从代码示例可以看出,代理模式和策略模式的关键差别在于它们的目的和应用场景。
代理模式主要用于为一个对象提供一个替代对象,以控制对原始对象的访问。在代理模式中,代理对象可以在调用原始对象的方法前后添加自己的逻辑,如日志记录、权限检查等。代理模式的关键在于代理对象与原始对象实现相同的接口,但客户端不直接访问原始对象,而是访问代理对象。
策略模式主要用于在一组算法中选择一个合适的算法来解决特定问题。策略模式可以让算法独立于使用它的客户端,这样可以方便地替换和扩展算法,而不影响客户端的实现。策略模式的关键在于将算法实现与使用算法的客户端解耦,客户端通过上下文类选择合适的策略来完成特定任务。
代理模式的核心是替代和控制对原始对象的访问,而策略模式的核心是选择合适的算法或策略来解决问题。