用观察者模式解决点击一次文章 update一次数据库的问题

本文介绍了一种利用观察者模式减少数据库访问频率的方法,通过缓存点击计数并在达到阈值时批量更新数据库,有效提升了系统性能。

接上文http://xuliangyong.iteye.com/blog/171240

对于第二种方法现用观察着模式来解决

思路是这样:当点击a文章(id=1234)够10次后 ,通知文章管理器更新点击次数

update article set hit_count = hit_count+10 where id = 1234

这样就减少了访问数据库的次数

代码如下:

Java代码
  1. publicclassHitCachedextendsObservable{
  2. privatestaticfinalintDEFAULT_MAX_HITS=10;
  3. privateMap<Long,Integer>hits=Collections.synchronizedMap(newHashMap<Long,Integer>());
  4. /**
  5. *最大点击量。超过该值就更新数据库
  6. */
  7. privateintmaxHits=DEFAULT_MAX_HITS;
  8. publicHitCached(){}
  9. publicHitCached(intmaxHits){
  10. this.maxHits=maxHits;
  11. }
  12. publicvoidput(Longkey,Integervalue){
  13. hits.put(key,value);
  14. }
  15. /**
  16. *为指定key增加指定的点击量
  17. *@paramhitIncreased增加的点数
  18. */
  19. publicvoidaddHit(Longkey,IntegerhitIncreased){
  20. if(!hits.containsKey(key))
  21. hits.put(key,0);
  22. Integervalue=hits.get(key);
  23. if(value+hitIncreased>=maxHits){
  24. setChanged();
  25. notifyObservers(KeyValuePair.create(key,value+hitIncreased));
  26. hits.remove(key);
  27. }else{
  28. hits.put(key,value+hitIncreased);
  29. }
  30. }
  31. publicIntegerget(Longkey){
  32. returnhits.get(key);
  33. }
  34. publicvoidclear(){
  35. hits.clear();
  36. }
  37. }
