各种设计模式如何用java代码体现?
设计原则
- 多用组合少用继承。
- 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。
- 针对接口编程,而不是针对实现编程。
- 为了交互对象之间的松耦合设计而努力。
- 类应该对扩展开放,对修改关闭。
- 要依赖抽象,不要依赖具体类。
- 最少知识原则:只和你的密友谈话。(相当于类间交互适当封装,减少耦合,只让必要部分交互)
- 好莱坞原则:别调用我们,我们会调用你。(高层组件控制何时调用底层组件)
- 一个类应该只有一个引起改变的原因。(使一个类具有单一的责任,避免类的改变引起大范围的修改,实现类的高内聚)
- 单一职责( 一个类和方法只做一件事 )
- 里氏替换( 多态,子类可扩展父类 )
- 依赖倒置( 细节依赖抽象,下层依赖上层 )
- 接口隔离( 建立单一接口 )
- 迪米特原则( 最少知道,降低耦合 )
- 开闭原则( 抽象架构,扩展实现 )
策略模式
定义:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式(Strategy Pattern)是一种行为设计模式,它允许在运行时根据不同的情况选择算法的行为。该模式将一组可互换的算法封装成独立的类,使得它们可以相互替换,而不会影响到使用算法的客户端代码。
在Java中,可以通过以下步骤来实现策略模式:
- 首先,定义一个策略接口(Strategy Interface),该接口声明了所有具体策略类(Concrete Strategy)需要实现的方法。
public interface Strategy {
void execute();
}
- 创建具体策略类,实现策略接口,并实现具体的算法逻辑。
public class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
// 实现策略A的算法逻辑
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
// 实现策略B的算法逻辑
}
}
// 可以根据需要创建更多的具体策略类
- 在客户端代码中,创建一个策略对象,并将其传递给使用算法的上下文对象(Context)。上下文对象将根据传入的策略对象来执行相应的算法。
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
// 在客户端代码中使用策略模式
public class Client {
public static void main(String[] args) {
Strategy strategyA = new ConcreteStrategyA();
Strategy strategyB = new ConcreteStrategyB();
Context context = new Context(strategyA);
context.executeStrategy();
// 可以动态切换策略
context.setStrategy(strategyB);
context.executeStrategy();
}
}
在上述示例中,通过使用策略模式,客户端可以根据需要动态选择并切换不同的算法(具体策略类),而无需修改原有的代码。这种灵活性使得策略模式在需要根据不同情况采用不同算法的场景中非常有用。
观察者模式
观察者模式(Observer Pattern)定义了对象之间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖它的对象都能够自动得到通知并更新。观察者模式将主题(被观察者)和观察者抽象成独立的对象,使它们可以独立地进行修改和重用。
在Java中,可以通过以下步骤来实现观察者模式:
- 定义观察者接口(Observer Interface),该接口声明了观察者对象需要实现的方法。
public interface Observer {
void update();
}
- 创建具体观察者类,实现观察者接口,并定义更新逻辑。
public class ConcreteObserver implements Observer {
@Override
public void update() {
// 更新逻辑
}
}
// 可以根据需要创建更多的具体观察者类
- 定义主题接口(Subject Interface),该接口声明了主题对象需要实现的方法,包括注册、取消注册和通知观察者的方法。
public interface Subject {
void registerObserver(Observer observer);
void unregisterObserver(Observer observer);
void notifyObservers();
}
- 创建具体主题类,实现主题接口,并实现具体的注册、取消注册和通知观察者的逻辑
import java.util.ArrayList;
import java.util.List;
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void unregisterObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
// 可以根据需要创建更多的具体主题类
- 在客户端代码中,创建具体主题和具体观察者对象,并进行注册和通知操作。
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.registerObserver(observer1);
subject.registerObserver(observer2);
// 当主题状态发生变化时,通知观察者
subject.notifyObservers();
}
}
在上述示例中,主题(ConcreteSubject)维护了一个观察者(Observer)列表,并提供了注册、取消注册和通知观察者的方法。具体观察者(ConcreteObserver)实现了观察者接口,并在更新方法中定义了自己的更新逻辑。当主题状态发生变化时,调用notifyObservers()方法会通知所有注册的观察者进行更新操作。
观察者模式可以实现松耦合的对象之间的交互,主题和观察者之间的依赖关系是动态的,可以随时添加或移除观察者。这使得观察者模式在实现事件处理、消息传递等场景中非常有用。
装饰者模式
装饰者模式(Decorator Pattern)允许向现有对象添加新的功能,同时又不改变其结构。装饰者模式通过将对象包装在装饰者对象中,实现了动态地添加额外的行为或责任。
在Java中,可以通过以下步骤来实现装饰者模式:
- 定义一个公共接口或抽象类,表示被装饰者和装饰者共同的行为。
public interface Component {
void operation();
}
- 创建具体的被装饰者类,实现公共接口或抽象类,并定义其具体的行为。
public class ConcreteComponent implements Component {
@Override
public void operation() {
// 实现被装饰者的操作
}
}
- 创建装饰者抽象类,实现公共接口或抽象类,并包含一个成员变量用于持有被装饰者对象。
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
- 创建具体的装饰者类,继承装饰者抽象类,并在需要的地方扩展额外的功能。
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
// 执行装饰者A的额外操作
super.operation();
// 执行其他操作
}
}
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
// 执行装饰者B的额外操作
super.operation();
// 执行其他操作
}
}
- 在客户端代码中,创建具体的被装饰者对象,并逐步添加装饰者对象来扩展功能
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component = new ConcreteDecoratorA(component);
component = new ConcreteDecoratorB(component);
// 执行操作
component.operation();
}
}
在上述示例中,首先创建了一个具体的被装饰者对象(ConcreteComponent),然后通过创建装饰者对象(ConcreteDecoratorA和ConcreteDecoratorB)来逐步包装被装饰者对象,以添加额外的功能。最终的对象是被多个装饰者对象包装后的组合对象,调用其operation()
方法时会依次执行被包装对象和各个装饰者对象的操作,从而实现了动态添加功能的效果。
装饰者模式遵循开闭原则,使得新增装饰者类和被装饰者类都很容易,同时避免了类爆炸的问题。它也提供了比继承更灵活的扩展方式,可以动态地组合对象以满足不同的需求。
工厂模式
工厂模式(Factory Pattern)提供了一种创建对象的方式,将对象的实例化过程封装在工厂类中,而不是在客户端直接通过new关键字来创建对象。工厂模式通过定义一个公共接口或抽象类来创建对象,并由具体的工厂类实现对象的创建逻辑。
在Java中,可以通过以下步骤来实现工厂模式:
- 定义一个公共接口或抽象类,表示待创建的对象。
public interface Product {
void operation();
}
- 创建具体的产品类,实现公共接口或抽象类,并定义具体的操作。
public class ConcreteProductA implements Product {
@Override
public void operation() {
// 具体产品A的操作
}
}
public class ConcreteProductB implements Product {
@Override
public void operation() {
// 具体产品B的操作
}
}
// 可以根据需要创建更多的具体产品类
- 创建工厂接口或抽象类,定义创建产品对象的方法。
public interface Factory {
Product createProduct();
}
- 创建具体的工厂类,实现工厂接口或抽象类,并实现创建产品对象的逻辑。
public class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
// 可以根据需要创建更多的具体工厂类
- 在客户端代码中,使用工厂对象创建具体的产品对象。
public class Client {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.operation();
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.createProduct();
productB.operation();
}
}
在上述示例中,定义了一个公共产品接口(Product),并有具体产品类(ConcreteProductA和ConcreteProductB)实现该接口。然后定义了一个工厂接口(Factory),其中包含一个创建产品对象的方法。具体工厂类(ConcreteFactoryA和ConcreteFactoryB)实现了工厂接口,并在其创建产品方法中返回相应的具体产品对象。在客户端代码中,通过具体工厂对象创建具体产品对象,并使用其提供的方法进行操作。
工厂模式将对象的创建过程与客户端代码解耦,客户端不需要直接依赖于具体产品类,而是通过工厂接口来创建对象。这样可以提供灵活性和可扩展性,当需要增加新的产品类时,只需要创建对应的具体产品类和具体工厂类即可,而不需要修改客户端代码。同时,工厂模式也提供了一种封装复杂创建逻辑的方式,使得客户端代码更加简洁和可读性更高。
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)提供了一种将一组相关的产品对象的创建封装在一起的方式,而不需要指定具体产品的类。抽象工厂模式通过定义一个抽象工厂接口或抽象类,然后具体的工厂类实现该接口或继承该抽象类来创建一组相关的产品。
在Java中,可以通过以下步骤来实现抽象工厂模式:
- 定义抽象产品接口或抽象类,表示一组相关的产品。
public interface ProductA {
void operationA();
}
public interface ProductB {
void operationB();
}
- 创建具体的产品类,实现抽象产品接口或抽象类,并定义具体的操作。
public class ConcreteProductA1 implements ProductA {
@Override
public void operationA() {
// 具体产品A1的操作
}
}
public class ConcreteProductA2 implements ProductA {
@Override
public void operationA() {
// 具体产品A2的操作
}
}
public class ConcreteProductB1 implements ProductB {
@Override
public void operationB() {
// 具体产品B1的操作
}
}
public class ConcreteProductB2 implements ProductB {
@Override
public void operationB() {
// 具体产品B2的操作
}
}
// 可以根据需要创建更多的具体产品类
- 创建抽象工厂接口或抽象类,定义创建产品对象的方法。
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
- 创建具体的工厂类,实现抽象工厂接口或抽象类,并实现创建产品对象的逻辑。
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
// 可以根据需要创建更多的具体工厂类
- 在客户端代码中,使用具体工厂对象创建具体的产品对象。
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.operationA();
productB1.operationB();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.operationA();
productB2.operationB();
}
}
在上述示例中,首先定义了一组抽象产品接口(ProductA和ProductB),然后具体产品类(ConcreteProductA1、ConcreteProductA2、ConcreteProductB1和ConcreteProductB2)实现了这些接口。接下来,定义了一个抽象工厂接口(AbstractFactory),其中包含了创建抽象产品对象的方法。具体工厂类(ConcreteFactory1和ConcreteFactory2)实现了抽象工厂接口,并在其创建产品方法中返回相应的具体产品对象。
在客户端代码中,通过具体工厂对象创建具体产品对象,并调用其方法进行操作。通过选择不同的具体工厂对象,可以创建不同组合的产品对象,实现了一种族的产品对象创建。抽象工厂模式提供了一种将一组相关的产品对象创建封装在一起的方式,使得客户端代码更加灵活和可扩展。
命令模式
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成对象,以便在不同的上下文中使用不同的请求、队列或日志请求。命令模式可以将请求发送者和请求接收者解耦,使得发送者不需要知道请求的具体执行细节。
在Java中,可以通过以下步骤来实现命令模式:
- 定义命令接口,声明执行命令的方法。
public interface Command {
void execute();
}
- 创建具体的命令类,实现命令接口,并在其中封装请求的执行逻辑。
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
- 创建命令接收者类,它包含了实际执行请求的方法。
public class Receiver {
public void action() {
// 执行实际的操作
}
}
- 创建命令调用者类,它持有命令对象,并在需要时调用命令对象的执行方法。
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
- 在客户端代码中,创建命令对象、命令接收者对象和命令调用者对象,并进行命令的设置和执行。
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
}
在上述示例中,定义了一个命令接口(Command),其中声明了执行命令的方法。具体命令类(ConcreteCommand)实现了命令接口,并在其中封装了请求的执行逻辑。命令接收者类(Receiver)包含了实际执行请求的方法。
命令调用者类(Invoker)持有命令对象,并在需要时调用命令对象的执行方法。在客户端代码中,创建命令对象、命令接收者对象和命令调用者对象,并进行命令的设置和执行。
通过使用命令模式,客户端和接收者之间解耦了,发送者只需要知道如何发送命令,而不需要关心具体的执行细节。可以轻松地添加新的命令和接收者,使系统更加灵活和可扩展。此外,命令模式还可以支持撤销、重做、队列、日志记录等功能的实现。
适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换为客户端所期望的另一个接口,从而使得原本不兼容的类能够协同工作。适配器模式通过创建一个适配器类,将原始类的接口转换为目标接口,使得客户端可以统一调用适配器的方法,而无需直接与原始类交互。
在Java中,可以通过以下步骤来实现适配器模式:
- 定义目标接口,即客户端所期望的接口。
public interface Target {
void request();
}
- 创建适配器类,实现目标接口,并在其中持有原始类的实例。
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 在适配器类中调用原始类的方法
adaptee.specificRequest();
}
}
- 创建原始类,即需要被适配的类。
public class Adaptee {
public void specificRequest() {
// 原始类的特定操作
}
}
- 在客户端代码中,通过适配器对象调用目标接口的方法。
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
在上述示例中,定义了一个目标接口(Target),其中声明了客户端所期望的方法。适配器类(Adapter)实现了目标接口,并在其中持有原始类(Adaptee)的实例。适配器类中的方法实际上是通过调用原始类的方法来实现的。
原始类(Adaptee)包含了特定的操作方法。在客户端代码中,创建原始类的实例和适配器对象,并通过适配器对象调用目标接口的方法。这样,客户端代码可以通过适配器对象统一调用目标接口的方法,而无需直接与原始类交互。
适配器模式可以用于解决不兼容接口的问题,使得原本不兼容的类能够协同工作。它可以使得客户端代码与具体实现解耦,并支持类的复用和扩展。适配器模式在实际开发中常用于对旧代码的重构或与第三方库的集成。
外观模式
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式定义了一个高层接口,使得客户端可以通过这个接口简化与子系统的交互,同时隐藏了子系统的复杂性。
在Java中,可以通过以下步骤来实现外观模式:
- 创建子系统类,即包含一组相关接口和方法的类。
public class SubsystemA {
public void operationA() {
// 子系统A的操作
}
}
public class SubsystemB {
public void operationB() {
// 子系统B的操作
}
}
public class SubsystemC {
public void operationC() {
// 子系统C的操作
}
}
// 可以根据需要创建更多的子系统类
- 创建外观类,它提供了简化的接口,并在其中协调调用子系统的方法。
public class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
private SubsystemC subsystemC;
public Facade() {
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
subsystemC = new SubsystemC();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
subsystemC.operationC();
}
}
- 在客户端代码中,通过外观对象调用简化的接口,而无需直接与子系统进行交互。
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operation();
}
}
在上述示例中,首先创建了一组子系统类(SubsystemA、SubsystemB和SubsystemC),每个类包含了一些具体的操作方法。然后创建了外观类(Facade),它在其中持有子系统类的实例,并在其简化的接口方法中协调调用子系统的方法。
在客户端代码中,通过创建外观对象,然后调用外观对象的简化接口方法,即可完成与子系统的交互,而无需直接与子系统类进行交互。
外观模式可以隐藏子系统的复杂性,提供了一个简化的接口给客户端使用。它提供了一种结构化的方式来组织子系统,使得系统更加可维护和易于理解。同时,外观模式也可以提供更高层次的接口,对子系统进行定制和扩展。
模板方法模式
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,将算法中的一些步骤延迟到子类中实现。模板方法模式使得子类可以重新定义算法的某些特定步骤,而不需要改变算法的结构。
在Java中,可以通过以下步骤来实现模板方法模式:
- 创建一个抽象类,即模板类,它包含了一个模板方法和一些抽象方法,模板方法定义了算法的骨架。
public abstract class AbstractClass {
public void templateMethod() {
// 步骤1
step1();
// 步骤2
step2();
// 步骤3
step3();
}
protected abstract void step1();
protected abstract void step2();
protected abstract void step3();
}
- 创建具体子类,继承抽象类,并实现抽象方法。
public class ConcreteClass extends AbstractClass {
@Override
protected void step1() {
// 实现步骤1
}
@Override
protected void step2() {
// 实现步骤2
}
@Override
protected void step3() {
// 实现步骤3
}
}
- 在客户端代码中,通过实例化具体子类对象,调用模板方法执行算法。
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();
}
}
在上述示例中,抽象类(AbstractClass)定义了一个模板方法(templateMethod)和一些抽象方法(step1、step2和step3)。模板方法中按照特定的顺序调用了抽象方法,形成了算法的骨架。
具体子类(ConcreteClass)继承了抽象类,并实现了抽象方法,完成了算法中的具体步骤。
在客户端代码中,通过实例化具体子类对象,调用模板方法,即可执行算法。
模板方法模式通过定义一个算法的骨架,将算法中的具体实现延迟到子类中。这样可以保持算法的结构稳定,同时提供了一定的扩展点,允许子类根据需要重写特定的步骤,实现个性化的行为。模板方法模式常用于框架设计和算法骨架的定义。
组合模式
组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树状结构以表示“整体-部分”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性,可以对它们进行统一的操作。
在Java中,可以通过以下步骤来实现组合模式:
创建一个抽象组件类,它可以是接口或抽象类,定义了组合中的对象共有的方法。
public interface Component {
void operation();
}
- 创建叶子节点类,实现抽象组件类,表示组合中的叶子对象。
public class Leaf implements Component {
@Override
public void operation() {
// 叶子节点的操作
}
}
- 创建容器节点类,实现抽象组件类,表示组合中的容器对象,可以包含子组件。
import java.util.ArrayList;
import java.util.List;
public class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
// 容器节点的操作
for (Component component : children) {
component.operation();
}
}
}
- 在客户端代码中,通过组合创建组合对象的树状结构,并调用其方法进行操作。
public class Client {
public static void main(String[] args) {
Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
Composite composite1 = new Composite();
composite1.add(leaf1);
composite1.add(leaf2);
Component leaf3 = new Leaf();
Composite composite2 = new Composite();
composite2.add(leaf3);
composite2.add(composite1);
composite2.operation();
}
}
在上述示例中,抽象组件类(Component)定义了组合中的对象共有的方法。叶子节点类(Leaf)和容器节点类(Composite)都实现了抽象组件类。叶子节点类表示组合中的叶子对象,而容器节点类表示组合中的容器对象,它可以包含子组件。
在客户端代码中,通过创建叶子节点对象和容器节点对象,通过组合创建了一个树状的组合对象结构。然后调用根节点的操作方法,该方法会递归调用每个节点的操作方法,实现对整个组合对象的操作。
组合模式将单个对象和组合对象统一对待,使得客户端可以一致地处理单个对象和组合对象。它提供了一种简化复杂系统的方式,可以构建层次结构,以表示对象的整体-部分关系。组合模式常用于树形结构的处理,例如文件系统、图形界面组件等。
状态模式
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为。状态模式将对象的行为封装在不同的状态类中,使得对象的状态可以动态切换,而不需要使用大量的条件语句。
在Java中,可以通过以下步骤来实现状态模式:
- 创建一个状态接口,定义了对象的各种状态对应的方法。
public interface State {
void handle();
}
- 创建具体的状态类,实现状态接口,定义不同状态下的行为。
public class ConcreteStateA implements State {
@Override
public void handle() {
// 具体状态A的处理逻辑
}
}
public class ConcreteStateB implements State {
@Override
public void handle() {
// 具体状态B的处理逻辑
}
}
- 创建包含状态的上下文类,它具有一个状态成员变量,并在其中调用状态的方法。
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
- 在客户端代码中,创建上下文对象,设置初始状态,并调用上下文对象的方法来执行相应的行为。
public class Client {
public static void main(String[] args) {
Context context = new Context();
State stateA = new ConcreteStateA();
State stateB = new ConcreteStateB();
context.setState(stateA);
context.request();
context.setState(stateB);
context.request();
}
}
在上述示例中,状态接口(State)定义了状态的方法。具体的状态类(ConcreteStateA和ConcreteStateB)实现了状态接口,并在各自的方法中实现了特定状态下的行为。
上下文类(Context)持有一个状态成员变量,并在其中调用状态的方法。客户端代码中,创建上下文对象,设置初始状态,然后通过调用上下文对象的方法来执行相应的行为。
状态模式将对象的行为和状态解耦,使得状态的变化可以独立于对象的行为变化。通过使用多态,可以动态切换对象的状态,并且添加新的状态类也比较容易。状态模式常用于对象具有多种状态,且状态之间的转换较为复杂的情况,例如订单状态、游戏角色状态等。
代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,它允许通过创建一个代理对象来控制对另一个对象的访问。代理对象充当了客户端和目标对象之间的中介,通过代理对象可以间接地访问目标对象,并可以在访问前后添加一些额外的逻辑。
在Java中,可以通过以下步骤来实现代理模式:
- 创建一个接口,定义了客户端和代理对象共同的接口方法。
public interface Subject {
void request();
}
- 创建目标对象类,实现接口,并定义了具体的业务逻辑。
public class RealSubject implements Subject {
@Override
public void request() {
// 目标对象的具体业务逻辑
}
}
- 创建代理对象类,实现接口,并在其中持有一个目标对象的引用。
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 在访问目标对象前可以添加一些额外的逻辑
preRequest();
// 调用目标对象的方法
realSubject.request();
// 在访问目标对象后可以添加一些额外的逻辑
postRequest();
}
private void preRequest() {
// 额外逻辑
}
private void postRequest() {
// 额外逻辑
}
}
- 在客户端代码中,通过代理对象来访问目标对象。
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.request();
}
}
在上述示例中,接口(Subject)定义了客户端和代理对象共同的接口方法。目标对象类(RealSubject)实现了接口,并定义了具体的业务逻辑。
代理对象类(Proxy)也实现了接口,并在其中持有一个目标对象(RealSubject)的引用。在代理对象的方法中,可以在访问目标对象前后添加一些额外的逻辑。
在客户端代码中,创建目标对象和代理对象,然后通过代理对象来访问目标对象的方法。
代理模式可以在不改变目标对象的情况下,增强目标对象的功能或控制对目标对象的访问。代理模式常用于实现延迟加载、权限控制、日志记录等场景。
建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,它允许你按照步骤创建复杂对象。它将对象的构建过程与其表示分离,使得相同的构建过程可以创建不同的表示。
在Java中,可以通过以下步骤来实现建造者模式:
- 创建一个产品类,它包含需要构建的复杂对象的属性。
public class Product {
private String part1;
private String part2;
private String part3;
// 省略构造函数和访问方法
}
- 创建一个抽象建造者类,定义构建产品对象的抽象方法。
public abstract class Builder {
protected Product product;
public void createProduct() {
product = new Product();
}
public abstract void buildPart1();
public abstract void buildPart2();
public abstract void buildPart3();
public Product getProduct() {
return product;
}
}
- 创建具体建造者类,继承抽象建造者类,并实现构建产品对象的具体方法。
public class ConcreteBuilder extends Builder {
@Override
public void buildPart1() {
product.setPart1("Part 1");
}
@Override
public void buildPart2() {
product.setPart2("Part 2");
}
@Override
public void buildPart3() {
product.setPart3("Part 3");
}
}
- 创建指挥者类,负责调用建造者的方法来构建产品对象。
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.createProduct();
builder.buildPart1();
builder.buildPart2();
builder.buildPart3();
return builder.getProduct();
}
}
- 在客户端代码中,使用指挥者对象来构建具体的产品对象。
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
// 使用构建好的产品对象
System.out.println(product.getPart1());
System.out.println(product.getPart2());
System.out.println(product.getPart3());
}
}
在上述示例中,产品类(Product)包含需要构建的复杂对象的属性。抽象建造者类(Builder)定义了构建产品对象的抽象方法,并持有一个产品对象的引用。
具体建造者类(ConcreteBuilder)继承抽象建造者类,并实现了具体的构建方法,完成产品对象的构建过程。
指挥者类(Director)负责调用建造者的方法来构建产品对象。在客户端代码中,创建具体的建造者对象并传入指挥者对象,然后通过指挥者对象的构建方法来构建产品对象。
建造者模式将产品的构建过程与表示分离,通过不同的具体建造者类可以构建出不同的产品对象。它可以在不同的构建步骤中灵活地添加、修改或替换具体的建造者类,使得构建过程更加灵活可扩展。建造者模式常用于构建复杂对象,例如创建包含多个部分的对象,或者对象构建过程需要多个步骤和顺序。
责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象依次处理同一个请求,形成一条处理请求的责任链。当一个请求进入责任链时,每个处理对象有机会处理请求,直到请求被处理完成或达到链的末尾。
在Java中,可以通过以下步骤来实现责任链模式:
- 创建一个抽象处理器类,定义了处理请求的方法,并持有下一个处理器的引用。
public abstract class Handler {
private Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public void handleRequest(Request request) {
// 判断是否能够处理请求
if (canHandle(request)) {
processRequest(request);
} else if (nextHandler != null) {
// 交给下一个处理器处理
nextHandler.handleRequest(request);
} else {
// 没有处理器能够处理请求
System.out.println("No handler can process the request.");
}
}
protected abstract boolean canHandle(Request request);
protected abstract void processRequest(Request request);
}
- 创建具体处理器类,继承抽象处理器类,并实现处理请求的具体逻辑。
public class ConcreteHandlerA extends Handler {
@Override
protected boolean canHandle(Request request) {
// 判断是否能够处理请求的逻辑
// 返回true表示能够处理,返回false表示不能处理
}
@Override
protected void processRequest(Request request) {
// 处理请求的具体逻辑
}
}
public class ConcreteHandlerB extends Handler {
@Override
protected boolean canHandle(Request request) {
// 判断是否能够处理请求的逻辑
// 返回true表示能够处理,返回false表示不能处理
}
@Override
protected void processRequest(Request request) {
// 处理请求的具体逻辑
}
}
- 创建请求类,用于封装请求的信息。
public class Request {
// 请求的信息
}
- 在客户端代码中,创建具体处理器对象并设置处理顺序,然后将请求发送给第一个处理器来处理。
public class Client {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
Request request = new Request();
handlerA.handleRequest(request);
}
}
在上述示例中,抽象处理器类(Handler)定义了处理请求的方法,并持有下一个处理器的引用。具体处理器类(ConcreteHandlerA和ConcreteHandlerB)继承抽象处理器类,并实现了处理请求的具体逻辑。
客户端代码中,创建具体处理器对象并设置处理顺序,然后将请求发送给第一个处理器来处理。每个处理器在处理请求时,先判断自己能否处理该请求,如果可以则处理请求,否则将请求交给下一个处理器。
责任链模式可以动态地组织和拆分责任链,可以灵活地添加、修改或移除处理器对象,从而实现请求处理的动态调整。它将请求发送方和接收方解耦,使得请求的发送方无需知道请求是如何被处理以及被哪个处理器处理的。责任链模式常用于多个对象可以处理同一请求,但处理器之间的处理逻辑有所不同的情况。
原型模式
原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新的对象,而无需通过实例化类和使用构造函数来创建。原型模式通过克隆已有对象的方式来创建新的对象,从而避免了创建对象的复杂性和性能开销。
在Java中,可以通过实现Cloneable
接口和重写clone()
方法来实现原型模式。
下面是一个使用原型模式的示例:
public class Circle implements Cloneable {
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public Circle clone() throws CloneNotSupportedException {
return (Circle) super.clone();
}
@Override
public String toString() {
return "Circle{" +
"x=" + x +
", y=" + y +
", radius=" + radius +
'}';
}
}
在上述示例中,Circle
类实现了Cloneable
接口,并重写了clone()
方法。clone()
方法通过调用super.clone()
来实现对象的浅拷贝。
接下来,我们可以使用原型模式来创建新的对象:
public class Client {
public static void main(String[] args) {
Circle circle = new Circle(10, 20, 5);
System.out.println("原始对象:" + circle);
try {
Circle clonedCircle = circle.clone();
System.out.println("克隆对象:" + clonedCircle);
clonedCircle.setX(15);
clonedCircle.setY(25);
clonedCircle.setRadius(8);
System.out.println("修改后的克隆对象:" + clonedCircle);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
在客户端代码中,我们首先创建一个原始对象circle,然后通过调用clone()方法来创建克隆对象clonedCircle。通过修改克隆对象的属性,我们可以看到原始对象和克隆对象是相互独立的。
原型模式在创建对象时避免了使用构造函数,可以提高对象的创建效率。它适用于创建复杂对象的场景,特别是当对象的创建过程比较耗时或复杂时。通过原型模式,我们可以复制已有对象的状态,然后根据需求进行调整和修改,从而快速创建新的对象。
桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分和实现部分解耦,使得它们可以独立地变化。桥接模式通过创建一个桥接接口,让抽象部分和实现部分分别继承桥接接口和实现接口,从而实现它们的解耦。
在Java中,可以通过以下步骤来实现桥接模式:
- 创建抽象部分的接口(或抽象类),定义抽象部分的行为。
public interface Abstraction {
void operation();
}
- 创建实现部分的接口(或抽象类),定义实现部分的行为。
public interface Implementor {
void implementation();
}
- 创建具体的抽象部分类,实现抽象部分的接口,并持有实现部分的接口。
public class ConcreteAbstraction implements Abstraction {
private Implementor implementor;
public ConcreteAbstraction(Implementor implementor) {
this.implementor = implementor;
}
@Override
public void operation() {
// 调用实现部分的方法
implementor.implementation();
}
}
- 创建具体的实现部分类,实现实现部分的接口。
public class ConcreteImplementorA implements Implementor {
@Override
public void implementation() {
// 具体实现部分A的逻辑
}
}
public class ConcreteImplementorB implements Implementor {
@Override
public void implementation() {
// 具体实现部分B的逻辑
}
}
- 在客户端代码中,创建具体的抽象部分对象,并将具体的实现部分对象传入构造函数。
public class Client {
public static void main(String[] args) {
Implementor implementorA = new ConcreteImplementorA();
Abstraction abstractionA = new ConcreteAbstraction(implementorA);
abstractionA.operation();
Implementor implementorB = new ConcreteImplementorB();
Abstraction abstractionB = new ConcreteAbstraction(implementorB);
abstractionB.operation();
}
}
在上述示例中,抽象部分的接口(Abstraction)定义了抽象部分的行为,实现部分的接口(Implementor)定义了实现部分的行为。
具体的抽象部分类(ConcreteAbstraction)实现了抽象部分的接口,并持有实现部分的接口。在抽象部分的方法中,调用实现部分的方法来完成具体的实现。
具体的实现部分类(ConcreteImplementorA和ConcreteImplementorB)实现了实现部分的接口,分别提供了具体的实现逻辑。
在客户端代码中,我们创建具体的抽象部分对象,并将具体的实现部分对象传入构造函数。通过桥接模式,抽象部分和实现部分可以独立地变化,我们可以在运行时动态地选择不同的实现部分来组合成不同的抽象部分对象。
桥接模式可以使得抽象部分和实现部分可以独立地进行扩展和修改,而不会相互影响。它常用于需要在运行时动态切换或组合不同实现的情况,从而提供更大的灵活性和可扩展性。
蝇量模式(享元模式)
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。享元模式通过将对象的状态分为内部状态(Intrinsic State)和外部状态(Extrinsic State),其中内部状态可以被多个对象共享,而外部状态需要根据具体情况进行传递。
在Java中,可以通过以下步骤来实现享元模式:
- 创建享元接口,定义对象的操作方法。
public interface Flyweight {
void operation(String externalState);
}
- 创建具体享元类,实现享元接口,并包含内部状态。
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String externalState) {
System.out.println("Intrinsic State: " + intrinsicState);
System.out.println("External State: " + externalState);
// 具体操作逻辑
}
}
- 创建享元工厂类,用于管理和创建享元对象。
public class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (flyweights.containsKey(key)) {
return flyweights.get(key);
} else {
Flyweight flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
return flyweight;
}
}
}
- 在客户端代码中,通过享元工厂来获取享元对象,并传递外部状态进行操作。
public class Client {
public static void main(String[] args) {
FlyweightFactory flyweightFactory = new FlyweightFactory();
Flyweight flyweight1 = flyweightFactory.getFlyweight("key1");
flyweight1.operation("external state 1");
Flyweight flyweight2 = flyweightFactory.getFlyweight("key2");
flyweight2.operation("external state 2");
Flyweight flyweight3 = flyweightFactory.getFlyweight("key1");
flyweight3.operation("external state 3");
}
}
在上述示例中,享元接口(Flyweight)定义了对象的操作方法。
具体享元类(ConcreteFlyweight)实现了享元接口,并包含内部状态(intrinsicState)。在操作方法中,输出内部状态和外部状态的值,然后执行具体的操作逻辑。
享元工厂类(FlyweightFactory)用于管理和创建享元对象。它通过一个Map来存储已创建的享元对象,并根据需要返回已有的享元对象或创建新的享元对象。
在客户端代码中,我们通过享元工厂来获取享元对象,并传递外部状态进行操作。注意,当获取享元对象时,如果已存在相同内部状态的对象,则直接返回已有的对象,实现了对象的共享。
享元模式通过共享对象的方式来节省内存和提高性能,特别适用于存在大量相似对象的情况。它能够有效地减少系统中对象的数量,节省了内存空间,并且可以在一定程度上提升系统的性能。
解释器模式
解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法表示,并且可以解释和执行该语言中的表达式。解释器模式通过使用一个解释器对象来表示文法的规则,然后根据需要解释和执行不同的表达式。
在Java中,可以通过以下步骤来实现解释器模式:
- 定义抽象表达式(AbstractExpression)类,声明解释操作的抽象方法。
public interface AbstractExpression {
void interpret(Context context);
}
- 创建具体表达式(ConcreteExpression)类,实现抽象表达式接口,并实现解释操作。
public class TerminalExpression implements AbstractExpression {
@Override
public void interpret(Context context) {
// 解释操作的具体实现
}
}
public class NonterminalExpression implements AbstractExpression {
private AbstractExpression expression;
public NonterminalExpression(AbstractExpression expression) {
this.expression = expression;
}
@Override
public void interpret(Context context) {
// 解释操作的具体实现,可以调用其他表达式的解释方法
expression.interpret(context);
}
}
- 创建上下文(Context)类,用于存储和传递解释器的上下文信息。
public class Context {
private String data;
public Context(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
- 在客户端代码中,根据需要创建具体的表达式对象,并构建解释器的表达式树。
public class Client {
public static void main(String[] args) {
Context context = new Context("Context data");
AbstractExpression expression1 = new TerminalExpression();
AbstractExpression expression2 = new NonterminalExpression(expression1);
expression2.interpret(context);
}
}
在上述示例中,抽象表达式接口(AbstractExpression)定义了解释操作的抽象方法。
具体表达式类(TerminalExpression和NonterminalExpression)实现了抽象表达式接口,并实现了解释操作。非终结符表达式类(NonterminalExpression)中可以持有其他表达式对象,以实现复杂的解释逻辑。
上下文类(Context)用于存储和传递解释器的上下文信息。
在客户端代码中,我们根据需要创建具体的表达式对象,并构建解释器的表达式树。通过调用根表达式的解释方法,可以依次解释执行整个表达式树。
解释器模式适用于需要解释和执行一种特定语言的表达式,特别是当表达式的规则较为复杂或需要频繁变动时。它将语言的文法规则表示为对象,从而可以灵活地扩展和修改解释的行为。
中介者模式
中介者模式(Mediator Pattern)是一种行为型设计模式,它通过封装一系列对象之间的交互,使它们不直接相互引用,而是通过一个中介者对象来进行通信和协调。中介者模式将对象之间的复杂关系转移到中介者对象中,从而简化了对象之间的交互和管理。
在Java中,可以通过以下步骤来实现中介者模式:
- 定义中介者(Mediator)接口,声明各个对象之间交互的方法。
public interface Mediator {
void send(String message, Colleague colleague);
}
- 创建具体中介者(ConcreteMediator)类,实现中介者接口,并管理各个对象之间的交互关系。
public class ConcreteMediator implements Mediator {
private Colleague colleague1;
private Colleague colleague2;
public void setColleague1(Colleague colleague1) {
this.colleague1 = colleague1;
}
public void setColleague2(Colleague colleague2) {
this.colleague2 = colleague2;
}
@Override
public void send(String message, Colleague colleague) {
if (colleague == colleague1) {
colleague2.receive(message);
} else if (colleague == colleague2) {
colleague1.receive(message);
}
}
}
- 定义抽象同事类(Colleague)并维护对中介者对象的引用,提供发送消息的方法。
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public abstract void send(String message);
public abstract void receive(String message);
}
- 创建具体同事类(ConcreteColleague)并实现发送消息和接收消息的方法。
public class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}
@Override
public void send(String message) {
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println("ConcreteColleague1 received: " + message);
}
}
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}
@Override
public void send(String message) {
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println("ConcreteColleague2 received: " + message);
}
}
- 在客户端代码中,创建中介者对象和具体同事对象,并设置彼此之间的关联关系。
public class Client {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
mediator.setColleague1(colleague1);
mediator.setColleague2(colleague2);
colleague1.send("Hello");
colleague2.send("Hi");
}
}
在上述示例中,中介者接口(Mediator)定义了各个对象之间交互的方法。
具体中介者类(ConcreteMediator)实现了中介者接口,并在其中管理各个对象之间的交互关系。当某个同事对象发送消息时,中介者根据需要将消息传递给其他同事对象。
抽象同事类(Colleague)维护对中介者对象的引用,并提供发送消息的方法。具体同事类(ConcreteColleague)继承抽象同事类,并实现发送消息和接收消息的方法。
在客户端代码中,我们创建中介者对象和具体同事对象,并通过中介者对象设置彼此之间的关联关系。然后,可以通过同事对象的发送方法发送消息,中介者会根据需要将消息传递给其他相关的同事对象。
中介者模式通过引入中介者对象,减少了对象之间的直接耦合,提供了一种松散耦合的方式来组织对象之间的交互。它适用于对象之间存在复杂的交互关系,而且随着交互规则的变化,减少了对象之间的相互依赖。
备忘录模式
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许将对象的内部状态保存并在需要时恢复到先前的状态。备忘录模式通过引入备忘录对象,将状态的保存和恢复逻辑与原始对象分离,从而提供了一种可靠的方式来实现对象状态的备份和恢复。
在Java中,可以通过以下步骤来实现备忘录模式:
创建原始对象(Originator)类,该类需要保存和恢复状态,并提供创建备忘录和从备忘录恢复状态的方法。
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento createMemento() {
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
state = memento.getState();
}
}
- 创建备忘录(Memento)类,用于保存原始对象的状态。
public class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
- 创建管理者(CareTaker)类,用于管理备忘录对象的保存和恢复。
public class CareTaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento retrieveMemento() {
return memento;
}
}
- 在客户端代码中,创建原始对象和管理者对象,并使用原始对象的方法来修改状态和创建备忘录,然后使用管理者对象来保存备忘录或恢复状态。
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State 1");
careTaker.saveMemento(originator.createMemento());
originator.setState("State 2");
careTaker.saveMemento(originator.createMemento());
originator.setState("State 3");
Memento memento = careTaker.retrieveMemento();
originator.restoreFromMemento(memento);
System.out.println("Current State: " + originator.getState());
}
}
在上述示例中,原始对象类(Originator)保存和恢复状态的方法被实现,包括设置状态、获取状态、创建备忘录和从备忘录恢复状态的方法。
备忘录类(Memento)用于保存原始对象的状态。
管理者类(CareTaker)用于管理备忘录对象的保存和恢复。
在客户端代码中,我们创建原始对象和管理者对象,并使用原始对象的方法来修改状态和创建备忘录。然后使用管理者对象来保存备忘录或恢复状态。最后,通过原始对象获取当前状态并进行打印。
备忘录模式允许在不破坏封装性的情况下,将对象的状态保存和恢复。它适用于需要保存对象状态并能够在需要时恢复到先前状态的场景,尤其是当对象的状态变化较为复杂或需要多次保存和恢复状态时。
访问者模式
访问者模式(Visitor Pattern)是一种行为型设计模式,它定义了一种操作,可以在不改变被操作对象的类的前提下,通过访问者对象对被操作对象进行新的操作。访问者模式将数据结构和操作分离,使得操作可以独立变化而不影响数据结构。
在Java中,可以通过以下步骤来实现访问者模式:
- 创建被访问者(Element)接口,定义了一个接受访问者的方法。
public interface Element {
void accept(Visitor visitor);
}
- 创建具体的被访问者(ConcreteElement)类,实现被访问者接口,并实现接受访问者的方法。
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationA() {
// 具体元素A的操作
}
}
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationB() {
// 具体元素B的操作
}
}
- 创建访问者(Visitor)接口,定义了对具体元素的访问方法。
public interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}
- 创建具体的访问者(ConcreteVisitor)类,实现访问者接口,并实现对具体元素的访问方法。
public class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
// 对具体元素A进行访问操作
elementA.operationA();
}
@Override
public void visit(ConcreteElementB elementB) {
// 对具体元素B进行访问操作
elementB.operationB();
}
}
- 在客户端代码中,创建具体元素对象和访问者对象,并通过具体元素的接受访问者方法来进行操作。
public class Client {
public static void main(String[] args) {
Element elementA = new ConcreteElementA();
Element elementB = new ConcreteElementB();
Visitor visitor = new ConcreteVisitor();
elementA.accept(visitor);
elementB.accept(visitor);
}
}
在上述示例中,被访问者接口(Element)定义了接受访问者的方法。
具体的被访问者类(ConcreteElementA和ConcreteElementB)实现了被访问者接口,并在接受访问者方法中调用访问者的访问方法。
访问者接口(Visitor)定义了对具体元素的访问方法。
具体的访问者类(ConcreteVisitor)实现了访问者接口,并在对具体元素的访问方法中执行相应的操作。
在客户端代码中,我们创建具体元素对象和访问者对象,并通过具体元素的接受访问者方法来进行操作。
访问者模式将对元素的操作从元素类中抽离出来,使得元素类的结构稳定,而具体的操作逻辑可以根据需要进行扩展和变化。它适用于需要对复杂对象结构进行操作,并且操作的种类经常发生变化的场景。