1.概述
本文介绍三种容易混淆的设计模式:策略模式、装饰器模式、代理模式,及其实际code。
至于设计模式有什么用,答案见仁见智啦,不再赘述。
2.这三种模式有什么区别?
答:上G老师给的答案
策略模式、装饰器模式和代理模式是三种常见且容易混淆的设计模式,它们分别有着不同的用途和实现方式:
-
策略模式(Strategy Pattern)
- 定义:策略模式定义了一系列算法,将每一个算法封装起来,并且使它们可以相互替换。策略模式使得算法可以独立于使用它的客户而变化。
- 用途:适合在运行时根据情况选择算法的场景,客户端可以根据需要在不同的算法之间切换。
- 示例:比如一个排序算法,可以使用策略模式来封装不同的排序算法(如快速排序、冒泡排序等),然后在运行时动态选择使用哪种算法。
-
装饰器模式(Decorator Pattern)
- 定义:装饰器模式动态地将责任附加到对象上。若要扩展功能,装饰器提供了比继承更有弹性的替代方案。
- 用途:用于向现有对象添加新功能,而无需修改其结构。通过一系列装饰器的叠加,可以实现对对象功能的逐步扩展。
- 示例:比如在咖啡店点咖啡时,可以通过装饰器模式选择添加不同的配料(如牛奶、糖等),每个装饰器代表一个配料。
-
代理模式(Proxy Pattern)
- 定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。
- 用途:常用于创建一个占位符或者替代品,以控制对实际对象的访问,可以在访问实际对象之前或之后做一些额外处理。
- 示例:比如网络代理服务器充当客户端和真实服务器之间的中介,控制和管理请求和响应。
区别总结
- 策略模式关注的是算法的封装和切换,允许动态地改变对象的行为。
- 装饰器模式关注的是对象功能的增强,通过装饰器可以不断地为对象添加新的功能。
- 代理模式关注的是控制对对象的访问,可以在访问实际对象之前或之后执行额外的操作。
虽然这些模式有时候在实现上有一些相似之处,但它们的关注点和解决的问题是不同的,因此在具体应用时需要根据情况选择合适的模式。
3.实践code
感受一下吧
策略模式(Strategy Pattern)
public class StrategyPatternDemo {
private static final Logger logger = LoggerFactory.getLogger(StrategyPatternDemo.class);
public static void main(String[] args)
{
Context context = new Context(new OperationSinglePrint());
logger.info("---------------------------STEP1------------------------------------");
context.executeStrategy();
logger.info("---------------------------OperationSinglePrint---------------------");
context.setStrategy(new OperatioDoublePrint());
logger.info("---------------------------STEP2------------------------------------");
context.executeStrategy();
logger.info("---------------------------OperatioDoublePrint----------------------");
}
}
public interface Strategy {
public Object doOperation();
}
public class Context {
private static final Logger logger = LoggerFactory.getLogger(Context.class);
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public void setStrategy(Strategy strategy){
this.strategy = strategy;
}
public void executeStrategy(){
if(strategy!=null){
strategy.doOperation();
}else {
logger.info("strategy is null");
}
}
}
public class OperatioDoublePrint implements Strategy {
private static final Logger logger = LoggerFactory.getLogger(OperatioDoublePrint.class);
private Random random = new Random();
@Override
public Integer doOperation() {
Integer i = random.nextInt(100);
logger.info("double print:{},{}",i,i);
return i;
}
}
public class OperationSinglePrint implements Strategy {
private static final Logger logger = LoggerFactory.getLogger(OperationSinglePrint.class);
private Random random = new Random();
@Override
public Integer doOperation() {
Integer i = random.nextInt(100);
logger.info("single print:{}",i);
return i;
}
}
装饰器模式(Decorator Pattern)
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape rectangle = new Rectangle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(new Rectangle());
circle.draw();
rectangle.draw();
redCircle.draw();
redRectangle.draw();
}
}
public interface Shape {
void draw();
}
public class ShapDecorator implements Shape{
protected Shape decoratedShape;
public ShapDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
@Override
public void draw(){
decoratedShape.draw();
}
}
public class RedShapeDecorator extends ShapDecorator{
private static final Logger logger = LoggerFactory.getLogger(RedShapeDecorator.class);
public RedShapeDecorator(Shape decoratedShape)
{
super(decoratedShape);
}
@Override
public void draw()
{
decoratedShape.draw();
logger.info("setRedBorder start");
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape)
{
decoratedShape.draw();
logger.info("RedShapeDecorator setRedBorder:RED");
}
}
public class Circle implements Shape {
private static final Logger logger = LoggerFactory.getLogger(Circle.class);
@Override
public void draw() {
logger.info("Circle draw");
}
}
public class Rectangle implements Shape {
private static final Logger logger = LoggerFactory.getLogger(Rectangle.class);
@Override
public void draw()
{
logger.info("Rectangle draw");
}
}
代理模式(Proxy Pattern)
public class ProxyPatternDemo {
public static void main(String[] args) {
Image proxyImage = new ProxyImage("image_1.jpg");
Image proxyImage2 = new ProxyImage("image_2.jpg");
proxyImage.display();// 图像1首次加载并显示
proxyImage.display();// 图像1再次显示,但无需重新加载
proxyImage2.display(); // 图像2首次加载并显示
proxyImage2.display(); // 图像2再次显示,但无需重新加载
}
}
public interface Image {
public void display();
}
public class ProxyImage implements Image {
private static final Logger logger = LoggerFactory.getLogger(ProxyImage.class);
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
logger.info("ProxyImage:{}", fileName);
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
logger.info("ProxyImage--------------首次初始化");
}
realImage.display();
logger.info("ProxyImage--------------再次display");
}
}
public class RealImage implements Image {
private static final Logger logger = LoggerFactory.getLogger(RealImage.class);
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
logger.info("RealImage:{}",fileName);
load(fileName);
}
@Override
public void display() {
logger.info("RealImage--------------display:{}",fileName);
}
public void load(String fileName) {
logger.info("RealImage--------------load:{}",fileName);
}
}