观察者模式是开发中比较常见的一种模式、例如队列的应用。那么不通过引入队列、怎么在项目中使用观察者模式呢?本文将用生产中的一个需求简单讲解。
需求与分析:用户下单之后记录日志并赠送优惠券、短信提醒。那我们可能的代码实现如下:
package com.leqidi.observer;
/**
* 购物简单处理流程
* @author fjx
*
*/
public class TicketSeller {
/**执行下单业务*/
public void sell(){
System.out.println("sell");
log();
coupon();
sms();
}
/**执行日志业务*/
public void log(){
System.out.println("log");
}
/**执行优惠券业务*/
public void coupon(){
System.out.println("coupon");
}
/**执行短信业务*/
public void sms(){
System.out.println("sms");
}
public static void main(String[] args) {
TicketSeller ts = new TicketSeller();
ts.sell();
}
}
好、我们已经开发完成、但这样代码耦合性太强、其实已经给后面版本迭代、需求变更加个了坑了。假设我们又要添加下单后对接第三方系统的需求、那只能继续在这上面的代码继续修改、这违背了软件开发的“开闭原则“。
--------------------------------------------------------------------------------我是分割线
好、引入设计者模式、那我们的代码可以怎么写呢?
先定义一个"主题”、也就是被监听着、熟悉队列的朋友应该很清楚这个概念
package com.leqidi.observer.design;
/**
*
* @author fjx
*
*/
public interface Subject {
/**
* 注册观察者
* @param notification 观察者
*/
public void addRegister(Notification notification);
/**
* 通知观察者
*/
public void call();
}
再给个主题的实现类
package com.leqidi.observer.design.impl;
import java.util.LinkedList;
import java.util.List;
import com.leqidi.observer.design.Notification;
import com.leqidi.observer.design.Subject;
/**
*
* @author fjx
*
*/
public class SubjectImpl implements Subject {
List<Notification> notifications = new LinkedList<>();
public void addRegister(Notification notification) {
// TODO Auto-generated method stub
notifications.add(notification);
}
public void call(){
for(Notification notification : notifications){
notification.doNotify();
}
}
}
再来个“观察者“、观察我们上面定义的”主题"
package com.leqidi.observer.design;
/**
*
* @author fjx
*
*/
public interface Notification {
/**
* 监听
*/
public void doNotify();
}
分别有对应的具体观察者实例
package com.leqidi.observer.design.impl;
import com.leqidi.observer.design.Notification;
/**
*
* @author fjx
*
*/
public class CouponNotification implements Notification {
public void doNotify() {
// TODO Auto-generated method stub
System.out.println("coupon");
}
}
package com.leqidi.observer.design.impl;
import com.leqidi.observer.design.Notification;
/**
*
* @author fjx
*
*/
public class SmsNotification implements Notification {
public void doNotify() {
// TODO Auto-generated method stub
System.out.println("sms");
}
}
架构完成、最后测试client
package com.leqidi.observer.design;
import com.leqidi.observer.design.impl.CouponNotification;
import com.leqidi.observer.design.impl.LogNotification;
import com.leqidi.observer.design.impl.SmsNotification;
import com.leqidi.observer.design.impl.SubjectImpl;
public class Client {
public void sell(){
/**执行下单业务*/
System.out.println("sell");
}
public static void main(String[] args) {
/**基础关系构建、项目中通过spring*/
Subject subject = new SubjectImpl();
Notification cn = new CouponNotification();
Notification ln = new LogNotification();
Notification sn = new SmsNotification();
subject.addRegister(sn);
subject.addRegister(ln);
subject.addRegister(cn);
/***/
Client client = new Client();
client.sell();
subject.call();
}
}
显然、我们的代码变丰(fu)富(za)起来很多。但是对于后续的需求变更、我们可以做到开闭原则了、大有以不变应万变的风格。
代码这种东西、前人种树、后人乘凉。
本文个人愚见!