欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 【Android】行为型设计模式—策略模式、模版方法模式、观察者模式

【Android】行为型设计模式—策略模式、模版方法模式、观察者模式

2024/12/22 0:22:21 来源:https://blog.csdn.net/2301_79977698/article/details/144491259  浏览:    关键词:【Android】行为型设计模式—策略模式、模版方法模式、观察者模式

策略模式

策略模式是一种行为设计模式,它定义了一系列算法,并将每一个算法封装起来,让它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。

uses >
Context
+contextInterface()
Strategy
+algorithm()
ConcreteStrategyA
+algorithm()
ConcreteStrategyB
+algorithm()
  • Context:上下文角色,用来操作策略的上下文环境,起到承上启下的作用,屏蔽高层模块对策略、算法的直接访问。
  • Stragety:抽象策略角色,策略、算法的抽象,通常为接口。
  • ConcreteStragety:具体的策略实现。

简单实现

策略模式的简单实现通常涉及以下几个部分:定义一个策略接口,然后根据不同的算法实现该接口,最后在一个上下文类中使用这些策略。以下是一个简化的示例:

(1)策略接口

策略接口定义了一个方法,所有的具体策略类都需要实现这个方法。

public interface Strategy {int execute(int a, int b);
}

(2)具体策略类

我们实现不同的策略类来执行不同的算法。比如,加法减法乘法

// 加法策略
public class AddStrategy implements Strategy {@Overridepublic int execute(int a, int b) {return a + b;}
}// 减法策略
public class SubtractStrategy implements Strategy {@Overridepublic int execute(int a, int b) {return a - b;}
}// 乘法策略
public class MultiplyStrategy implements Strategy {@Overridepublic int execute(int a, int b) {return a * b;}
}

(3)上下文类

上下文类 Context 使用策略接口来调用具体的策略类。

public class Context {private Strategy strategy;// 设置策略public void setStrategy(Strategy strategy) {this.strategy = strategy;}// 执行策略public int executeStrategy(int a, int b) {return strategy.execute(a, b);}
}

(4)测试类

在测试类中,我们可以通过设置不同的策略来运行不同的算法。

public class StrategyPatternExample {public static void main(String[] args) {Context context = new Context();// 使用加法策略context.setStrategy(new AddStrategy());System.out.println("10 + 5 = " + context.executeStrategy(10, 5));// 使用减法策略context.setStrategy(new SubtractStrategy());System.out.println("10 - 5 = " + context.executeStrategy(10, 5));// 使用乘法策略context.setStrategy(new MultiplyStrategy());System.out.println("10 * 5 = " + context.executeStrategy(10, 5));}
}

(5)输出

10 + 5 = 15
10 - 5 = 5
10 * 5 = 50

使用场景和优缺点

  • 使用场景:

    • 对客户隐藏具体策略(算法)的实现细节,彼此完全独立
    • 针对同一类型问题的多种处理方式,仅具体行为有差别时
    • 在一个类中定义了很多行为,而且这些行为在这个类里的操作以多个条件语句的形式出现。策略模式将相关的条件分支移入它们各自的Strategy类中,以代替这些条件语句
  • 优点:

    • 使用策略模式可以避免使用多重条件语句。多重条件语句不易维护,而且易出错
    • 易于拓展。当需要添加一个策略时,只需要实现接口就可以了
  • 缺点:

    • 每一个策略都是一个类,复用性小。如果策略过多,类的数量会增多
    • 上层模块必须知道有哪些策略,才能够使用这些策略,这与迪米特原则相违背

模版方法模式

模版方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,并允许子类在不改变算法结构的情况下,重新定义算法的某些步骤。该模式通过继承实现,父类负责封装大致流程,而具体细节则由子类提供。

AbstractClass
-stepOne()
-stepTwo()
-stepThree()
+execute()
ConcreteClassA
ConcreteClassB
  • 抽象类(AbstractClass):定义了算法的模板方法和一些基本方法。模板方法一般是一个封装了算法骨架的固定方法,它不允许子类修改,只有算法的个别步骤可以由子类重写。
  • 具体类(ConcreteClass):实现抽象类中的某些方法,具体实现各个步骤的细节。

简单实现

假设我们有一个抽象的制作咖啡和茶的流程。虽然制作的步骤相似(比如加热水、倒水等),但是具体的饮料制作细节有所不同(如茶需要浸泡,而咖啡需要过滤)。

(1)抽象类

public abstract class Beverage {// 模版方法,定义了制作饮料的骨架public final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 固定步骤:烧水private void boilWater() {System.out.println("Boiling water");}// 固定步骤:倒入杯中private void pourInCup() {System.out.println("Pouring into cup");}// 变动步骤:由子类实现protected abstract void brew();  // 不同饮料的冲泡方式不同// 变动步骤:由子类实现protected abstract void addCondiments();  // 不同饮料的调料不同
}

(2)具体类:咖啡

public class Coffee extends Beverage {@Overrideprotected void brew() {System.out.println("Brewing coffee");}@Overrideprotected void addCondiments() {System.out.println("Adding sugar and milk");}
}

(3)具体类:茶

public class Tea extends Beverage {@Overrideprotected void brew() {System.out.println("Steeping the tea");}@Overrideprotected void addCondiments() {System.out.println("Adding lemon");}
}

(4)客户端代码

public class TemplateMethodExample {public static void main(String[] args) {Beverage coffee = new Coffee();Beverage tea = new Tea();System.out.println("Making coffee:");coffee.prepareRecipe();  // 按照模板做咖啡System.out.println("\nMaking tea:");tea.prepareRecipe();  // 按照模板做茶}
}

(5)输出

Making coffee:
Boiling water
Brewing coffee
Pouring into cup
Adding sugar and milkMaking tea:
Boiling water
Steeping the tea
Pouring into cup
Adding lemon

使用场景和优缺点

