工作中运用到设计模式的开发场景

本文深入探讨了装饰器模式、枚举策略结合简单工厂模式以及享元模式的实际应用,通过具体案例展示了如何在高并发和分布式环境下优化代码结构和提高运行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试的时候,别人问起我工作这么多年了,有没有自己的一些沉淀和积累。其实高并发、分布式都是很响亮的,然而我却要讲讲用到的设计模式,也是一些细节。

  • 装饰器(包装器)模式:
public class ResponseMapWrapper {

	private static Logger logger = LoggerFactory.getLogger(ResponseMapWrapper.class);
	private static final String STATUS = "status";
	private static final String STATUS_TEXT = "statusText";
	private static final String DATA = "data";
	
	public static Map<String, Object> build(InfoCode infoCode, Object data) {

		Map<String, Object> map = new HashMap<>();
		
		map.put(STATUS, infoCode.getStatus());
		map.put(STATUS_TEXT, infoCode.getMsg());
		if (data != null) {
			map.put(DATA, data);
		}

		logger.info(JSON.toJSONString(map));
		return map;
	}

	public static Map<String, Object> build(ResponseCode responseCode) {

		Map<String, Object> map = new HashMap<>();
		
		map.put(STATUS, responseCode.getCode());
		map.put(STATUS_TEXT, responseCode.getReasonPhrase());

		logger.info(JSON.toJSONString(map));
		return map;
	}
}

InfoCode是enum类型,比如PARAMS_ERROR(40000, "参数错误"),这样在Controller里就能按照统一的格式返回,return ResponseMapWrapper.build(InfoCode.SUCCESS, vo);

  • 枚举策略 + 简单工厂模式:

最典型的就是微信公众号开发中的event/msg了。从解析xml到对接具体的业务,event包括关注取消关注、扫码、点击菜单等,而msg包括了文本、图片、语音等等,种类繁多,所以很适合枚举策略。

接口:

public interface IEventStrategy {

  public String dealEvent(Element root);

}

实现:

public enum EventStrategy implements IEventStrategy {

  // 关注事件 || 扫描带参数二维码, 用户未关注时,进行关注后的事件推送
  subscribe {
    @Override
    public String dealEvent(Element root) {
      return SubscribeStrategy.dealEvent(root);
    }
  },

  // 取消关注事件
  unsubscribe {
    @Override
    public String dealEvent(Element root) {
      return UnSubscribeStrategy.dealEvent(root);
    }
  },

  // 自定义菜单 —— 点击菜单拉取消息时的事件
  CLICK {
    @Override
    public String dealEvent(Element root) {
      return ClickStrategy.dealEvent(root);
    }
  },

  // 自定义菜单 —— 点击菜单跳转链接时的事件
  VIEW {
    @Override
    public String dealEvent(Element root) {
      return ViewStrategy.dealEvent(root);
    }
  },

  // 模版消息发送任务完成后的事件
  TEMPLATESENDJOBFINISH {
    @Override
    public String dealEvent(Element root) {
      return TemplateSendStrategy.dealEvent(root);
    }
  }
}

具体的策略,以关注为例:

public class SubscribeStrategy {
  private static final Logger logger = LoggerFactory.getLogger(SubscribeStrategy.class);

  /*
   * ToUserName 开发者微信号 FromUserName 发送方帐号(一个OpenID) CreateTime 消息创建时间 (整型) MsgType 消息类型,event Event
   * 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
   */
  public static String dealEvent(Element root) {

    WxUserService wxUserService = (WxUserService) SpringContextUtils.getBeanById("wxUserService");

    NodeList toUserName = root.getElementsByTagName("ToUserName");
    NodeList fromUserName = root.getElementsByTagName("FromUserName");
    NodeList createTime = root.getElementsByTagName("CreateTime");

    String developerId = toUserName.item(0).getTextContent();
    String openId = fromUserName.item(0).getTextContent();
    String _createTime = createTime.item(0).getTextContent();
    NodeList eventKey = root.getElementsByTagName("EventKey");
    String _eventKey = "";
    if (eventKey != null) {
      _eventKey = eventKey.item(0).getTextContent();
    }

    logger.info("SubscribeStrategy toUserName: {}; fromUserName: {}; createTime: {}; eventKey: {}",
        developerId, openId, _createTime, _eventKey);

    UserInfo userInfo = wxUserService.getUserInfo(openId);

    // 以unionId为Key
    String unionid = userInfo.getUnionid();
    RedisUtils redisUtils = (RedisUtils) SpringContextUtils.getBeanByClass(RedisUtils.class);

    if (unionid == null) {
      logger.warn("weclome get unionid failed,  userOpenId : {}", openId);
    } else {
      // 存储用户信息
      redisUtils.setStrNX(openId, unionid);
      userInfo.setSubscribe(1);
      redisUtils.setPOJO(unionid, userInfo);
    }

    // 以下与具体业务对接
    @TODO
}

对外调用是通过简单工厂提供的方法:

public class EventStrategyFactory {

  public static IEventStrategy getDealer(String event) {

    // 按事件发生概率由高到低排序
    switch (event) {

    // 自定义菜单 —— 点击菜单拉取消息时的事件
      case "CLICK":
        return EventStrategy.CLICK;

        // 自定义菜单 —— 点击菜单跳转链接时的事件
      case "VIEW":
        return EventStrategy.VIEW;

        // 关注事件 || 扫描带参数二维码, 用户未关注时,进行关注后的事件推送
      case "subscribe":
        return EventStrategy.subscribe;

        // 模版消息发送任务完成后的事件
      case "TEMPLATESENDJOBFINISH":
        return EventStrategy.TEMPLATESENDJOBFINISH;

        // 取消关注事件
      case "unsubscribe":
        return EventStrategy.unsubscribe;

      default:
        return null;
    }
  }
}

入口,xml节点是event时,不关心具体的event名称,EventStrategyFactory.getDealer(_event)从工厂拿到策略,然后启用该策略。

if ("event".equals(_msgType)) {
        NodeList event = root.getElementsByTagName("Event");
        String _event = event.item(0).getTextContent();
        IEventStrategy eventStrategy = EventStrategyFactory.getDealer(_event);
        if(eventStrategy != null){
          replyMsg = eventStrategy.dealEvent(root);
        }
        
      }
  • 享元模式:

复用map,不要每次都new一个map,这样创建的开销很大,而且还会垃圾回收。具体等我找一下代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值