当前位置: 首页 > news >正文

深圳市住房与建设局实名制网站小程序制作二维码签到

深圳市住房与建设局实名制网站,小程序制作二维码签到,滁州seo网站推广方案,网站建设吴江前言 哈喽#xff0c;大家好。平时我们写代码呢#xff0c;多数情况都是流水线式写代码#xff0c;基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢#xff0c;我觉得#xff0c;最好的方式就是#xff1a;使用设计模式优化自己的业务代码。今天跟大家聊聊日常工作中…前言 哈喽大家好。平时我们写代码呢多数情况都是流水线式写代码基本就可以实现业务逻辑了。如何在写代码中找到乐趣呢我觉得最好的方式就是使用设计模式优化自己的业务代码。今天跟大家聊聊日常工作中我都使用过哪些设计模式。工作中常用到哪些设计模式1.策略模式 1.1 业务场景假设有这样的业务场景大数据系统把文件推送过来根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码if(typeA){//按照A格式解析}else if(typeB){//按B格式解析 }else{//按照默认格式解析 }这个代码可能会存在哪些问题呢如果分支变多这里的代码就会变得臃肿难以维护可读性低。如果你需要接入一种新的解析类型那只能在原有代码上修改。说得专业一点的话就是以上代码违背了面向对象编程的开闭原则以及单一原则。开闭原则对于扩展是开放的但是对于修改是封闭的增加或者删除某个逻辑都需要修改到原来代码单一原则规定一个类应该只有一个发生变化的原因修改任何类型的分支逻辑代码都需要改动当前类的代码。如果你的代码就是酱紫有多个if...else等条件分支并且每个条件分支可以封装起来替换的我们就可以使用策略模式来优化。1.2 策略模式定义策略模式定义了算法族分别封装起来让它们之间可以相互替换此模式让算法的变化独立于使用算法的的客户。这个策略模式的定义是不是有点抽象呢那我们来看点通俗易懂的比喻假设你跟不同性格类型的小姐姐约会要用不同的策略有的请电影比较好有的则去吃小吃效果不错有的去逛街买买买最合适。当然目的都是为了得到小姐姐的芳心请看电影、吃小吃、逛街就是不同的策略。策略模式针对一组算法将每一个算法封装到具有共同接口的独立的类中从而使得它们可以相互替换。1.3 策略模式使用策略模式怎么使用呢酱紫实现的一个接口或者抽象类里面两个方法一个方法匹配类型一个可替换的逻辑实现方法不同策略的差异化实现(就是说不同策略的实现类)使用策略模式1.3.1 一个接口两个方法public interface IFileStrategy {//属于哪种文件解析类型FileTypeResolveEnum gainFileType();//封装的公用算法具体的解析方法void resolve(Object objectparam); }1.3.2 不同策略的差异化实现A 类型策略具体实现Component public class AFileResolve implements IFileStrategy {Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_A_RESOLVE;}Overridepublic void resolve(Object objectparam) {logger.info(A 类型解析文件参数{},objectparam);//A类型解析具体逻辑} }B 类型策略具体实现Component public class BFileResolve implements IFileStrategy {Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_B_RESOLVE;}Overridepublic void resolve(Object objectparam) {logger.info(B 类型解析文件参数{},objectparam);//B类型解析具体逻辑} }默认类型策略具体实现Component public class DefaultFileResolve implements IFileStrategy {Overridepublic FileTypeResolveEnum gainFileType() {return FileTypeResolveEnum.File_DEFAULT_RESOLVE;}Overridepublic void resolve(Object objectparam) {logger.info(默认类型解析文件参数{},objectparam);//默认类型解析具体逻辑} }1.3.3 使用策略模式如何使用呢我们借助spring的生命周期使用ApplicationContextAware接口把对用的策略初始化到map里面。然后对外提供resolveFile方法即可。/***  author 公众号捡田螺的小男孩*/ Component public class StrategyUseService implements ApplicationContextAware{private MapFileTypeResolveEnum, IFileStrategy iFileStrategyMap  new ConcurrentHashMap();public void resolveFile(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam) {IFileStrategy iFileStrategy  iFileStrategyMap.get(fileTypeResolveEnum);if (iFileStrategy ! null) {iFileStrategy.resolve(objectParam);}}//把不同策略放到mapOverridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {MapString, IFileStrategy tmepMap  applicationContext.getBeansOfType(IFileStrategy.class);tmepMap.values().forEach(strategyService - iFileStrategyMap.put(strategyService.gainFileType(), strategyService));} }2. 责任链模式 2.1 业务场景我们来看一个常见的业务场景下订单。下订单接口基本的逻辑一般有参数非空校验、安全校验、黑名单校验、规则拦截等等。很多伙伴会使用异常来实现public class Order {public void checkNullParam(Object param){//参数非空校验throw new RuntimeException();}public void checkSecurity(){//安全校验throw new RuntimeException();}public void checkBackList(){//黑名单校验throw new RuntimeException();}public void checkRule(){//规则拦截throw new RuntimeException();}public static void main(String[] args) {Order order new Order();try{order.checkNullParam();order.checkSecurity ();order.checkBackList();order2.checkRule();System.out.println(order success);}catch (RuntimeException e){System.out.println(order fail);}} }这段代码使用了异常来做逻辑条件判断如果后续逻辑越来越复杂的话会出现一些问题如异常只能返回异常信息不能返回更多的字段这时候需要自定义异常类。并且阿里开发手册规定禁止用异常做逻辑判断。【强制】 异常不要用来做流程控制条件控制。说明异常设计的初衷是解决程序运行中的各种意外情况且异常的处理效率比条件判断方式要低很多。如何优化这段代码呢可以考虑责任链模式2.2 责任链模式定义当你想要让一个以上的对象有机会能够处理某个请求的时候就使用责任链模式。责任链模式为请求创建了一个接收者对象的链。执行链上有多个对象节点每个对象节点都有机会条件匹配处理请求事务如果某个对象节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。这种模式给予请求的类型对请求的发送者和接收者进行解耦。责任链模式实际上是一种处理请求的模式它让多个处理器对象节点都有机会处理该请求直到其中某个处理成功为止。责任链模式把多个处理器串成链然后让请求在链上传递责任链模式打个比喻假设你晚上去上选修课为了可以走点走坐到了最后一排。来到教室发现前面坐了好几个漂亮的小姐姐于是你找张纸条写上“你好, 可以做我的女朋友吗如果不愿意请向前传”。纸条就一个接一个的传上去了后来传到第一排的那个妹子手上她把纸条交给老师听说老师40多岁未婚...2.3 责任链模式使用责任链模式怎么使用呢一个接口或者抽象类每个对象差异化处理对象链数组初始化连起来2.3.1 一个接口或者抽象类这个接口或者抽象类需要有一个指向责任下一个对象的属性一个设置下一个对象的set方法给子类对象差异化实现的方法如以下代码的doFilter方法/***  关注公众号捡田螺的小男孩*/ public abstract class AbstractHandler {//责任链中的下一个对象private AbstractHandler nextHandler;/*** 责任链的下一个对象*/public void setNextHandler(AbstractHandler nextHandler){this.nextHandler  nextHandler;}/*** 具体参数拦截逻辑,给子类去实现*/public void filter(Request request, Response response) {doFilter(request, response);if (getNextHandler() ! null) {getNextHandler().filter(request, response);}}public AbstractHandler getNextHandler() {return nextHandler;}abstract void doFilter(Request filterRequest, Response response);}2.3.2 每个对象差异化处理责任链上每个对象的差异化处理如本小节的业务场景就有参数校验对象、安全校验对象、黑名单校验对象、规则拦截对象/*** 参数校验对象**/ Component Order(1) //顺序排第1最先校验 public class CheckParamFilterObject extends AbstractHandler {Overridepublic void doFilter(Request request, Response response) {System.out.println(非空参数检查);} }/***  安全校验对象*/ Component Order(2) //校验顺序排第2 public class CheckSecurityFilterObject extends AbstractHandler {Overridepublic void doFilter(Request request, Response response) {//invoke Security checkSystem.out.println(安全调用校验);} } /***  黑名单校验对象*/ Component Order(3) //校验顺序排第3 public class CheckBlackFilterObject extends AbstractHandler {Overridepublic void doFilter(Request request, Response response) {//invoke black list checkSystem.out.println(校验黑名单);} }/***  规则拦截对象*/ Component Order(4) //校验顺序排第4 public class CheckRuleFilterObject extends AbstractHandler {Overridepublic void doFilter(Request request, Response response) {//check ruleSystem.out.println(check rule);} }2.3.3 对象链连起来初始化 使用Component(ChainPatternDemo) public class ChainPatternDemo {//自动注入各个责任链的对象Autowiredprivate ListAbstractHandler abstractHandleList;private AbstractHandler abstractHandler;//spring注入后自动执行责任链的对象连接起来PostConstructpublic void initializeChainFilter(){for(int i  0;iabstractHandleList.size();i){if(i  0){abstractHandler  abstractHandleList.get(0);}else{AbstractHandler currentHander  abstractHandleList.get(i - 1);AbstractHandler nextHander  abstractHandleList.get(i);currentHander.setNextHandler(nextHander);}}}//直接调用这个方法使用public Response exec(Request request, Response response) {abstractHandler.filter(request, response);return response;}public AbstractHandler getAbstractHandler() {return abstractHandler;}public void setAbstractHandler(AbstractHandler abstractHandler) {this.abstractHandler  abstractHandler;} }运行结果如下非空参数检查 安全调用校验 校验黑名单 check rule3. 模板方法模式 3.1 业务场景假设我们有这么一个业务场景内部系统不同商户调用我们系统接口去跟外部第三方系统交互http方式。走类似这么一个流程如下一个请求都会经历这几个流程查询商户信息对请求报文加签发送http请求出去对返回的报文验签这里有的商户可能是走代理出去的有的是走直连。假设当前有AB商户接入不少伙伴可能这么实现伪代码如下// 商户A处理句柄 CompanyAHandler implements RequestHandler {Resp hander(req){//查询商户信息queryMerchantInfo();//加签signature();//http请求A商户假设走的是代理httpRequestbyProxy()//验签verify();} } // 商户B处理句柄 CompanyBHandler implements RequestHandler {Resp hander(Rreq){//查询商户信息queryMerchantInfo();//加签signature();// http请求B商户不走代理直连httpRequestbyDirect();// 验签verify(); } }假设新加一个C商户接入你需要再实现一套这样的代码。显然这样代码就重复了一些通用的方法却在每一个子类都重新写了这一方法。如何优化呢可以使用模板方法模式。3.2 模板方法模式定义定义一个操作中的算法的骨架流程而将一些步骤延迟到子类中使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。它的核心思想就是定义一个操作的一系列步骤对于某些暂时确定不下来的步骤就留给子类去实现这样不同的子类就可以定义出不同的步骤。打个通俗的比喻模式举例追女朋友要先“牵手”再“拥抱”再“接吻” 再“拍拍..额..手”。至于具体你用左手还是右手牵无所谓但是整个过程定了一个流程模板按照模板来就行。3.3 模板方法使用一个抽象类定义骨架流程抽象方法放一起确定的共同方法步骤放到抽象类去除抽象方法标记不确定的步骤给子类去差异化实现我们继续那以上的举例的业务流程例子来一起用 模板方法优化一下哈3.3.1 一个抽象类定义骨架流程因为一个个请求经过的流程为一下步骤查询商户信息对请求报文加签发送http请求出去对返回的报文验签所以我们就可以定义一个抽象类包含请求流程的几个方法方法首先都定义为抽象方法哈/*** 抽象类定义骨架流程查询商户信息加签http请求验签*/ abstract class AbstractMerchantService  { //查询商户信息abstract queryMerchantInfo();//加签abstract signature();//http 请求abstract httpRequest();// 验签abstract verifySinature();}3.3.2 确定的共同方法步骤放到抽象类abstract class AbstractMerchantService  { //模板方法流程Resp handlerTempPlate(req){//查询商户信息queryMerchantInfo();//加签signature();//http 请求httpRequest();// 验签verifySinature();}// Http是否走代理提供给子类实现abstract boolean isRequestByProxy(); }3.3.3 不确定的步骤给子类去差异化实现因为是否走代理流程是不确定的所以给子类去实现。商户A的请求实现CompanyAServiceImpl extends AbstractMerchantService{Resp hander(req){return handlerTempPlate(req);}//走http代理的boolean isRequestByProxy(){return true;}商户B的请求实现CompanyBServiceImpl extends AbstractMerchantService{Resp hander(req){return handlerTempPlate(req);}//公司B是不走代理的boolean isRequestByProxy(){return false;}4. 观察者模式 4.1 业务场景登陆注册应该是最常见的业务场景了。就拿注册来说事我们经常会遇到类似的场景就是用户注册成功后我们给用户发一条消息又或者发个邮件等等因此经常有如下的代码void register(User user){insertRegisterUseruser;sendIMMessage();sendEmail() }这块代码会有什么问题呢如果产品又加需求现在注册成功的用户再给用户发一条短信通知。于是你又得改register方法的代码了。。。这是不是违反了开闭原则啦。void register(User user){insertRegisterUseruser;sendIMMessage();sendMobileMessage;sendEmail() }并且如果调发短信的接口失败了是不是又影响到用户注册了这时候是不是得加个异步方法给通知消息才好。。。实际上我们可以使用观察者模式优化。4.2 观察者模式定义观察者模式定义对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都得到通知并被完成业务的更新。观察者模式属于行为模式一个对象被观察者的状态发生改变所有的依赖对象观察者对象都将得到通知进行广播通知。它的主要成员就是观察者和被观察者。被观察者Observerable目标对象状态发生变化时将通知所有的观察者。观察者observer接受被观察者的状态变化通知执行预先定义的业务。使用场景 完成某件事情后异步通知场景。如登陆成功发个IM消息等等。4.3 观察者模式使用观察者模式实现的话还是比较简单的。一个被观察者的类Observerable ;多个观察者Observer 观察者的差异化实现经典观察者模式封装EventBus实战4.3.1 一个被观察者的类Observerable 和 多个观察者Observerpublic class Observerable {private ListObserver observers  new ArrayListObserver();private int state;public int getState() {return state;}public void setState(int state) {notifyAllObservers();}//添加观察者public void addServer(Observer observer){observers.add(observer);      }//移除观察者public void removeServer(Observer observer){observers.remove(observer);      }//通知public void notifyAllObservers(int state){if(state!1){System.out.println(“不是通知的状态”);return ;}for (Observer observer : observers) {observer.doEvent();}}   }4.3.2 观察者的差异化实现//观察者interface Observer {  void doEvent();   }   //Im消息 IMMessageObserver implements Observer{void doEvent{System.out.println(发送IM消息);} }//手机短信 MobileNoObserver implements Observer{void doEvent{System.out.println(发送短信消息);} } //EmailNo EmailObserver implements Observer{void doEvent{System.out.println(发送email消息);} }4.3.3 EventBus实战自己搞一套观察者模式的代码还是有点小麻烦。实际上Guava EventBus就封装好了它 提供一套基于注解的事件总线api可以灵活的使用爽歪歪。我们来看下EventBus的实战代码哈首先可以声明一个EventBusCenter类它类似于以上被观察者那种角色Observerable。public class EventBusCenter {private static EventBus eventBus  new EventBus();private EventBusCenter() {}public static EventBus getInstance() {return eventBus;}//添加观察者public static void register(Object obj) {eventBus.register(obj);}//移除观察者public static void unregister(Object obj) {eventBus.unregister(obj);}//把消息推给观察者public static void post(Object obj) {eventBus.post(obj);} }然后再声明观察者EventListenerpublic class EventListener {Subscribe //加了订阅这里标记这个方法是事件处理方法  public void handle(NotifyEvent notifyEvent) {System.out.println(发送IM消息  notifyEvent.getImNo());System.out.println(发送短信消息  notifyEvent.getMobileNo());System.out.println(发送Email消息  notifyEvent.getEmailNo());} }//通知事件类 public class NotifyEvent  {private String mobileNo;private String emailNo;private String imNo;public NotifyEvent(String mobileNo, String emailNo, String imNo) {this.mobileNo  mobileNo;this.emailNo  emailNo;this.imNo  imNo;}}使用demo测试public class EventBusDemoTest {public static void main(String[] args) {EventListener eventListener  new EventListener();EventBusCenter.register(eventListener);EventBusCenter.post(new NotifyEvent(13372817283, 123qq.com, 666));} }运行结果发送IM消息666 发送短信消息13372817283 发送Email消息123qq.com5. 工厂模式 5.1 业务场景工厂模式一般配合策略模式一起使用。用来去优化大量的if...else...或switch...case...条件语句。我们就取第一小节中策略模式那个例子吧。根据不同的文件解析类型创建不同的解析对象IFileStrategy getFileStrategy(FileTypeResolveEnum fileType){IFileStrategy  fileStrategy ;if(fileTypeFileTypeResolveEnum.File_A_RESOLVE){fileStrategy  new AFileResolve();}else if(fileTypeFileTypeResolveEnum.File_A_RESOLV){fileStrategy  new BFileResolve();}else{fileStrategy  new DefaultFileResolve();}return fileStrategy;}其实这就是工厂模式定义一个创建对象的接口让其子类自己决定实例化哪一个工厂类工厂模式使其创建过程延迟到子类进行。策略模式的例子没有使用上一段代码而是借助spring的特性搞了一个工厂模式哈哈小伙伴们可以回去那个例子细品一下我把代码再搬下来小伙伴们再品一下吧/***  author 公众号捡田螺的小男孩*/ Component public class StrategyUseService implements ApplicationContextAware{private MapFileTypeResolveEnum, IFileStrategy iFileStrategyMap  new ConcurrentHashMap();//把所有的文件类型解析的对象放到map需要使用时信手拈来即可。这就是工厂模式的一种体现啦Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {MapString, IFileStrategy tmepMap  applicationContext.getBeansOfType(IFileStrategy.class);tmepMap.values().forEach(strategyService - iFileStrategyMap.put(strategyService.gainFileType(), strategyService));} }5.2 使用工厂模式定义工厂模式也是比较简单的:一个工厂接口提供一个创建不同对象的方法。其子类实现工厂接口构造不同对象使用工厂模式5.3.1 一个工厂接口interface IFileResolveFactory{void resolve(); }5.3.2 不同子类实现工厂接口class AFileResolve implements IFileResolveFactory{void resolve(){System.out.println(文件A类型解析);} }class BFileResolve implements IFileResolveFactory{void resolve(){System.out.println(文件B类型解析);} }class DefaultFileResolve implements IFileResolveFactory{void resolve(){System.out.println(默认文件类型解析);} }5.3.3 使用工厂模式//构造不同的工厂对象 IFileResolveFactory fileResolveFactory; if(fileType“A”){fileResolveFactory  new AFileResolve(); }else if(fileType“B”){fileResolveFactory  new BFileResolve();}else{fileResolveFactory  new DefaultFileResolve(); }fileResolveFactory.resolve();一般情况下对于工厂模式你不会看到以上的代码。工厂模式会跟配合其他设计模式如策略模式一起出现的。6. 单例模式 6.1 业务场景单例模式保证一个类仅有一个实例并提供一个访问它的全局访问点。I/O与数据库的连接,一般就用单例模式实现de的。Windows里面的Task Manager任务管理器也是很典型的单例模式。来看一个单例模式的例子public class LanHanSingleton {private static LanHanSingleton instance;private LanHanSingleton(){}public static LanHanSingleton getInstance(){if (instance  null) {instance  new LanHanSingleton();}return instance;}}以上的例子就是懒汉式的单例实现。实例在需要用到的时候才去创建就比较懒。如果有则返回没有则新建需要加下 synchronized关键字要不然可能存在线性安全问题。6.2 单例模式的经典写法其实单例模式还有有好几种实现方式如饿汉模式双重校验锁静态内部类枚举等实现方式。6.2.1 饿汉模式public class EHanSingleton {private static EHanSingleton instance  new EHanSingleton();private EHanSingleton(){      }public static EHanSingleton getInstance() {return instance;}}饿汉模式它比较饥饿、比较勤奋实例在初始化的时候就已经建好了不管你后面有没有用到都先新建好实例再说。这个就没有线程安全的问题但是呢浪费内存空间呀。6.2.2 双重校验锁public class DoubleCheckSingleton {private volatile static DoubleCheckSingleton instance;private DoubleCheckSingleton() { }public static DoubleCheckSingleton getInstance(){if (instance  null) {synchronized (DoubleCheckSingleton.class) {if (instance  null) {instance  new DoubleCheckSingleton();}}}return instance;} }双重校验锁实现的单例模式综合了懒汉式和饿汉式两者的优缺点。以上代码例子中在synchronized关键字内外都加了一层  if条件判断这样既保证了线程安全又比直接上锁提高了执行效率还节省了内存空间。6.2.3 静态内部类public class InnerClassSingleton {private static class InnerClassSingletonHolder{private static final InnerClassSingleton INSTANCE  new InnerClassSingleton();}private InnerClassSingleton(){}public static final InnerClassSingleton getInstance(){return InnerClassSingletonHolder.INSTANCE;} }静态内部类的实现方式效果有点类似双重校验锁。但这种方式只适用于静态域场景双重校验锁方式可在实例域需要延迟初始化时使用。6.2.4 枚举public enum SingletonEnum {INSTANCE;public SingletonEnum getInstance(){return INSTANCE;} }枚举实现的单例代码简洁清晰。并且它还自动支持序列化机制绝对防止多次实例化。-- end--求点赞、在看、分享三连
http://www.huolong8.cn/news/184035/