Java代码
  1. publicclassArticleManagerImplextendsHibernateGenericDao<Article,Long>implementsArticleManager,Oberver{
  2. publicvoidupdate(Observableo,Objectarg){
  3. KeyValuePairkeyValue=(KeyValuePair)arg;
  4. Articlearticle=this.get(keyValue.getKey());
  5. article.setHitCount(article.getHitCount()+keyValue.getValue());
  6. save(article);
  7. }

action中调用

Java代码
  1. privatestaticHitCachedhitCached=newHitCached(5);
  2. publicStringview(){
  3. if(id!=null){
  4. entity=articleManager.get(id);
  5. hitCached.addObserver(articleManager);
  6. hitCached.addHit(id,1);
  7. }
  8. }

这样没十次查看才update一次数据库 更新一次缓存 性能得到了大的提升

存在的问题:

停止服务会丢失一些数据 可加一个监听器 来处理

<think>嗯,用户想了解Java中常见的设计模式,特别是单例模式、观察者模式和工厂模式。我需要先回顾一下这些模式的定义和用途,然后整理出清晰的解释和示例代码。 首先,单例模式确保一个类只有一个实例,并提供全局访问点。记得饿汉式和懒汉式的区别,饿汉式在类加载时就创建实例,线程安全;而懒汉式延迟加载,但需要同步处理。用户提供的引用中有几个代码示例,比如引用[2]中的饿汉式实现和引用[3]中的懒汉式示例。需要确认这些代码的正确性,并解释它们的特点。 接下来是工厂模式,它负责对象的创建,将实例化过程封装起来。工厂模式分为简单工厂、工厂方法和抽象工厂。用户的问题中提到工厂模式,可能需要先介绍简单工厂,再说明其他变体。引用[3]提到了工厂模式的基本概念,但需要具体的代码示例。例如,可以创建一个形状工厂,根据输入参数返回不同的形状对象。需要确保示例代码简洁,并说明如何通过工厂类解耦客户端和具体类。 然后是观察者模式,用于对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者都会收到通知。引用中并没有给出具体的观察者模式示例,所以需要自己构造。比如,定义一个主题接口和观察者接口,然后实现具体的主题和观察者类。需要展示如何注册观察者、更新状态和通知观察者的过程。 在整理过程中,要注意引用用户提供的参考文献,例如在单例模式部分引用[1]、[2]、[3]、[4]和[5]。同时,按照用户的要求,所有行内公式用$...$,独立公式用$$...$$,但当前问题可能不需要数学公式,但需要确保LaTeX语法正确,如果有变量或代码中的数学符号的话。 用户要求生成相关问题,可能需要包括设计模式的其他类型、如何选择合适的设计模式、各模式的优缺点比较等。例如,可以问“如何选择单例模式的饿汉式和懒汉式?”或者“观察者模式有哪些实际应用场景?” 还需要检查回答的结构是否清晰,分点解释每个模式,并附上代码示例。确保代码格式正确,使用中文回答,并自然添加引用标识。最后,验证所有引用是否准确对应到提供的参考文献,例如引用[1]提到单例模式的不同实现方式,引用[3]有工厂模式的解释,引用[5]则概述设计模式的基本概念。</think>### Java常见设计模式解析与示例 #### 一、单例模式(Singleton Pattern) **定义**:确保一个类仅有一个实例,并提供全局访问点[^1][^5]。 **适用场景**:日志记录器、配置管理、线程池等需要唯一实例的场景。 ##### 实现方式: 1. **饿汉式** 类加载时立即创建实例,线程安全但可能占用资源。 ```java public class EagerSingleton { private static final EagerSingleton instance = new EagerSingleton(); private EagerSingleton() {} // 私有构造函数 public static EagerSingleton getInstance() { return instance; } } ``` 引用示例:[^2] 2. **懒汉式(线程安全)** 延迟加载,通过`synchronized`保证线程安全,但可能影响性能。 ```java public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } } ``` 引用示例:[^3] --- #### 二、工厂模式(Factory Pattern) **定义**:将对象创建逻辑封装在工厂类中,解耦调用方与具体实现类。 **适用场景**:需要灵活扩展对象类型时,如数据库连接、UI组件生成。 ##### 简单工厂示例: ```java // 接口定义 interface Shape { void draw(); } // 具体实现类 class Circle implements Shape { public void draw() { System.out.println("绘制圆形"); } } class Rectangle implements Shape { public void draw() { System.out.println("绘制矩形"); } } // 工厂类 class ShapeFactory { public Shape createShape(String type) { if ("Circle".equals(type)) return new Circle(); else if ("Rectangle".equals(type)) return new Rectangle(); throw new IllegalArgumentException("未知类型"); } } // 使用 public class Client { public static void main(String[] args) { ShapeFactory factory = new ShapeFactory(); Shape circle = factory.createShape("Circle"); circle.draw(); // 输出:绘制圆形 } } ``` 引用示例:[^3][^4] --- #### 三、观察者模式(Observer Pattern) **定义**:定义对象间的一对多依赖关系,当主题对象状态变化时,自动通知所有观察者[^1]。 **适用场景**:事件驱动系统、消息订阅、GUI事件监听。 ##### 示例代码: ```java // 主题接口 interface Subject { void registerObserver(Observer o); void notifyObservers(String message); } // 具体主题类 class NewsPublisher implements Subject { private List<Observer> observers = new ArrayList<>(); public void registerObserver(Observer o) { observers.add(o); } public void notifyObservers(String message) { for (Observer o : observers) { o.update(message); } } } // 观察者接口 interface Observer { void update(String message); } // 具体观察者类 class Subscriber implements Observer { private String name; public Subscriber(String name) { this.name = name; } public void update(String message) { System.out.println(name + " 收到消息:" + message); } } // 使用 public class Client { public static void main(String[] args) { NewsPublisher publisher = new NewsPublisher(); publisher.registerObserver(new Subscriber("用户A")); publisher.registerObserver(new Subscriber("用户B")); publisher.notifyObservers("新文章发布!"); } } ``` 输出: ``` 用户A 收到消息:新文章发布! 用户B 收到消息:新文章发布! ``` 引用示例:[^1] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值