设计模式-观察者模式(Observer Pattern)

设计模式-观察者模式(Observer Pattern)-ALOOGY WORLD (aloogychendl23.asia)

观察者模式的应用

观察者模式(Observer Pattern)是一种行为型设计模式,用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时,其相关依赖对象会自动收到通知并进行相应处理。

一、概念

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

二、观察者模式适用场景

  1. 当一个对象的改变需要同时通知其他对象,并且你不知道有多少对象需要被通知时,可以使用观察者模式。它将这种一对多的依赖关系进行了解耦,使得主题对象和观察者对象之间松耦合。

  2. 当一个对象的改变需要触发其他对象的特定行为时,可以使用观察者模式。观察者可以根据主题对象的状态变化来执行相应的操作,实现了对象之间的交互和协作。

  3. 当应用中的某个对象需要与多个其他对象进行交互,但又希望避免紧密耦合时,可以使用观察者模式。观察者模式使得主题对象和观察者对象之间只依赖于抽象接口,减少了对象间的直接依赖,提高了系统的灵活性和可扩展性。

三、优点

  1. 解耦合:将主题与具体观察者解耦,使得它们可以独立地变化和复用。

  2. 扩展性:易于添加新的观察者以及定义新的事件类型。

  3. 实时性:实现了实时更新机制,当主题状态改变时能够即刻通知相关观察者

四、缺点

  1. 过度使用可能导致性能问题和复杂度增加。

  2. 触发链问题:如果观察者之间有依赖关系,那么通知链可能会导致不可预料的结果。

五、观察者模式的构成

  • Subject(主题):也称为被观察者或可观察者,它维护了一组观察者,并提供了用于添加、删除和通知观察者的方法。当其状态发生变化时,会通知所有观察者。

  • Observer(观察者):也称为订阅者或监听者,它定义了一个更新接口,用于接收主题的通知。当观察者接收到通知时,可以执行相应的操作。

  • 主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。

  • 观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。

  • 具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。

  • 具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。

六、观察者模式的实现方式

  • 定义观察者接口:包含一个更新方法。

  • 创建具体观察者:实现观察者接口,定义接收到通知时的行为。

  • 定义主题接口:包含添加、删除和通知观察者的方法。

  • 创建具体主题:实现主题接口,管理观察者列表,并在状态改变时通知它们。

七、应用实例(源码分享)

1.演示示例

  • 创建 Subject 类

 //Subject.java
 import java.util.ArrayList;
 import java.util.List;
  
 public class Subject {
    
    private List<Observer> observers 
       = new ArrayList<Observer>();
    private int state;
  
    public int getState() {
       return state;
    }
  
    public void setState(int state) {
       this.state = state;
       notifyAllObservers();
    }
  
    public void attach(Observer observer){
       observers.add(observer);      
    }
  
    public void notifyAllObservers(){
       for (Observer observer : observers) {
          observer.update();
       }
    }  
 }
  • 创建 Observer 类

 //Observer.java
 public abstract class Observer {
    protected Subject subject;
    public abstract void update();
 }
  • 创建实体观察者类

 //BinaryObserver.java
 public class BinaryObserver extends Observer{
  
    public BinaryObserver(Subject subject){
       this.subject = subject;
       this.subject.attach(this);
    }
  
    @Override
    public void update() {
       System.out.println( "Binary String: " 
       + Integer.toBinaryString( subject.getState() ) ); 
    }
 }
 //OctalObserver.java
 public class OctalObserver extends Observer{
  
    public OctalObserver(Subject subject){
       this.subject = subject;
       this.subject.attach(this);
    }
  
    @Override
    public void update() {
      System.out.println( "Octal String: " 
      + Integer.toOctalString( subject.getState() ) ); 
    }
 }
 //HexaObserver.java
 public class HexaObserver extends Observer{
  
    public HexaObserver(Subject subject){
       this.subject = subject;
       this.subject.attach(this);
    }
  
    @Override
    public void update() {
       System.out.println( "Hex String: " 
       + Integer.toHexString( subject.getState() ).toUpperCase() ); 
    }
 }
  • 使用 Subject 和实体观察者对象

 //ObserverPatternDemo.java
 public class ObserverPatternDemo {
    public static void main(String[] args) {
       Subject subject = new Subject();
  
       new HexaObserver(subject);
       new OctalObserver(subject);
       new BinaryObserver(subject);
  
       System.out.println("First state change: 15");   
       subject.setState(15);
       System.out.println("Second state change: 10");  
       subject.setState(10);
    }
 }
  • 执行程序,输出结果:

     First state change: 15
     Hex String: F
     Octal String: 17
     Binary String: 1111
     Second state change: 10
     Hex String: A
     Octal String: 12
     Binary String: 1010

