观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
在Java中,观察者模式通常通过接口和类来实现。以下是一个简单的观察者模式示例,包括一个主题(Subject)接口、一个观察者(Observer)接口以及它们的实现类。
首先,我们定义Observer
接口,它有一个update
方法,用于接收来自主题的通知:
// Observer.java
public interface Observer {
void update(String message);
}
接着,我们定义Subject
接口,它有一个addObserver
方法用于添加观察者,一个removeObserver
方法用于移除观察者,以及一个notifyObservers
方法用于通知所有观察者:
// Subject.java
import java.util.ArrayList;
import java.util.List;
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String message);
}
现在,我们实现一个具体的主题类ConcreteSubject
,它实现了Subject
接口:
// ConcreteSubject.java
import java.util.ArrayList;
import java.util.List;
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
notifyObservers(state);
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
最后,我们实现一个具体的观察者类ConcreteObserver
,它实现了Observer
接口:
// ConcreteObserver.java
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
现在,我们可以编写一个测试类来演示观察者模式的工作方式:
// ObserverPatternDemo.java
public class ObserverPatternDemo {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
Observer observer3 = new ConcreteObserver("Observer 3");
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.addObserver(observer3);
subject.setState("State has changed to A");
subject.setState("State has changed to B");
// Removing an observer
subject.removeObserver(observer2);
subject.setState("State has changed to C");
}
}
运行ObserverPatternDemo
类,你将看到以下输出:
Observer 1 received message: State has changed to A
Observer 2 received message: State has changed to A
Observer 3 received message: State has changed to A
Observer 1 received message: State has changed to B
Observer 3 received message: State has changed to B
Observer 1 received message: State has changed to C
Observer 3 received message: State has changed to C
在这个示例中,当ConcreteSubject
的状态发生变化时,它会通知所有注册的观察者,并且观察者会相应地更新自己。注意,我们在最后一次状态变化之前移除了observer2
,因此它不再接收更新消息。
模板模式
Java模板模式是一种行为设计模式,它定义了一个算法的框架,将一些步骤推迟到子类中实现。这个模式的主要目的是在不改变算法结构的情况下,通过不同的子类实现来扩展算法的行为。以下是对Java模板模式的详细解释:
一、模板模式的结构
-
抽象类(Abstract Class):
- 定义一个模板方法,该方法包含算法的骨架,并调用一系列抽象方法。
- 这些抽象方法由子类实现,具体实现由子类决定。
- 模板方法通常被声明为
final
,以防止子类重写。
-
具体子类(Concrete Class):
- 继承抽象类并实现其中的抽象方法。
- 通过实现这些抽象方法,子类提供了算法中特定步骤的具体实现。
二、模板模式的实现步骤
-
创建抽象类:
- 在抽象类中定义模板方法和抽象方法。
- 模板方法中包含调用抽象方法的代码。
-
实现具体子类:
- 继承抽象类。
- 实现抽象类中的抽象方法。
-
客户端代码:
- 创建具体子类的实例。
- 调用模板方法来执行算法。
三、模板模式的示例
以下是一个简单的Java模板模式示例,模拟制作咖啡的过程:
// 抽象类
abstract class CoffeeTemplate {
// 模板方法
public final void prepareCoffee() {
boilWater();
brew();
pourInCup();
addCondiments();
}
// 具体方法
private void boilWater() {
System.out.println("将水煮沸");
}
// 抽象方法,由子类实现
protected abstract void brew();
// 具体方法
private void pourInCup() {
System.out.println("将咖啡倒入杯中");
}
// 抽象方法,由子类实现
protected abstract void addCondiments();
}
// 具体子类
class Coffee extends CoffeeTemplate {
@Override
protected void brew() {
System.out.println("用滤网过滤咖啡");
}
@Override
protected void addCondiments() {
System.out.println("添加糖和牛奶");
}
}
// 客户端代码
public class TemplateMethodPatternDemo {
public static void main(String[] args) {
CoffeeTemplate coffee = new Coffee();
coffee.prepareCoffee();
}
}
在这个示例中,CoffeeTemplate
是抽象类,定义了制作咖啡的模板方法prepareCoffee
,并包含了一些具体方法(如boilWater
和pourInCup
)和两个抽象方法(如brew
和addCondiments
)。Coffee
是具体子类,实现了这两个抽象方法。客户端代码创建了一个Coffee
实例,并调用了模板方法prepareCoffee
来执行制作咖啡的算法。
四、模板模式的优点和缺点
优点:
- 提高了代码的复用性:将算法的公共部分提取到父类中,子类只需要实现特定的步骤。
- 增强了代码的扩展性:通过子类来实现算法中的特定步骤,可以方便地扩展算法的行为。
- 遵循了开闭原则:对扩展开放,对修改关闭。通过添加新的子类来实现新的算法行为,而不需要修改现有的代码。
缺点:
- 类的数量可能会增加:对于每个不同的算法实现,都需要创建一个新的子类。
- 增加了系统的复杂度:由于类的数量增加,系统的设计和实现可能会变得更加复杂。
- 子类对父类的依赖性较高:如果父类中的方法发生更改,可能会影响所有子类。
总的来说,Java模板模式是一种非常有用的设计模式,可以提高代码的复用性和扩展性,但在使用时也需要注意其可能带来的缺点。
责任链模式
责任链模式(Chain of Responsibility)是一种行为设计模式,它允许你将请求沿着处理者链进行传递。每个处理者都对请求进行某些处理,并且可以决定是否将请求传递给链中的下一个处理者。这个模式使得你可以在不修改现有代码结构的情况下,动态地增加或删除处理者。
在Java中,责任链模式通常通过以下方式实现:
-
定义一个处理请求的接口:这个接口声明了处理请求的方法。
-
实现具体的处理者类:这些类实现了处理请求的接口,并包含指向链中下一个处理者的引用。每个处理者都可以决定是否处理请求,或者将请求传递给链中的下一个处理者。
-
组装处理者链:在客户端代码中,你需要创建处理者对象,并将它们链接在一起,形成一个处理者链。
-
提交请求:客户端通过向链中的第一个处理者提交请求来启动责任链。
下面是一个简单的Java示例,展示了责任链模式的实现:
// 定义处理请求的接口
interface Handler {
void handleRequest(String request);
void setNext(Handler nextHandler);
}
// 实现具体的处理者类
class ConcreteHandler1 implements Handler {
private Handler nextHandler;
@Override
public void handleRequest(String request) {
if ("Handler1".equals(request)) {
System.out.println("ConcreteHandler1 handled the request.");
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
@Override
public void setNext(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
// 另一个具体的处理者类,实现方式与ConcreteHandler1类似
class ConcreteHandler2 implements Handler {
private Handler nextHandler;
@Override
public void handleRequest(String request) {
if ("Handler2".equals(request)) {
System.out.println("ConcreteHandler2 handled the request.");
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
@Override
public void setNext(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
// 客户端代码
public class ChainOfResponsibilityDemo {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
// 组装处理者链
handler1.setNext(handler2);
// 提交请求
handler1.handleRequest("Handler1"); // ConcreteHandler1 handled the request.
handler1.handleRequest("Handler2"); // ConcreteHandler2 handled the request.
handler1.handleRequest("Handler3"); // No output, as no handler handles "Handler3"
}
}
在这个示例中,ConcreteHandler1
和 ConcreteHandler2
是两个具体的处理者类,它们实现了 Handler
接口。在 ChainOfResponsibilityDemo
类中,我们创建了两个处理者对象,并将它们链接在一起。然后,我们向链中的第一个处理者提交了三个请求。每个处理者都检查请求是否是自己可以处理的,如果是,则处理它;如果不是,则将请求传递给链中的下一个处理者。
责任链模式的一个优点是它提供了灵活性,允许你动态地改变处理者的顺序或添加新的处理者,而无需修改现有代码。然而,这个模式也可能导致请求在链中传递过多次,从而降低性能。此外,如果链中没有处理者能够处理请求,那么请求可能会丢失或被忽略。因此,在使用责任链模式时,需要仔细设计处理者的逻辑和链的组装方式。