相关文章:

  • 培训网站模板韦博在上面做课件的网站叫什么
  • 台州cms建站系统建筑工程公司有哪些岗位
  • 网站手机端怎么制作教程微信小程序怎么盈利
  • 湘潭网站设计公司装潢设计专业可以考二建吗
  • 昆明建设局网站号码网站登录后不显示内容
  • 那种网站打不开经典网页设计欣赏
  • 上海长宁区网站建设wordpress 添加链接
  • 彬县网站wordpress邮箱插件
  • 建设网站系统wordpress求助
  • 宁夏网站建设怎么样静态网站开发课程模板
  • 国外的网站建设wordpress投稿系统
  • 大理高端网站建设友点cms
  • 网站开发询价方案业之峰装饰公司简介
  • 深圳成交型网站建设石景山网站建设有哪些公司
  • 秦皇岛网站制作小程序开发开发平台 英文
  • 北京网站建设搜q.479185700定制营销型网站公司
  • 雁塔免费做网站验证码平台 wordpress
  • 保定网站制作软件网站改版怎样做301
  • 什么网站做顶置便宜温州网站制作网站
  • 怎么下载网站备案号网站开发网页前置开发
  • 怎么用eclipse做网站开发郑州网站建设乛汉狮网络
  • 网站建设 jz.woonl网站速度
  • 学校教育网站模板dede 网站目录
  • 做网站可以用什么数据库网站前端与后台必须同时做吗
  • 泸州百拓网站建设河北网站开发网站
  • 小程序建设吉林关键词优化的方法
  • 网站建设怎么找客源?免费推广网站入口
  • 网站源码怎么上传有没有做高仿手表的网站
  • 做游戏音频下载网站济南网站建设公司电子商务网站
  • 深圳定制家具厂佛山网站优化推广方案