2.具体实例

用观察者模式实现: 网上商店中如果商品(product)在名称(name)、价格(price)、产地(address)等方面有变化,系统能自动把变化了的信息通知会员,这将是网上商店区别传统商店的一大特色。画出类关系图(UML图)并编程实现。

  • 定义具体目标类

 // ConcreteProduct.java
 public class ConcreteProduct extends Product {
     private String name;
     private double price;
     private String address;
 ​
     public ConcreteProduct(String name, double price, String address) {
         super(name);
         this.name = name;
         this.price = price;
         this.address = address;
     }
 ​
     @Override
     public void setName(String name) {
         this.name = name;
         notifyObservers("Name changed to: " + name);
     }
 ​
     @Override
     public void setPrice(double price) {
         this.price = price;
         notifyObservers("Price changed to: $" + price);
     }
 ​
     @Override
     public void setAddress(String address) {
         this.address = address;
         notifyObservers("Address changed to: " + address);
     }
 ​
     // 获取产品名称
     public String getName() {
         return name;
     }
 ​
     // 获取产品价格
     public double getPrice() {
         return price;
     }
 ​
     // 获取产品地址
     public String getAddress() {
         return address;
     }
 }
  • 定义具体观察者类

 // Member.java
 public class Member implements Observer {
     private String name;
 ​
     public Member(String name) {
         this.name = name;
     }
 ​
     @Override
     public void update(String productName, String message) {
         System.out.printf("Member: %-10s | Product: %-15s | Update: %s%n", name, productName, message);
     }
 ​
     // 获取会员名称
     public String getName() {
         return name;
     }
 }
  • 观察者接口

 public interface Observer {
     void update(String productName, String message);
 }
  • 定义目标接口

 import java.util.ArrayList;
 import java.util.List;
 ​
 public abstract class Product {
  private List<Observer> observers = new ArrayList<>();
  private String productName;
 ​
  public Product(String productName) {
      this.productName = productName;
  }
 ​
  // 添加观察者
  public void addObserver(Observer observer) {
      observers.add(observer);
      System.out.printf("Observer added: %s for Product: %s%n", ((Member) observer).getName(), productName);
  }
 ​
  // 移除观察者
  public void removeObserver(Observer observer) {
      observers.remove(observer);
      System.out.printf("Observer removed: %s for Product: %s%n", ((Member) observer).getName(), productName);
  }
 ​
  // 通知所有观察者
  protected void notifyObservers(String message) {
      for (Observer observer : observers) {
          observer.update(productName, message);
      }
  }
 ​
  // 抽象方法,供具体产品实现
  public abstract void setName(String name);
  public abstract void setPrice(double price);
  public abstract void setAddress(String address);
 }
  • 创建具体产品和会员,并模拟产品信息的变化。(具体观察者)

 // ObserverPatternTest.java
 public class ObserverPatternTest {
     public static void main(String[] args) {
         // 创建具体产品
         ConcreteProduct laptop = new ConcreteProduct("Laptop", 1500.00, "China");
         ConcreteProduct camera = new ConcreteProduct("Camera", 500.00, "Japan");
 ​
         // 创建具体观察者(会员)
         Member alice = new Member("Aloogy");
         Member bob = new Member("Yumi");
 ​
         // 注册观察者
         laptop.addObserver(alice);
         laptop.addObserver(bob);
         camera.addObserver(alice);
 ​
         // 模拟产品信息变化
         System.out.println("\nChanging Laptop details:");
         laptop.setName("Gaming Laptop");
         laptop.setPrice(2000.00);
 ​
         System.out.println("\nChanging Camera details:");
         camera.setAddress("South Korea");
         camera.setPrice(600.00);
 ​
         // 移除观察者并再次更改信息
         laptop.removeObserver(bob);
         System.out.println("\nChanging Laptop details after removing an observer:");
         laptop.setName("Ultra Gaming Laptop");
         laptop.setPrice(2500.00);
     }
 }
  • 输出结果:

    7a7cfa790e404ecfa67a209b3bcd16b9.png

  • UML

cdea9da9c1584a61b52cfaad77287124.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值