设计模式:Java装饰模式与实际业务场景应用

装饰模式简介

  • 装饰模式(Decorator Pattern)是一种结构型设计模式,它让你能够向对象动态地添加新功能。这种模式特别适用于你想要扩展一个类的功能,或者给某个对象添加附加职责的时候,而且这一切都在不改变其他对象的情况下完成。装饰模式经常作为替代继承机制的选择,因为它提供了比继承更大的灵活性。

业务场景

  1. 动态地给对象添加职责:如果需要在运行时决定是否给对象添加额外的行为,那么装饰模式非常适合这种情况。比如,根据用户的权限级别动态地赋予系统中的用户不同的访问权限。
  2. 需要灵活地组合对象的行为:装饰模式允许你通过组合不同的装饰器来给对象添加多种行为。这使得你可以根据需要构造出各种各样的行为组合。
  3. 当不能使用子类时:有时候可能不允许修改现有的类(例如第三方库),或者修改类的成本很高,这时可以通过装饰模式来达到类似的效果。

模板代码

取自《大话设计模式》,基于java实现的装饰模式demo.

abstract class Component {
    public abstract void operation();
}

public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("具体对象的实际操作");
    }
}

//具体装饰类A
public class ConcreteDecoratorA extends Decorator {
    private String addedState;

    @Override
    public void operation() {
        super.operation();
        this.addedState = "具体装饰对象A独有状态";
        System.out.println(this.addedState);
    }

}
//具体装饰类B
public class ConcreteDecoratorB extends Decorator {

    private void addedState() {
        System.out.println("具体装饰对象B独有方法");
    }

    @Override
    public void operation() {
        super.operation();
        this.addedState();
    }

}

public class Decorator extends Component {
    protected Component component;

    //装饰一个component
    public void setComponent(Component component) {
        this.component = component;
    }
    //重写operation,实际调用component的op方法
    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

//主启动类,客户端
public class App {
    public static void main(String[] args) {
        ConcreteComponent c=new ConcreteComponent();
        ConcreteDecoratorA a=new ConcreteDecoratorA();
        ConcreteDecoratorB b=new ConcreteDecoratorB();
        //a用来装饰c
        a.setComponent(c);
        //b装饰a
        b.setComponent(a);
        //执行b的operation,发现三者operation全部执行
        b.operation();
    }
}

业务场景应用

  • 业务场景为系统与其他模块建立连接,通信协议有很多种。在这种情况下,系统需要对目标模块发送报文,报文段一般由多种部分组成,每个通信协议也不一样。

  • 因此在系统中,通常实际的功能由报文段的Data部分承担,这也是报文段的有效载荷,即应用程序的实际数据。而报文的其他内容,如报文头、报文长度、报文尾等需要根据不同协议去动态生成。此时可以通过装饰模式,设计出不同的handler,对不同协议的报文添加不同的内容。

以下为基于该业务场景设计的demo代码

//messageHandler,定义了所有报文段处理类的规范,具有handle方法,处理报文段
public interface MessageHandler {
    String handle(String msg);
}
//所有具体concreteHandler的父类,具有装饰方法和handle方法
public class BaseHandler implements MessageHandler {
    MessageHandler messageHandler;

    //装饰对象
    public void decorate(MessageHandler messageHandler) {
        this.messageHandler = messageHandler;
    }

    @Override
    public String handle(String msg) {
    //调用具体messageHandler的handle方法
        if (messageHandler != null) {
            return messageHandler.handle(msg);
        }
        return msg;
    }
}

以下为concreteHandler的实现

//该handler用于统计报文长度(不包含报文头和报文尾)
public class MsgLengthHandler extends BaseHandler {
    @Override
    public String handle(String msg) {
        msg = "Context Length:" + msg.length() + "::" + msg;
        return super.handle(msg);
    }
}
//该handler用于添加tcp报文头,可根据需要添加不同报文头的handler
public class TcpHeadHandler extends BaseHandler {
    @Override
    public String handle(String msg) {
        msg = "Tcp Head::" + msg;
        return super.handle(msg);
    }
}
//该handler用于添加tcp报文尾
public class TcpTailHandler extends BaseHandler {
    @Override
    public String handle(String msg) {
        msg = msg + "::Tcp Tail";
        return super.handle(msg);
    }
}

最后是客户端方法,此处需要注意装饰顺序,否则会出现报文长度计算错误的情况.

public class App {
    public static MessageHandler handler;

    public static void main(String[] args) {
        String msg = "this is a message context";

        MsgLengthHandler msgLengthHandler = new MsgLengthHandler();
        TcpHeadHandler tcpHeadHandler = new TcpHeadHandler();
        TcpTailHandler tcpTailHandler = new TcpTailHandler();
        //先计算报文长度,再加报文头,最后加报文尾
        tcpHeadHandler.decorate(tcpTailHandler);
        msgLengthHandler.decorate(tcpHeadHandler);
        handler = msgLengthHandler;
        msg = handler.handle(msg);
        System.out.println(msg);
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值