  • 使用场景:

    • 多个子类有共有的方法,并且逻辑基本相同时

    • 面对重要、复杂的算法,可以把核心算法设计为模板方法,周边相关细节功能则由各个子类实现。

    • 需要通过子类来决定父类算法中的某个步骤是否执行,实现子类对父类的反向控制。

  • 优点:

    • 模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某
    • 些细节,有助于算法的扩展。
  • 缺点:

    • 每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象

观察者模式

观察者模式是一种行为设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会自动得到通知并更新。这个模式通常用于事件驱动的系统中。

+subject
1
*
Subject
+attach(o: Observer)
+detach(o: Observer)
+notify()
Observer
+update()
ConcreteSubject
ConcreteObserver
  • Subject:抽象主题(抽象被观察者)。抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加或删除观察者对象。
  • ConcreteSubiect:具体主题(具体被观察者)。该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  • Observer:抽象观察者,是观察者的抽象类。它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态

简单实现

假设有一个天气预报系统,天气变化时,多个设备(如温度显示、气象站等)需要接收到天气变化的通知。

(1)主题(被观察者)接口

public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}

(2)观察者接口

public interface Observer {void update(float temperature, float humidity, float pressure);
}

(3)具体主题(天气数据)

public class WeatherData implements Subject {private List<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(temperature, humidity, pressure);}}// 更新天气数据public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;notifyObservers(); // 数据更新后通知所有观察者}
}

(4)具体观察者(温度显示)

public class TemperatureDisplay implements Observer {private float temperature;@Overridepublic void update(float temperature, float humidity, float pressure) {this.temperature = temperature;display();}public void display() {System.out.println("Temperature Display: " + temperature + "°C");}
}

(5)具体观察者(气象站)

public class WeatherStation implements Observer {private float temperature;private float humidity;private float pressure;@Overridepublic void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;display();}public void display() {System.out.println("Weather Station - Temperature: " + temperature + "°C, Humidity: " + humidity + "%, Pressure: " + pressure + "hPa");}
}

(6)客户端代码(测试)

public class ObserverPatternExample {public static void main(String[] args) {// 创建主题对象WeatherData weatherData = new WeatherData();// 创建观察者对象TemperatureDisplay tempDisplay = new TemperatureDisplay();WeatherStation weatherStation = new WeatherStation();// 注册观察者weatherData.registerObserver(tempDisplay);weatherData.registerObserver(weatherStation);// 更新天气数据并通知所有观察者weatherData.setMeasurements(25.5f, 65.0f, 1013.1f);weatherData.setMeasurements(27.0f, 60.0f, 1012.5f);}
}

(7)输出

Temperature Display: 25.5°C
Weather Station - Temperature: 25.5°C, Humidity: 65.0%, Pressure: 1013.1hPa
Temperature Display: 27.0°C
Weather Station - Temperature: 27.0°C, Humidity: 60.0%, Pressure: 1012.5hPa

使用场景和优缺点

  • 使用场景:
    • 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系
    • 事件多级触发场景
    • 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
  • 优点:
    • 观察者和被观察者之间是抽象耦合的,容易扩展。
    • 方便建立一套触发机制。
  • 缺点:在应用观察者模式时需要考虑一下开发效率和运行效率的问题。程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂;而且在Java中消息的通知一般是顺序执行的,那么一个观察者卡顿,会影响整体的执行效率。在这种情况下,一般会采用异步方式。

已经到底啦!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com