当前位置: 首页 > news >正文

大连鼎信网站建设公司地址wordpress过期

大连鼎信网站建设公司地址,wordpress过期,网站上的代码网页怎么做的,国家扶持新型环保项目23大设计模式#xff08;即软件设计中的24种常用设计模式#xff09;源自《设计模式#xff1a;可复用面向对象软件的基础》一书#xff0c;由四位作者#xff08;Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides#xff09;提出#xff0c;通常也被称为“Go…23大设计模式即软件设计中的24种常用设计模式源自《设计模式可复用面向对象软件的基础》一书由四位作者Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides提出通常也被称为“GoF设计模式”。这些模式分为三大类创建型模式、结构型模式和行为型模式。 知识体系系统性梳理 创建型模式4种 创建型模式处理对象创建问题注重如何使系统在创建对象时更加灵活和高效。 单例模式Singleton Pattern 单例模式的定义是确保一个类最多只有一个实例并提供一个全局访问点。这是为了保证系统中的某些资源如配置类、数据库连接等只有一个全局的实例防止创建多个实例导致不一致的状态或资源浪费。 在单例模式中可以根据实例的创建时机分为两种实现方式预加载和懒加载。 预加载饿汉式Eager Initialization 在预加载模式下单例实例在类加载时就会被创建无论是否已经使用。这种方式创建的单例对象是线程安全的因为实例是在类加载过程中完成的且 JVM 保证类加载过程中的线程安全性。 public class Singleton {// 1. 静态实例在类加载时创建private static final Singleton instance new Singleton();// 2. 私有化构造函数防止外部实例化private Singleton() {}// 3. 提供全局访问点public static Singleton getInstance() {return instance;} }特点 线程安全因为实例是在类加载的时候创建的线程安全性由 JVM 保证。高效没有加锁也没有延迟创建每次访问时都能立即返回实例。缺点即使单例不被使用它也会一直存在可能会浪费系统资源特别是当单例类非常占用内存时。 懒加载懒汉式Lazy Initialization 在懒加载模式下单例实例只有在第一次调用时才会被创建。这种方式可以避免系统资源的浪费尤其是在实例的创建代价较大或单例并不常用的情况下。懒加载的单例模式可以是线程安全的也可以是非线程安全的。 非线程安全的懒加载实现 public class Singleton {private static Singleton instance;// 私有化构造函数防止外部实例化private Singleton() {}// 提供全局访问点非线程安全public static Singleton getInstance() {if (instance null) {instance new Singleton(); // 第一次调用时创建实例}return instance;} }线程安全的懒加载实现 通过 同步 或 双重检查锁 来确保线程安全。 线程安全的同步实现 public class Singleton {private static Singleton instance;private Singleton() {}// 通过 synchronized 确保线程安全public static synchronized Singleton getInstance() {if (instance null) {instance new Singleton();}return instance;} }双重检查锁Double-Checked Locking public class Singleton {// 使用 volatile 防止指令重排序private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance null) { // 第一次检查synchronized (Singleton.class) {if (instance null) { // 第二次检查instance new Singleton();}}}return instance;} }特点 懒加载实例在第一次使用时才创建避免了不必要的资源浪费。线程安全的懒加载需要增加一定的性能开销如加锁、双重检查锁。延迟加载适合那些实例化开销较大或不一定会被使用的类。 总结预加载 vs 懒加载 预加载饿汉式实例在类加载时就创建线程安全但可能浪费资源。懒加载懒汉式实例在第一次调用时创建懒加载节约资源但需要考虑线程安全问题。 原型模式Prototype Pattern 原型模式Prototype Pattern允许通过复制现有对象来创建新的对象而不是通过类的实例化。这样可以避免使用 new 关键字直接创建对象尤其在对象创建成本较高或需要大量类似对象时原型模式非常有用。 原型模式的关键要素 原型接口定义了一个用于克隆自身的方法。具体原型类实现了原型接口并定义了如何复制对象的具体过程。客户端通过调用原型对象的克隆方法来创建新的对象。 原型模式的实现步骤 定义一个 Cloneable 接口或实现 Java 提供的 Cloneable 接口。实现 clone() 方法用于复制对象。通过原型模式可以快速创建对象而不需要直接调用构造函数。 public class Prototype implements Cloneable {private String name;private int age;public Prototype(String name, int age) {this.name name;this.age age;}// 实现 clone 方法Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 使用 Object 类的 clone() 方法}// getter 和 setter 方法public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return Prototype{name name , age age };} }public class Main {public static void main(String[] args) {try {// 创建原型对象Prototype original new Prototype(John, 30);System.out.println(Original: original);// 通过克隆创建新对象Prototype cloned (Prototype) original.clone();System.out.println(Cloned: cloned);// 修改克隆对象的属性原型对象不受影响cloned.setName(Jane);cloned.setAge(25);System.out.println(Modified Cloned: cloned);System.out.println(Original after modification: original);} catch (CloneNotSupportedException e) {e.printStackTrace();}} }深拷贝与浅拷贝 在原型模式中深拷贝和浅拷贝是两个重要的概念 浅拷贝Shallow Copy复制对象时仅复制对象的基本类型字段和对引用类型的引用引用类型本身不会被复制。对于对象的嵌套对象它们指向的仍然是同一个内存地址。深拷贝Deep Copy不仅复制基本类型字段还会复制对象引用所指向的对象保证副本对象与原始对象完全独立。 保护性拷贝 原型模式中的保护性拷贝是一种用于只读或防止对象状态被修改的策略。通过返回一个对象的拷贝而不是返回对象的引用用户可以对这个拷贝进行操作但不会影响到原始对象的状态。 这种方式有效防止了原始对象的修改。例如某个系统中的对象需要在不同模块共享但不希望某些模块能够修改对象本身就可以返回对象的一个克隆副本。 public class Configuration implements Cloneable {private String configName; // 配置名称private int configValue; // 配置值public Configuration(String configName, int configValue) {this.configName configName;this.configValue configValue;}Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public String getConfigName() {return configName;}public int getConfigValue() {return configValue;} }public class Main {public static void main(String[] args) {try {Configuration config new Configuration(数据库配置, 100);// 获取配置对象的克隆副本Configuration configCopy (Configuration) config.clone();// 输出原始对象和克隆对象的配置名称System.out.println(原始配置名称: config.getConfigName());System.out.println(克隆配置名称: configCopy.getConfigName());// 修改克隆副本确保原始对象保持不变configCopy new Configuration(修改后的配置, 200);System.out.println(修改后的克隆配置名称: configCopy.getConfigName());System.out.println(原始配置值克隆修改后: config.getConfigValue());} catch (CloneNotSupportedException e) {e.printStackTrace(); // 捕获异常并输出错误信息}} }总结 原型模式的核心是克隆它可以快速复制现有对象避免重新构建复杂对象的开销。保护性拷贝是原型模式的一个重要用途能通过返回副本的方式有效防止对象状态被修改起到只读保护的作用。 工厂方法模式Factory Method Pattern 工厂模式主要包括三种不同的实现方式简单工厂模式、工厂方法模式和抽象工厂模式。 简单工厂模式 定义简单工厂模式不属于 GoF 设计模式它通过一个工厂类来创建对象。这个工厂类根据提供的信息决定创建哪个产品类的实例。 适用场合当只有一个工厂负责生产相同层次的产品如不同类型的披萨且产品类型固定不支持扩展时。 优缺点 优点简单易用适合小规模项目。缺点不利于扩展一旦需要增加产品类型必须修改工厂类。 结构 工厂类负责创建对象的逻辑。产品接口定义产品的共同特征。具体产品类实现产品接口。 public class SimpleFactory {public static Product createProduct(String type) {if (A.equals(type)) {return new ConcreteProductA();} else if (B.equals(type)) {return new ConcreteProductB();}return null;} }// 客户端使用 Product product SimpleFactory.createProduct(A);工厂方法模式 定义工厂方法模式通过定义一个用于创建对象的接口让子类决定实例化哪个类。工厂方法将类的实例化推迟到子类中。 适用场合当工厂可以有多个实现如伦敦工厂和纽约工厂且每个工厂生产固定类型的产品如三种披萨时。 优缺点 优点支持扩展可以轻松添加新工厂或产品类型。缺点增加了系统的复杂性需要为每种产品创建对应的工厂类。 结构 产品接口定义产品的共同特征。具体产品类实现产品接口。工厂接口定义创建产品的方法。具体工厂类实现工厂接口负责实例化具体产品。 public interface ProductFactory {Product createProduct(); }public class ConcreteFactoryA implements ProductFactory {Overridepublic Product createProduct() {return new ConcreteProductA();} }// 客户端使用 ProductFactory factory new ConcreteFactoryA(); Product product factory.createProduct();抽象工厂模式Abstract Factory Pattern 定义抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口而无需指定它们具体的类。适用于需要创建多个相关产品的场景。 适用场合当需要创建不同种类的产品如不同类型的披萨且这些产品之间可能存在关联时比如在增加了新的披萨类型如中式披萨的情况下。 优缺点 优点高度灵活支持扩展和变更便于管理不同产品族。缺点系统复杂性较高增加了类的数量。 结构 抽象工厂接口定义创建不同产品的方法。具体工厂类实现抽象工厂接口负责创建一系列相关产品。产品接口定义产品的共同特征。具体产品类实现产品接口。 public interface AbstractFactory {ProductA createProductA();ProductB createProductB(); }public class ConcreteFactory1 implements AbstractFactory {Overridepublic ProductA createProductA() {return new ConcreteProductA1();}Overridepublic ProductB createProductB() {return new ConcreteProductB1();} }// 客户端使用 AbstractFactory factory new ConcreteFactory1(); ProductA productA factory.createProductA(); ProductB productB factory.createProductB();总结对比 简单工厂模式适合小型、固定的产品需求。工厂方法模式适合多工厂、同类产品的需求支持扩展。抽象工厂模式适合多产品族的需求能够灵活管理不同类型的产品。 建造者模式Builder Pattern 定义建造者模式通过将对象的构建步骤逐一分离开来使得对象的创建过程更加灵活并且可以根据需要生成不同类型的对象。 结构 Builder建造者接口定义创建产品各个部分的接口。ConcreteBuilder具体建造者实现 Builder 接口负责构建产品的各个部分。Product产品要创建的复杂对象。Director指挥者控制建造者的构建过程按照一定的顺序构建产品。Client客户端通过 Director 与 Builder 进行交互来获取最终的产品对象。 产品类 // 产品类一个复杂对象 public class Product {private String partA;private String partB;private String partC;// Setter 方法public void setPartA(String partA) {this.partA partA;}public void setPartB(String partB) {this.partB partB;}public void setPartC(String partC) {this.partC partC;}Overridepublic String toString() {return Product [partA partA , partB partB , partC partC ];} }抽象建造者 // 建造者接口定义了构建产品的步骤 public interface Builder {void buildPartA();void buildPartB();void buildPartC();Product getResult(); }具体建造者 // 具体建造者实现了构建步骤 public class ConcreteBuilder implements Builder {private Product product new Product();Overridepublic void buildPartA() {product.setPartA(Part A);}Overridepublic void buildPartB() {product.setPartB(Part B);}Overridepublic void buildPartC() {product.setPartC(Part C);}Overridepublic Product getResult() {return product;} }指挥者 // 指挥者控制建造过程 public class Director {private Builder builder;public Director(Builder builder) {this.builder builder;}// 指定建造顺序public void construct() {builder.buildPartA();builder.buildPartB();builder.buildPartC();} }客户端 public class Main {public static void main(String[] args) {// 创建具体建造者Builder builder new ConcreteBuilder();// 创建指挥者并指挥建造过程Director director new Director(builder);director.construct();// 获取建造的产品Product product builder.getResult();System.out.println(product);} }使用场景 复杂对象的创建创建过程比较复杂且构建步骤需要灵活的控制。同样的构建过程生成不同产品可以在构建过程中通过不同的组合方式生成不同的对象。 建造者模式的优缺点 优点 更好的控制复杂对象的创建过程将复杂对象的构建过程拆分为多个步骤逐步构建。更好的扩展性通过不同的建造者可以生成不同类型的产品方便扩展。解耦客户端不需要知道产品的创建细节构造过程由建造者和指挥者协作完成。 缺点 增加代码复杂度需要额外创建 Builder 和 Director 类来管理对象的构建。使用场景有限适用于对象创建过程非常复杂的情况对于简单的对象可能不适合。 结构型模式7种 结构型模式涉及如何将类和对象组合成更大的结构以确保系统的功能能够高效扩展。 适配器模式Adapter Pattern 定义适配器模式通过定义一个适配器类将一个接口转化为客户端所期待的另一种接口。适配器模式通常用于两个接口不兼容的场景允许不兼容的类可以协同工作。 目标接口 // 目标接口 public interface Target {void request(); }源类  // 源类不兼容的接口 public class Adaptee {public void specificRequest() {System.out.println(执行源类的特定请求。);} }适配器类 // 适配器类实现目标接口并适配源类 public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee adaptee;}Overridepublic void request() {// 调用源类的方法adaptee.specificRequest();} }客户端 public class Main {public static void main(String[] args) {// 创建源类的实例Adaptee adaptee new Adaptee();// 使用适配器将源类适配为目标接口Target target new Adapter(adaptee);// 调用目标接口的方法target.request(); // 输出: 执行源类的特定请求。} }使用场景 接口不兼容需要将一个接口转换成另一个接口使得不同接口的类可以协作。旧代码的重用想要重用某个旧的类但该类的接口不符合新系统的需求时。多种接口的适配在同一个系统中需要适配多个类的接口。 适配器模式的优缺点 优点 提高了类的复用性可以通过适配器类来复用已有的类而不必修改原有代码。灵活性和可扩展性可以在不影响客户端的情况下方便地添加新适配器或修改现有的适配器。解耦合客户端与源类之间通过适配器进行解耦降低了系统的复杂性。 缺点 增加了系统的复杂性引入了适配器类增加了系统的复杂度特别是在适配器数量较多时。性能开销适配器模式可能会引入额外的性能开销因为需要通过适配器转发请求。 总结 适配器模式是一种有效的设计模式用于解决由于接口不兼容而导致的类之间无法协作的问题。通过适配器的引入可以在不改变现有类的情况下灵活地实现接口之间的适配和转换。 桥接模式Bridge Pattern 定义桥接模式将抽象与实现解耦客户端通过抽象接口与实现部分交互从而允许两者独立变化。它可以被认为是两个独立维度的扩展一个是抽象层次另一个是实现层次。 结构 Abstraction抽象类定义抽象部分的接口包含一个 Implementor 类型的引用。RefinedAbstraction扩展抽象类扩展抽象类维护实现部分的引用。Implementor实现类接口定义实现类的接口具体实现由具体的实现类来定义。ConcreteImplementor具体实现类具体实现 Implementor 接口完成具体的实现工作。 实现类接口 // 实现类接口 public interface Implementor {void operationImpl(); }具体实现类 // 具体实现类1 public class ConcreteImplementorA implements Implementor {Overridepublic void operationImpl() {System.out.println(具体实现 A 的操作。);} }// 具体实现类2 public class ConcreteImplementorB implements Implementor {Overridepublic void operationImpl() {System.out.println(具体实现 B 的操作。);} }抽象类 // 抽象类 public abstract class Abstraction {protected Implementor implementor;public Abstraction(Implementor implementor) {this.implementor implementor;}public abstract void operation(); }扩展抽象类 // 扩展抽象类 public class RefinedAbstraction extends Abstraction {public RefinedAbstraction(Implementor implementor) {super(implementor);}Overridepublic void operation() {System.out.println(扩展抽象类的操作。);implementor.operationImpl(); // 调用实现部分的操作} }客户端  public class Main {public static void main(String[] args) {// 使用具体实现AImplementor implementorA new ConcreteImplementorA();Abstraction abstractionA new RefinedAbstraction(implementorA);abstractionA.operation();// 使用具体实现BImplementor implementorB new ConcreteImplementorB();Abstraction abstractionB new RefinedAbstraction(implementorB);abstractionB.operation();} }桥接模式的优缺点 优点 分离抽象和实现可以独立地扩展抽象类和实现类避免它们之间的强耦合。提高系统的可扩展性在不修改原有系统的情况下可以扩展新的抽象和实现。遵循单一职责原则抽象类和实现类可以分别进行变化彼此不受影响。减少子类的数量通过组合关系代替继承关系避免创建大量的子类。 缺点 增加系统复杂性引入了更多的类和对象可能增加系统的复杂性。调试困难由于抽象与实现是分离的可能使调试变得更加复杂。 适用场景 需要跨越多个平台例如图形绘制程序抽象类可以表示“形状”而实现类可以表示“绘制API”不同的绘制API可以在不同的平台上使用。多个维度的变化系统需要面对多个维度的变化比如颜色、形状等不想通过继承来组合这些维度时可以采用桥接模式。避免继承爆炸如果使用继承会产生大量的子类且难以维护时可以使用桥接模式。 桥接模式与适配器模式的区别 桥接模式用于分离抽象与实现使它们可以独立变化强调的是系统内部的设计和扩展性。适配器模式用于将一个已有接口适配到另一个接口解决接口不兼容的问题主要用于系统之间的兼容。 总结 桥接模式通过将抽象与实现解耦使得系统更灵活适用于系统中多个维度都可能发生变化的场景。它可以有效地减少继承关系的数量避免继承导致的类层次复杂度但也会引入额外的类和对象增加了系统的设计复杂性。 装饰器模式Decorator Pattern 定义装饰器模式通过创建装饰类来包装原有的类被装饰的类并在保持原有类接口一致的情况下动态地为该类添加新的职责或功能。 结构 Component抽象组件定义一个接口表示可以动态添加职责的对象。ConcreteComponent具体组件实现 Component 接口表示一个具体的对象它将接受额外的职责。Decorator装饰类实现 Component 接口包含一个 Component 类型的成员变量负责将请求委派给该成员对象。ConcreteDecorator具体装饰类继承 Decorator为对象动态添加功能。 抽象组件 // 抽象组件接口 public interface Component {void operation(); }具体组件 // 具体组件实现抽象组件 public class ConcreteComponent implements Component {Overridepublic void operation() {System.out.println(执行基本操作。);} }装饰类 // 装饰类实现抽象组件接口并持有一个组件的引用 public class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component component;}Overridepublic void operation() {component.operation(); // 委派给具体组件} }具体装饰类 // 具体装饰类A扩展原有功能 public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}Overridepublic void operation() {super.operation(); // 执行原有操作addedBehaviorA(); // 添加新的功能}private void addedBehaviorA() {System.out.println(附加功能 A。);} }// 具体装饰类B扩展原有功能 public class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}Overridepublic void operation() {super.operation(); // 执行原有操作addedBehaviorB(); // 添加新的功能}private void addedBehaviorB() {System.out.println(附加功能 B。);} }客户端 public class Main {public static void main(String[] args) {// 创建具体组件Component component new ConcreteComponent();// 使用装饰器A来装饰具体组件Component decoratorA new ConcreteDecoratorA(component);// 再用装饰器B来装饰AComponent decoratorB new ConcreteDecoratorB(decoratorA);// 执行操作decoratorB.operation();} }装饰器模式的优缺点 优点 职责的动态扩展可以在运行时动态地为对象增加功能避免了使用继承带来的类爆炸问题。更灵活的功能组合可以通过不同的装饰器进行功能的组合满足不同的功能需求。遵循开闭原则无需修改现有的类结构就可以通过添加新的装饰器类来扩展功能。 缺点 生成大量的小对象每个装饰器都会创建一个新的对象这可能导致对象数量增多增加系统的复杂性。调试困难由于功能是通过多个装饰器类层层叠加的可能会增加调试和排错的难度。 适用场景 功能扩展希望在不修改原有类的情况下动态地为对象添加功能。功能灵活组合不同功能的组合需要灵活变化例如GUI组件的功能扩展日志系统的功能扩展。需要在运行时增加功能而不想通过静态继承关系进行扩展时可以使用装饰器模式。 总结 装饰器模式通过将对象包裹在装饰器类中动态地为对象添加新的职责。相比于继承装饰器模式更加灵活避免了因为继承导致的类爆炸问题适用于需要扩展对象功能的场景。然而它也会增加系统的复杂性特别是在装饰器类较多时。 组合模式Composite Pattern 定义组合模式通过将对象组合成树形结构使得客户端可以对单个对象和组合对象进行一致的处理。 结构 Component抽象组件为组合中的对象声明接口定义接口的默认行为。Leaf叶子组件实现 Component 接口表示树的叶子节点不再包含其他子节点。Composite组合对象实现 Component 接口表示一个容器对象包含子节点可以增加、删除子节点。Client客户端通过 Component 接口与组合结构进行交互。 抽象组件 // 抽象组件接口 public abstract class Component {protected String name;public Component(String name) {this.name name;}public abstract void operation();// 默认的添加、删除方法public void add(Component component) {throw new UnsupportedOperationException(不支持添加操作);}public void remove(Component component) {throw new UnsupportedOperationException(不支持删除操作);}public Component getChild(int index) {throw new UnsupportedOperationException(不支持获取子节点操作);} }叶子组件 // 叶子组件 public class Leaf extends Component {public Leaf(String name) {super(name);}Overridepublic void operation() {System.out.println(叶子节点 name 执行操作。);} }组合组件 // 组合组件 import java.util.ArrayList; import java.util.List;public class Composite extends Component {private ListComponent children new ArrayList();public Composite(String name) {super(name);}Overridepublic void operation() {System.out.println(组合节点 name 执行操作。);for (Component child : children) {child.operation(); // 递归调用子节点的操作}}Overridepublic void add(Component component) {children.add(component);}Overridepublic void remove(Component component) {children.remove(component);}Overridepublic Component getChild(int index) {return children.get(index);} }客户端 public class Main {public static void main(String[] args) {// 创建叶子节点Component leaf1 new Leaf(Leaf 1);Component leaf2 new Leaf(Leaf 2);Component leaf3 new Leaf(Leaf 3);// 创建组合节点Composite composite1 new Composite(Composite 1);Composite composite2 new Composite(Composite 2);// 组合节点添加子节点composite1.add(leaf1);composite1.add(leaf2);composite2.add(leaf3);composite2.add(composite1); // 组合节点中嵌套另一个组合节点// 执行操作composite2.operation();} }组合模式的优缺点 优点 统一处理客户端可以一致地处理单个对象和组合对象简化了对复杂树形结构的操作。更容易扩展通过组合可以灵活地增加新的叶子或组合对象无需修改现有代码。遵循开闭原则可以轻松添加新的组件或组合而无需修改现有代码。 缺点 设计复杂性增加如果系统中树的层次结构过于复杂可能会导致类的数量增多增加设计复杂性。不适合高层次和底层差异较大的场景组合模式的统一接口要求叶子和组合对象有一致的行为但如果叶子和组合对象的行为差异较大则可能会带来设计上的困难。 适用场景 树形结构如文件系统、组织结构、图形控件等具有明显的“部分-整体”层次关系。需要统一处理单个对象和组合对象客户不想关心是单个对象还是组合对象时可以使用组合模式。递归操作如图形界面的绘制可以递归遍历所有子节点进行渲染操作。 总结 组合模式是一种用于处理树形结构的设计模式它允许客户端一致地处理单个对象和组合对象使得系统可以灵活地进行扩展。在使用组合模式时要确保叶子节点和组合节点具有一致的接口这样可以使客户端不需要区分处理对象的类型。尽管组合模式简化了客户端的操作但它也可能引入一定的设计复杂性特别是在树形结构较为复杂的情况下。 外观模式Facade Pattern 定义外观模式通过创建一个简单的接口来隐藏系统内部的复杂性从而简化客户端与子系统的交互过程。 结构 Facade外观类提供一个简化的接口隐藏子系统的复杂性。Subsystems子系统类包含实际的业务逻辑或功能客户端通过外观类与它们交互但它们自己不需要知道外观类的存在。Client客户端通过外观类与子系统交互。 子系统类 // 子系统类1 public class SubsystemA {public void operationA() {System.out.println(子系统 A 的操作);} }// 子系统类2 public class SubsystemB {public void operationB() {System.out.println(子系统 B 的操作);} }// 子系统类3 public class SubsystemC {public void operationC() {System.out.println(子系统 C 的操作);} }外观类 // 外观类 public class Facade {private SubsystemA subsystemA;private SubsystemB subsystemB;private SubsystemC subsystemC;public Facade() {this.subsystemA new SubsystemA();this.subsystemB new SubsystemB();this.subsystemC new SubsystemC();}// 提供给客户端的统一接口public void operation() {subsystemA.operationA();subsystemB.operationB();subsystemC.operationC();} }客户端 public class Main {public static void main(String[] args) {// 创建外观类实例Facade facade new Facade();// 客户端通过外观类与子系统交互facade.operation();} }外观模式的优缺点 优点 简化客户端接口客户端只需要与外观类交互减少了与多个子系统之间的耦合使得代码更加简洁、易懂。松散耦合外观模式将客户端与复杂子系统解耦客户端只需关心外观类减少了系统的依赖。更好的分层可以将系统分层处理每一层都可以定义自己的外观类使得每个层次的实现细节被封装。 缺点 降低子系统的灵活性外观类可能会隐藏子系统的部分功能从而使客户端无法直接访问到一些功能。可能增加代码复杂性如果设计不当外观类可能会变得臃肿承担过多的职责反而增加系统的复杂性。 适用场景 简化子系统的使用当子系统包含多个复杂的接口外观模式通过统一接口简化它们的使用。系统分层可以在系统的不同层次上使用外观模式使得每层的实现细节对外部隐藏保持层次间的独立性。与遗留系统交互使用外观模式包装旧有的系统或库提供一个新接口使得客户端可以更方便地与旧系统交互。 外观模式与其他模式的对比 外观模式 vs. 适配器模式适配器模式是将一个接口转换为另一个接口而外观模式是提供一个统一的接口来简化多个接口的调用。外观模式 vs. 代理模式代理模式用于控制对象的访问而外观模式用于简化接口的使用。 总结 外观模式是一种用于简化系统与客户端交互的设计模式它通过提供一个简单的接口将复杂的子系统封装起来。通过外观模式客户端不需要了解子系统的内部实现降低了系统的复杂度和耦合度。在系统设计中外观模式可以很好地用于简化复杂子系统的操作尤其是在需要处理多个接口或子系统的情况下。 享元模式Flyweight Pattern 定义享元模式运用共享技术有效地支持大量细粒度对象的复用它通过将对象的内部状态和外部状态分离来共享相同的内部状态从而节省内存空间。 内部状态和外部状态 内部状态对象可以共享的状态不会随环境改变。内部状态通常由享元对象本身保存。 外部状态对象不可以共享的状态通常随着环境变化由客户端在使用享元对象时传递。 结构 Flyweight享元接口定义了对象的行为和接口通常包含操作外部状态的方法。ConcreteFlyweight具体享元类实现享元接口存储共享的内部状态。UnsharedConcreteFlyweight非共享享元类不被共享的类通常是复合对象持有多个享元对象。FlyweightFactory享元工厂类管理享元对象的创建和共享确保客户端获取的对象是共享的。Client客户端通过享元工厂获取享元对象并使用它们。 享元接口 // 享元接口 public interface Flyweight {void operation(String externalState); // 操作外部状态 }具体享元类 // 具体享元类 public class ConcreteFlyweight implements Flyweight {private final String intrinsicState; // 内部状态public ConcreteFlyweight(String intrinsicState) {this.intrinsicState intrinsicState;}Overridepublic void operation(String externalState) {System.out.println(内部状态: intrinsicState , 外部状态: externalState);} }享元工厂类 import java.util.HashMap; import java.util.Map;// 享元工厂类 public class FlyweightFactory {private MapString, Flyweight flyweights new HashMap();public Flyweight getFlyweight(String key) {if (!flyweights.containsKey(key)) {flyweights.put(key, new ConcreteFlyweight(key));}return flyweights.get(key);} }客户端 public class Main {public static void main(String[] args) {FlyweightFactory factory new FlyweightFactory();// 获取共享的享元对象Flyweight flyweight1 factory.getFlyweight(A);Flyweight flyweight2 factory.getFlyweight(A); // 共享对象Flyweight flyweight3 factory.getFlyweight(B);// 操作享元对象flyweight1.operation(First Call with A);flyweight2.operation(Second Call with A);flyweight3.operation(First Call with B);// 检查是否共享System.out.println(flyweight1 flyweight2); // 输出: true, 表示对象是共享的} }享元模式的优缺点 优点 节省内存通过共享相同的对象实例减少了大量相似对象的内存消耗。提升性能享元模式通过减少对象的数量提高了系统的运行性能。可扩展性当内部状态是可共享的而外部状态是由客户端维护时享元模式可以灵活处理大量对象。 缺点 增加复杂性享元模式要求将状态分为内部状态和外部状态导致代码复杂度上升尤其是在对象状态变化较多的情况下。外部状态管理复杂外部状态必须由客户端管理可能增加开发难度。 适用场景 大量相似对象在系统中存在大量相似对象的场景如字符处理、图形渲染、缓存等享元模式能有效减少内存消耗。需要共享的对象某些对象具有可以共享的部分状态享元模式通过提取这些共享部分使得系统更加高效。资源受限的场合如游戏开发中精灵、粒子系统等图形对象需要大量复用同样的模型。 享元模式的扩展 享元模式通常与对象池结合使用如线程池、数据库连接池等场景都是共享资源的典型应用场景。享元模式可以看作是对象池的一种特殊形式强调共享内部状态。 享元模式与其他模式的关系 与单例模式单例模式保证一个类仅有一个实例而享元模式则允许多个相同实例共享。与工厂模式享元模式通常通过工厂模式获取共享对象工厂负责创建和维护享元对象的缓存。 总结 享元模式是一种通过共享相似对象来减少内存消耗的设计模式特别适用于需要大量细粒度对象的场景。它通过将对象的状态分为可共享的内部状态和依赖环境的外部状态减少了对象实例的重复创建。在实际应用中享元模式广泛应用于需要优化性能和内存使用的系统中如缓存机制、字符处理系统、图形渲染系统等。 代理模式Proxy Pattern 定义代理模式为其他对象提供一种代理以控制对该对象的访问。代理模式通常用于延迟对象的加载、提供额外的访问控制或者在实际对象不可用时提供一个替代品。 结构 Subject抽象主题类定义代理类和真实主题类的公共接口确保代理类和真实类可以互换。RealSubject真实主题类代理类所代表的实际对象包含业务逻辑。Proxy代理类代理类包含对真实主题类的引用并通过该引用控制对真实对象的访问可以添加额外的功能或限制。 抽象主题类 // 抽象主题类 public interface Subject {void request(); }真实主题类 // 真实主题类 public class RealSubject implements Subject {Overridepublic void request() {System.out.println(真实对象的请求处理);} }代理类 // 代理类 public class Proxy implements Subject {private RealSubject realSubject;Overridepublic void request() {// 在这里可以添加额外的操作如权限控制、日志记录等if (realSubject null) {realSubject new RealSubject(); // 延迟加载}System.out.println(代理对象处理一些前置任务);realSubject.request(); // 调用真实对象的方法System.out.println(代理对象处理一些后置任务);} }客户端 public class Main {public static void main(String[] args) {// 使用代理对象Subject proxy new Proxy();proxy.request();} }代理模式的类型 静态代理代理类在编译时确定代理类需要实现与真实类相同的接口。动态代理代理类在运行时生成通常通过反射机制在运行时处理接口的实现。虚拟代理用于对象的懒加载只有在需要时才创建对象。保护代理控制对象的访问权限确保不同的用户角色有不同的访问权限。远程代理为位于不同地址空间的对象提供本地代表用于分布式系统中。 代理模式的优缺点 优点 控制访问代理模式可以控制对目标对象的访问可以通过代理类进行权限控制、日志记录等操作。延迟加载可以在需要时才创建真实对象减少不必要的开销优化资源使用。增强功能代理模式可以在不修改真实类的情况下增强类的功能比如添加缓存、日志或安全检查。 缺点 增加复杂性代理模式会引入额外的对象层次增加系统的复杂性特别是在过度使用时可能导致维护困难。性能开销虽然代理模式可以延迟对象的加载但每次调用都需要经过代理类可能引入一定的性能开销。 适用场景 远程代理在分布式系统中代理对象代表位于不同地址空间的远程对象如RPC远程过程调用。虚拟代理用于延迟加载对象只有在需要时才真正创建对象如懒加载。保护代理在需要权限控制或访问控制的场景中代理对象可以限制客户端的访问权限。智能引用代理对象可以在访问目标对象时加入额外的行为如引用计数、日志记录等。 扩展 1. 动态代理 动态代理通过反射机制在运行时创建代理对象。Java 提供了java.lang.reflect.Proxy类允许在运行时动态创建代理类。 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;// 动态代理处理器 public class DynamicProxyHandler implements InvocationHandler {private Object realObject;public DynamicProxyHandler(Object realObject) {this.realObject realObject;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(动态代理: 前置处理);Object result method.invoke(realObject, args);System.out.println(动态代理: 后置处理);return result;} }// 客户端使用动态代理 public class Main {public static void main(String[] args) {RealSubject realSubject new RealSubject();Subject proxyInstance (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new DynamicProxyHandler(realSubject));proxyInstance.request();} }2. 静态代理与动态代理的对比 静态代理代理类在编译时生成必须手动为每个具体类编写代理类。优点是可以定制化每个代理类的行为但缺点是需要为每个类编写代码增加了代码冗余。动态代理代理类在运行时动态生成减少了编写代理类的代码量灵活性较强尤其适合场景变化较多的情况。 总结 代理模式是一种常用的设计模式它通过引入代理对象控制对目标对象的访问可以用于延迟加载、权限控制、日志记录等场景。代理模式的主要优势在于可以在不改变目标对象的前提下增强或控制其行为但也会增加系统的复杂性。代理模式在实际开发中被广泛应用如远程代理、虚拟代理、保护代理等尤其在分布式系统、资源受限系统中表现尤为突出。 装饰器模式与代理模式的区别 装饰器模式用于动态为对象增加功能强调对功能的扩展。代理模式用于控制对对象的访问强调对对象的控制和保护常用于延迟加载、安全检查等场景。 行为型模式12种 行为型模式关注对象之间的责任分配处理对象间的交互和职责划分。 策略模式Strategy Pattern 定义策略模式将算法的定义和使用分开允许在运行时动态选择或替换算法使得不同的算法可以独立于使用它的客户端进行变化。 结构 Context上下文类维护一个对 Strategy 对象的引用。客户端通过 Context 使用策略。Strategy策略接口定义了算法的公共接口具体策略类会实现这个接口。ConcreteStrategy具体策略类实现 Strategy 接口提供具体的算法实现。 策略接口 // 策略接口 public interface Strategy {int doOperation(int num1, int num2); }具体策略类 // 具体策略类加法策略 public class OperationAdd implements Strategy {Overridepublic int doOperation(int num1, int num2) {return num1 num2;} }// 具体策略类减法策略 public class OperationSubtract implements Strategy {Overridepublic int doOperation(int num1, int num2) {return num1 - num2;} }// 具体策略类乘法策略 public class OperationMultiply implements Strategy {Overridepublic int doOperation(int num1, int num2) {return num1 * num2;} }上下文类 // 上下文类持有策略的引用 public class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy strategy;}public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);} }客户端  public class Main {public static void main(String[] args) {// 使用加法策略Context context new Context(new OperationAdd());System.out.println(10 5 context.executeStrategy(10, 5));// 使用减法策略context new Context(new OperationSubtract());System.out.println(10 - 5 context.executeStrategy(10, 5));// 使用乘法策略context new Context(new OperationMultiply());System.out.println(10 * 5 context.executeStrategy(10, 5));} }策略模式的优缺点 优点 遵循开闭原则可以在不修改现有代码的情况下添加新的策略实现算法的动态扩展。消除条件语句通过将算法封装到独立的策略类中避免了大量的条件语句。提高代码的可读性和可维护性每个策略类只负责一种算法职责单一代码清晰。可互换的策略不同的策略类可以动态切换提升了系统的灵活性。 缺点 增加了对象数量每个策略都是一个单独的类可能导致类的数量增多增加了系统的复杂性。客户端必须了解策略客户端需要知道每个策略的区别并根据场景选择合适的策略。 适用场景 多种算法在某些场景下存在多个算法可以解决同一个问题比如排序算法、支付方式等策略模式可以帮助动态选择合适的算法。算法易变如果算法经常发生变化策略模式可以使变化更加灵活减少对使用场景的影响。避免条件判断当代码中有大量的 if-else 或 switch-case 语句选择算法时策略模式是很好的解决方案。 策略模式的扩展 策略模式可以结合其他模式使用特别是与工厂模式结合。工厂模式可以用来创建具体的策略对象从而实现策略的动态选择。 示例结合工厂模式 // 策略工厂类用于动态创建策略 public class StrategyFactory {public static Strategy getStrategy(String type) {switch (type) {case add:return new OperationAdd();case subtract:return new OperationSubtract();case multiply:return new OperationMultiply();default:throw new IllegalArgumentException(Unknown strategy type);}} }客户端 public class Main {public static void main(String[] args) {// 通过工厂模式动态获取策略Context context new Context(StrategyFactory.getStrategy(add));System.out.println(10 5 context.executeStrategy(10, 5));context new Context(StrategyFactory.getStrategy(subtract));System.out.println(10 - 5 context.executeStrategy(10, 5));context new Context(StrategyFactory.getStrategy(multiply));System.out.println(10 * 5 context.executeStrategy(10, 5));} }策略模式与其他模式的关系 策略模式 vs 状态模式策略模式的主要目的是让算法可以互换而状态模式的目的是根据对象的状态来改变行为。两者的实现结构类似但意图不同。策略模式 vs 模板方法模式模板方法模式通过继承来决定算法的具体实现而策略模式通过组合来实现算法的动态选择策略模式比模板方法模式更灵活。策略模式 vs 装饰器模式装饰器模式用于动态增强对象的功能而策略模式用于动态选择算法。 总结 策略模式通过将算法封装到不同的策略类中允许算法在运行时动态切换消除了条件语句的使用符合开闭原则。在实际应用中策略模式被广泛用于解决具有多种算法选择或动态变化需求的场景如支付系统、折扣策略、排序算法等。策略模式的灵活性使得系统能够轻松应对算法的变化和扩展。 模板方法模式Template Method Pattern 定义模板方法模式是一种通过定义一个抽象方法或钩子方法让子类去实现这些具体细节确保算法的框架不变。这样做的好处是提高代码复用性子类可以通过复写某些方法实现不同的行为。 结构 AbstractClass抽象类定义了算法的骨架包含模板方法以及具体步骤或抽象步骤的定义。ConcreteClass具体类实现了抽象类中的抽象步骤或者覆写钩子方法。 抽象类定义算法骨架 // 抽象类定义了算法的骨架 public abstract class Game {// 模板方法定义算法的步骤final 以防止子类改变整体流程public final void play() {initialize();startPlay();endPlay();}// 抽象方法子类实现这些具体步骤protected abstract void initialize();protected abstract void startPlay();protected abstract void endPlay(); }具体类实现算法的某些步骤 // 具体类1实现具体步骤 public class Football extends Game {Overrideprotected void initialize() {System.out.println(足球游戏初始化);}Overrideprotected void startPlay() {System.out.println(足球游戏开始);}Overrideprotected void endPlay() {System.out.println(足球游戏结束);} }// 具体类2实现不同的步骤 public class Basketball extends Game {Overrideprotected void initialize() {System.out.println(篮球游戏初始化);}Overrideprotected void startPlay() {System.out.println(篮球游戏开始);}Overrideprotected void endPlay() {System.out.println(篮球游戏结束);} }客户端  public class Main {public static void main(String[] args) {Game footballGame new Football();footballGame.play(); // 执行足球游戏的模板方法System.out.println();Game basketballGame new Basketball();basketballGame.play(); // 执行篮球游戏的模板方法} }模板方法模式的关键点 模板方法模板方法是算法的骨架它是一个具体方法并且通常声明为 final以防止子类修改算法的顺序。具体步骤方法一些步骤在模板方法中已经实现它们在父类中定义可以由所有子类共享。抽象步骤方法一些步骤被声明为抽象方法强制子类去实现具体的逻辑。钩子方法钩子方法是子类可以选择性地覆盖的方法它在父类中提供默认实现子类可以根据需要进行扩展。 优缺点 优点 代码复用将不变的部分实现放在父类中而将可变的部分交给子类实现了代码的复用。灵活性强子类可以通过扩展具体步骤或者钩子方法来实现不同的行为增强了灵活性。符合开闭原则可以通过添加新的子类来扩展新的行为而不需要修改已有的代码。 缺点 继承带来的局限子类必须继承抽象类使用继承机制会限制类的灵活性过多的层次继承可能导致复杂性增加。子类实现增加每个子类都需要实现父类中定义的抽象方法当子类较多时可能导致代码臃肿。 适用场景 框架搭建当构建一个框架时可以使用模板方法模式将通用的流程定义在父类中允许框架的使用者根据需要扩展具体的行为。多种操作流程的变体比如游戏中的初始化、开始、结束操作相似但细节有所不同时可以使用模板方法模式。复用公共逻辑如果多个类的行为大致相同只有少量步骤不同模板方法可以有效地将相同逻辑复用。 钩子方法 钩子方法是模板方法模式中的一个重要概念。它允许子类有机会在算法的关键步骤中加入或修改行为而不必强制子类实现这些方法。钩子方法在父类中提供一个默认的空实现子类可以根据需要选择性地重写钩子方法。 public abstract class Game {public final void play() {initialize();startPlay();if (isHalfTime()) { // 钩子方法halfTime();}endPlay();}protected abstract void initialize();protected abstract void startPlay();protected abstract void endPlay();// 钩子方法子类可覆盖protected boolean isHalfTime() {return false;}// 默认空实现子类可选择性实现protected void halfTime() {System.out.println(中场休息);} }客户端 public class Football extends Game {Overrideprotected void initialize() {System.out.println(足球游戏初始化);}Overrideprotected void startPlay() {System.out.println(足球游戏开始);}Overrideprotected void endPlay() {System.out.println(足球游戏结束);}Overrideprotected boolean isHalfTime() {return true; // 足球比赛有中场休息}Overrideprotected void halfTime() {System.out.println(足球比赛中场休息);} }public class Main {public static void main(String[] args) {Game footballGame new Football();footballGame.play(); // 调用带有钩子方法的模板方法} }抽象类定义算法骨架模板方法模式的扩展 模板方法模式可以和其他模式结合使用如 工厂方法模式可以在模板方法中调用工厂方法以动态创建某些步骤中的对象。策略模式在模板方法模式中可以通过策略模式动态选择某些步骤的实现方式。 总结 模板方法模式是一种有效的代码复用和算法控制手段通过在父类中定义算法的骨架子类可以灵活地实现或修改算法的某些步骤。它可以减少代码的重复实现逻辑的复用同时允许不同的子类对算法的部分步骤进行定制或扩展。模板方法模式非常适合处理具有固定流程但细节可能不同的场景比如游戏流程、数据处理流程等。 观察者模式Observer Pattern 定义观察者模式允许对象之间建立一种松耦合的关系。被观察的对象称为主题Subject它维护一个观察者Observer列表。当主题的状态发生变化时主题会通知所有注册的观察者进行相应的更新。 角色 Subject主题被观察者维护观察者列表并提供注册、取消注册和通知的功能。Observer观察者订阅主题的对象一旦主题的状态发生改变观察者会接收到通知并执行更新操作。ConcreteSubject具体主题主题的具体实现维护观察者并在状态改变时调用通知方法。ConcreteObserver具体观察者观察者的具体实现定义如何在收到通知时做出响应。 定义观察者接口 // 观察者接口定义更新操作 public interface Observer {void update(String message); }定义主题接口 // 主题接口定义注册、移除观察者以及通知操作 public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers(); }具体主题类 import java.util.ArrayList; import java.util.List;// 具体主题类 public class ConcreteSubject implements Subject {private ListObserver observers new ArrayList();private String message; // 被观察的状态Overridepublic void attach(Observer observer) {observers.add(observer);}Overridepublic void detach(Observer observer) {observers.remove(observer);}Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(message);}}// 更新状态并通知所有观察者public void setMessage(String message) {this.message message;notifyObservers();} }具体观察者类 // 具体观察者类实现更新逻辑 public class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name name;}Overridepublic void update(String message) {System.out.println(name 收到消息: message);} }客户端 public class Main {public static void main(String[] args) {ConcreteSubject subject new ConcreteSubject();// 创建两个观察者Observer observer1 new ConcreteObserver(Observer 1);Observer observer2 new ConcreteObserver(Observer 2);// 注册观察者subject.attach(observer1);subject.attach(observer2);// 更新状态并通知观察者subject.setMessage(Hello Observers!);// 移除一个观察者subject.detach(observer1);// 更新状态并通知剩下的观察者subject.setMessage(Another update!);} }观察者模式的关键点 注册与取消注册观察者可以动态地注册或取消注册控制是否接收主题的通知。松耦合观察者与主题之间是松耦合的主题并不关心观察者的具体实现只通过抽象接口通知。通知机制一旦主题的状态发生改变它会自动通知所有已注册的观察者使得观察者能够响应变化。 优缺点 优点 松耦合观察者和主题之间是松耦合的它们彼此不知道对方的具体实现符合开闭原则。动态联动观察者可以随时注册或取消注册允许在运行时动态修改依赖关系。可扩展性强可以轻松地添加新的观察者而不需要修改现有的代码。 缺点 过度通知如果观察者数量过多频繁的状态更新可能导致系统开销增加。通知顺序由于观察者的通知顺序不确定可能会导致某些业务场景中的执行顺序问题。内存泄漏如果观察者没有正确移除注册可能会导致内存泄漏。 使用场景 事件驱动系统在事件驱动架构中观察者模式广泛用于通知事件监听器处理事件比如GUI编程中的按钮点击、网络编程中的消息传递。模型-视图联动在MVC架构中观察者模式常用于视图与模型的同步更新模型发生变化时视图能够自动更新。消息广播系统可以将观察者模式用于消息发布订阅系统多个订阅者同时接收一个发布者的消息。 与发布-订阅模式的区别 观察者模式和发布-订阅模式的核心思想类似但在实现上有所不同 直接通知观察者模式是主题直接通知观察者观察者主动接收通知而发布-订阅模式通常通过一个中间件如消息队列来解耦发布者和订阅者。灵活性发布-订阅模式更灵活因为它允许多个系统通过中间代理进行通信而观察者模式更适合单个应用程序内部的对象间联动。 扩展 观察者模式可以与其他模式结合使用 装饰器模式可以使用装饰器来增强某些观察者的功能。策略模式可以为不同的观察者提供不同的策略以动态改变观察者的行为。单例模式如果某个主题是系统全局唯一的可以结合单例模式实现。 总结 观察者模式提供了一种非常灵活的机制来实现对象之间的联动关系尤其适合在状态变化需要通知其他对象时使用。通过定义主题和观察者的抽象接口观察者模式使得系统更具扩展性同时保持了松耦合的特性。 迭代器模式Iterator Pattern 定义迭代器模式定义了一个迭代器接口这个接口包含了遍历集合元素所需的方法。具体集合对象提供实现了该接口的迭代器这样就可以通过迭代器遍历集合中的元素而无需知道集合的底层实现方式。 角色 Iterator迭代器接口定义访问和遍历元素的方法例如hasNext()和next()。ConcreteIterator具体迭代器实现迭代器接口负责遍历集合中的元素。Aggregate聚合接口定义创建迭代器的方法例如createIterator()。ConcreteAggregate具体聚合类实现聚合接口创建具体的迭代器对象。 定义迭代器接口 // 迭代器接口定义遍历方法 public interface Iterator {boolean hasNext();Object next(); }定义聚合接口 // 聚合接口定义创建迭代器的方法 public interface Aggregate {Iterator createIterator(); }具体迭代器类 // 具体迭代器类遍历聚合对象 public class ConcreteIterator implements Iterator {private String[] items;private int position 0;public ConcreteIterator(String[] items) {this.items items;}Overridepublic boolean hasNext() {return position items.length;}Overridepublic Object next() {if (hasNext()) {return items[position];}return null;} }具体聚合类 // 具体聚合类实现创建迭代器的方法 public class ConcreteAggregate implements Aggregate {private String[] items;public ConcreteAggregate(String[] items) {this.items items;}Overridepublic Iterator createIterator() {return new ConcreteIterator(items);} }客户端 public class Main {public static void main(String[] args) {String[] items {Item 1, Item 2, Item 3, Item 4};Aggregate aggregate new ConcreteAggregate(items);Iterator iterator aggregate.createIterator();// 使用迭代器遍历元素while (iterator.hasNext()) {System.out.println(iterator.next());}} }迭代器模式的关键点 封装迭代逻辑迭代器封装了遍历的逻辑客户端通过迭代器接口与集合对象交互而不需要关心集合的内部结构。统一接口无论集合类型如何数组、列表等通过迭代器接口客户端可以以相同的方式遍历集合对象中的元素。多样化迭代不同的集合可以有不同的迭代器实现支持不同的遍历方式顺序遍历、反向遍历等。 优缺点 优点 简化客户端代码客户端不需要直接与集合的内部结构打交道只需要通过迭代器接口访问集合中的元素简化了代码。统一遍历方式通过统一的接口遍历不同的集合对象方便扩展和维护。支持不同遍历方式可以根据需要自定义不同的迭代器实现不同的遍历方式。 缺点 开销增加对于较大的集合创建迭代器可能会有一定的开销尤其是在需要频繁创建迭代器的情况下。对集合对象的修改不敏感如果在迭代的过程中集合对象发生了修改可能会导致迭代器失效或产生不一致的结果。 使用场景 遍历集合当需要遍历复杂的数据结构如树、图、链表等时迭代器模式可以提供统一的访问接口。对集合对象解耦当集合的内部结构复杂、但需要对外提供简洁的遍历方式时迭代器模式能很好地将内部结构与客户端解耦。需要多种遍历方式当同一个集合可能需要不同的遍历方式例如正序遍历、倒序遍历、跳跃遍历等可以通过不同的迭代器实现这些遍历。 扩展 Java 内置迭代器Java 集合框架已经实现了迭代器模式所有的集合类都提供了Iterator接口的实现。例如ArrayList、HashSet、HashMap等类都可以通过iterator()方法返回一个迭代器。 ListString list new ArrayList(); list.add(A); list.add(B); list.add(C);IteratorString iterator list.iterator(); while (iterator.hasNext()) {System.out.println(iterator.next()); }多种迭代方式可以通过自定义多个具体迭代器来实现不同的遍历策略。例如正序遍历、倒序遍历等。 总结 迭代器模式为集合对象的遍历提供了一种统一的接口极大地简化了遍历逻辑并且将遍历操作与集合的具体实现分离。通过迭代器集合的内部结构对客户端透明既增强了系统的灵活性又使得代码更易于维护。 责任链模式Chain of Responsibility Pattern 定义责任链模式的核心思想是将请求的处理者串联起来形成一条链式的结构依次传递请求。每个处理者都包含对下一个处理者的引用当一个处理者无法处理请求时传递给下一个处理者直到找到能够处理请求的对象为止。 角色 Handler处理者定义处理请求的接口并包含一个对下一个处理者的引用。ConcreteHandler具体处理者继承处理者接口负责处理它所擅长的请求。如果不能处理则将请求传递给下一个处理者。Client客户端创建处理链并将请求发送给第一个处理者。 定义处理者接口 // 处理者接口定义处理请求的抽象方法 public abstract class Handler {protected Handler nextHandler;// 设置下一个处理者public void setNextHandler(Handler nextHandler) {this.nextHandler nextHandler;}// 处理请求的抽象方法public abstract void handleRequest(String request); }具体处理者 // 具体处理者1处理特定类型的请求 public class ConcreteHandler1 extends Handler {Overridepublic void handleRequest(String request) {if (request.equals(Request1)) {System.out.println(ConcreteHandler1 处理了 request);} else if (nextHandler ! null) {nextHandler.handleRequest(request);}} }// 具体处理者2处理其他类型的请求 public class ConcreteHandler2 extends Handler {Overridepublic void handleRequest(String request) {if (request.equals(Request2)) {System.out.println(ConcreteHandler2 处理了 request);} else if (nextHandler ! null) {nextHandler.handleRequest(request);}} }客户端 public class Main {public static void main(String[] args) {// 创建处理者Handler handler1 new ConcreteHandler1();Handler handler2 new ConcreteHandler2();// 设置责任链handler1.setNextHandler(handler2);// 发送请求handler1.handleRequest(Request1);handler1.handleRequest(Request2);handler1.handleRequest(UnknownRequest);} }责任链模式的关键点 请求传递请求沿着链条依次传递直到某个处理者处理该请求或者到达链条的末端。如果没有处理者能处理请求通常可以设计默认的处理机制。解耦请求的发送者和处理者责任链模式将请求的发送者和实际处理者解耦发送者无需知道是哪一个处理者处理了请求增加了系统的灵活性。灵活的扩展可以动态地增加或修改处理者的链条结构符合“开闭原则”OCP对扩展开放对修改封闭。 优缺点 优点 降低耦合发送者不需要明确指定接收者多个对象可以协作处理请求。动态组合处理者处理者链可以根据需要动态地组织和重组灵活性较高。符合职责分离原则每个处理者只关心自己能处理的请求其余的交给链条上的下一个处理者。 缺点 请求处理不保证如果链条末端没有处理请求的能力可能会导致请求被忽略或处理不完整。调试困难由于请求的传递是链式的可能会增加调试和排错的难度尤其是链条很长时。 适用场景 多种请求处理当系统中有多种请求需要处理而请求的处理者可能不唯一时适合使用责任链模式。动态组织请求处理者当处理者的顺序或种类需要灵活变化时可以使用责任链模式。权限校验、日志记录等常见的场景包括权限校验、日志记录等功能这些操作通常需要串联处理。 实际应用 Java 过滤器链Servlet 的过滤器Filter机制就使用了责任链模式。多个过滤器按照链式结构依次处理请求。异常处理机制在一些编程语言中异常处理也可以使用责任链模式。多个异常处理器可以链式处理异常直到找到匹配的异常处理器。 扩展 双向链表在某些场景下可以扩展为双向责任链使得请求可以向前或向后传递。组合模式与责任链模式结合有时责任链中的某些节点本身也可以是一个组合结构例如某个处理者可以包含一组子处理者它们内部形成一个小责任链。 总结 责任链模式通过将请求处理者串联起来降低了发送者与接收者之间的耦合度并且可以动态地扩展和修改处理链。它特别适合用于需要多个对象处理请求的场景增强了系统的灵活性和可扩展性。然而由于链式结构调试和维护可能变得稍微复杂。 命令模式Command Pattern 定义命令模式的核心是将一个动作或操作封装为一个对象。这个对象包含了执行该操作所需的信息包括操作的接收者和执行的参数。通过这种方式命令对象可以被传递、存储和执行。 角色 Command命令接口定义一个执行操作的接口。ConcreteCommand具体命令实现命令接口定义与接收者之间的绑定调用接收者相应的操作。Receiver接收者具体的业务逻辑类负责实际执行命令。Invoker调用者持有命令对象并调用其执行方法。Client客户端创建具体命令对象并设置其接收者。 定义命令接口 // 命令接口定义执行操作的方法 public interface Command {void execute(); }具体命令类 // 具体命令类封装请求 public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light light;}Overridepublic void execute() {light.turnOn();} }public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light light;}Overridepublic void execute() {light.turnOff();} }接收者 // 接收者类执行具体操作 public class Light {public void turnOn() {System.out.println(Light is ON);}public void turnOff() {System.out.println(Light is OFF);} }调用者 // 调用者类持有命令对象并调用执行方法 public class RemoteControl {private Command command;public void setCommand(Command command) {this.command command;}public void pressButton() {command.execute();} }客户端 public class Main {public static void main(String[] args) {Light light new Light();Command lightOn new LightOnCommand(light);Command lightOff new LightOffCommand(light);RemoteControl remote new RemoteControl();// 开灯remote.setCommand(lightOn);remote.pressButton();// 关灯remote.setCommand(lightOff);remote.pressButton();} }命令模式的关键点 请求封装通过将请求封装为命令对象可以灵活地处理请求包括队列、记录和撤销等操作。解耦请求的发送者与接收者之间解耦发送者只需要知道命令对象而无需知道具体的接收者。扩展性可以通过添加新的命令类来扩展功能无需修改现有代码符合开闭原则。 优缺点 优点 解耦请求者和接收者请求者无需了解请求的具体处理过程只需调用命令对象。支持撤销和重做可以通过保存命令对象的状态实现命令的撤销和重做。可扩展性强添加新命令时无需更改现有代码符合开闭原则。 缺点 命令对象增多随着命令的增加可能导致命令对象数量激增增加系统的复杂性。对命令的管理需要对命令对象进行有效管理否则可能导致混乱。 适用场景 需要支持撤销/重做操作例如在图形编辑器中用户可以撤销或重做上一步操作。需要记录操作日志可以将命令对象存储到日志中以便后续查看。构建简单的宏命令将多个命令组合成一个命令通过调用单个命令执行一系列操作。 实际应用 图形用户界面GUI例如按钮点击事件、菜单项选择等都可以使用命令模式实现。事务管理可以通过命令模式实现对事务的管理确保数据的一致性。远程控制在智能家居系统中通过命令模式实现远程控制设备的开关。 总结 命令模式通过将请求封装为对象解耦请求的发送者与接收者增强了系统的灵活性和可扩展性。适用于需要记录、撤销或重做操作的场景能够提高代码的可维护性与可读性。尽管可能导致命令类数量增加但其带来的灵活性和扩展性是非常值得的。 备忘录模式Memento Pattern 定义备忘录模式的核心在于提供一个可以保存对象状态的备忘录对象以及一个可以恢复对象状态的发起人。发起人可以在不违反封装原则的情况下将其状态保存到备忘录中。 角色 Originator发起人创建一个备忘录记录当前状态并可以根据备忘录恢复状态。Memento备忘录保存发起人的内部状态可以被发起人和外部对象访问。Caretaker管理者管理备忘录对象负责保存和恢复备忘录但不允许访问备忘录的内容。 定义备忘录类 // 备忘录类保存发起人的状态 public class Memento {private String state;public Memento(String state) {this.state state;}public String getState() {return state;} }定义发起人类 // 发起人类负责创建和恢复备忘录 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 restore(Memento memento) {this.state memento.getState();} }定义管理者类 // 管理者类负责备忘录的保存和恢复 import java.util.ArrayList; import java.util.List;public class Caretaker {private ListMemento mementoList new ArrayList();public void save(Originator originator) {mementoList.add(originator.createMemento());}public void restore(Originator originator, int index) {if (index mementoList.size()) {originator.restore(mementoList.get(index));}} }客户端 public class Main {public static void main(String[] args) {Originator originator new Originator();Caretaker caretaker new Caretaker();originator.setState(State 1);caretaker.save(originator);originator.setState(State 2);caretaker.save(originator);originator.setState(State 3);System.out.println(Current State: originator.getState());// 恢复到之前的状态caretaker.restore(originator, 0);System.out.println(Restored State: originator.getState());caretaker.restore(originator, 1);System.out.println(Restored State: originator.getState());} }备忘录模式的关键点 封装性备忘录模式提供了对内部状态的封装外部对象不能直接访问发起人的内部状态。状态恢复可以在需要的时候方便地恢复到某个之前的状态支持历史版本的管理。管理者的角色管理者负责管理多个备忘录能够灵活地保存和恢复状态。 优缺点 优点 保护内部状态不暴露发起人的内部状态维护了对象的封装性。简化恢复操作提供简单的接口来恢复对象的状态方便使用。灵活性可以灵活地保存和恢复多个状态适合需要历史记录的场景。 缺点 内存消耗如果对象状态较复杂且变化频繁可能会消耗大量内存存储多个备忘录。备忘录管理需要有效管理备忘录的生命周期以防止内存泄漏。 适用场景 需要实现撤销操作的应用如文本编辑器、图形编辑器等需要保存历史状态以便用户撤销操作。版本控制管理对象的多个版本支持状态恢复和比较。复杂状态的保存在游戏、模拟器等复杂状态管理中备忘录模式能够方便地保存和恢复状态。 实际应用 图形编辑器在图形编辑软件中用户的操作可以被记录用户可以随时撤销或恢复到某个状态。文本编辑器文本编辑器可以在用户编辑文本时记录每个版本以便用户随时回退。游戏状态游戏中的玩家状态可以被保存以便在游戏中断后恢复。 总结 备忘录模式通过提供一个保存和恢复对象状态的机制增强了系统的灵活性和可维护性。它适用于需要历史记录和撤销操作的场景能够有效地管理对象状态同时保持对象的封装性。尽管可能带来内存消耗的问题但其带来的便利性通常是值得的。 状态模式State Pattern 定义状态模式的核心思想是将对象的状态封装成独立的类并通过状态对象来控制对象的行为。每个状态类实现了相同的接口代表对象在该状态下的行为。 角色 Context上下文维护一个对具体状态对象的引用并在需要时改变状态。State状态接口定义一个接口表示状态所应具备的行为。ConcreteState具体状态类实现状态接口定义在该状态下的具体行为。 定义状态接口 // 状态接口定义状态的行为 public interface State {void handle(); }具体状态类 // 具体状态类A public class ConcreteStateA implements State {Overridepublic void handle() {System.out.println(Handling request in State A);} }// 具体状态类B public class ConcreteStateB implements State {Overridepublic void handle() {System.out.println(Handling request in State B);} }上下文类 // 上下文类维护当前状态 public class Context {private State state;public void setState(State state) {this.state state;}public void request() {state.handle();} }客户端 public class Main {public static void main(String[] args) {Context context new Context();// 设置状态为A并执行请求context.setState(new ConcreteStateA());context.request();// 改变状态为B并执行请求context.setState(new ConcreteStateB());context.request();} }状态模式的关键点 状态封装每个状态的行为被封装在独立的状态类中减少了条件语句的使用使代码更清晰。状态切换上下文可以根据需要动态改变状态状态的改变不影响上下文的其他功能。行为动态变化对象的行为可以随其状态的变化而变化符合“开放/封闭原则”。 优缺点 优点 提高可维护性通过将状态行为封装在独立类中减少了条件判断提高了代码的可读性和可维护性。易于扩展添加新状态时只需新增状态类而无需修改现有代码符合开闭原则。明确的状态管理状态与行为的对应关系明确使得状态管理更加清晰。 缺点 类的数量增加每个状态都需要创建一个类可能导致类的数量激增增加系统的复杂性。状态切换复杂如果状态之间有复杂的切换逻辑可能会使得状态管理变得复杂。 适用场景 对象的行为依赖于状态当一个对象的行为受到其内部状态的影响并且可能会在运行时发生变化时适合使用状态模式。状态转换较多的系统如游戏角色、工作流程、文档编辑等场景需要在多种状态之间切换。复杂状态管理在需要管理多个状态和状态之间的转换逻辑时状态模式能够简化代码结构。 实际应用 游戏开发在游戏中角色可能有不同的状态如“行走”、“跳跃”、“攻击”等状态模式可以用来管理这些状态及其对应行为。工作流管理在工作流系统中不同的状态如“待审核”、“审核通过”、“已完成”对应不同的处理逻辑。UI组件在用户界面中按钮、输入框等组件的状态如“正常”、“悬停”、“点击”可以通过状态模式来管理。 总结 状态模式通过将对象的状态和行为封装成独立的类增强了系统的灵活性和可扩展性。适用于需要管理复杂状态的场景能够有效地减少条件判断使代码更加清晰、可维护。尽管可能导致类的数量增加但其带来的管理便利性通常是值得的。 访问者模式Visitor Pattern 定义访问者模式的核心是将操作与对象结构分离。访问者通过访问对象的方法来实现特定的功能。这样如果要添加新功能只需添加新的访问者类而无需修改已有的对象结构。 角色 Visitor访问者接口定义了访问每种元素的方法。ConcreteVisitor具体访问者实现访问者接口定义对每个元素的具体操作。Element元素接口定义接受访问者的方法。ConcreteElement具体元素类实现元素接口定义可以被访问的对象。ObjectStructure对象结构管理元素的集合提供接受访问者的方法。 定义访问者接口 // 访问者接口 public interface Visitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element); }具体访问者类 // 具体访问者 public class ConcreteVisitor implements Visitor {Overridepublic void visit(ConcreteElementA element) {System.out.println(Visiting Element A);}Overridepublic void visit(ConcreteElementB element) {System.out.println(Visiting Element B);} }定义元素接口 // 元素接口 public interface Element {void accept(Visitor visitor); }具体元素类 // 具体元素类A public class ConcreteElementA implements Element {Overridepublic void accept(Visitor visitor) {visitor.visit(this);} }// 具体元素类B public class ConcreteElementB implements Element {Overridepublic void accept(Visitor visitor) {visitor.visit(this);} }对象结构类 import java.util.ArrayList; import java.util.List;// 对象结构类 public class ObjectStructure {private ListElement elements new ArrayList();public void attach(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}} }客户端 public class Main {public static void main(String[] args) {ObjectStructure structure new ObjectStructure();structure.attach(new ConcreteElementA());structure.attach(new ConcreteElementB());Visitor visitor new ConcreteVisitor();structure.accept(visitor);} }访问者模式的关键点 分离操作和数据结构通过访问者模式将操作和数据结构分开使得可以灵活地添加新操作。扩展性添加新操作时只需增加一个新的访问者类无需更改现有元素类。增强代码可读性将与特定操作相关的代码集中在访问者中使得代码更加清晰。 优缺点 优点 增加新的操作容易可以在不修改现有元素类的情况下轻松增加新的操作。集中操作相关操作可以集中在访问者中增强代码的可读性和可维护性。支持复合结构可以对复杂对象结构中的元素进行统一操作。 缺点 违反封装访问者需要了解元素的内部结构可能会破坏封装性。增加新元素难度添加新元素时需要在每个访问者中增加相应的方法增加了维护成本。 适用场景 对象结构稳定但操作频繁变动当对象结构相对稳定但需要频繁添加新的操作时适合使用访问者模式。复杂对象结构的操作在需要对复杂的对象结构进行多种操作时可以使用访问者模式来简化管理。需要在不同对象上执行操作如编译器中对抽象语法树的遍历和处理等。 实际应用 编译器编译器中的语法树遍历访问不同节点进行不同的操作如语法分析、语义分析等。图形程序在图形界面应用中可以实现不同图形元素的操作如绘制、打印等。数据结构操作在一些数据结构中需要对元素进行多种操作时使用访问者模式可以简化操作流程。 总结 访问者模式通过将操作与对象结构分离增强了系统的灵活性和可扩展性。适用于对象结构相对稳定而操作频繁变动的场景有助于提高代码的可读性和可维护性。尽管可能违反封装性和增加新元素的难度但其带来的便利性通常是值得的。 中介者模式Mediator Pattern 定义中介者模式的核心思想是将对象间的复杂关系封装在中介者中让对象不直接通信而通过中介者进行交互。这使得对象之间的依赖关系降低便于扩展和维护。 角色 Mediator中介者接口定义与各个同事对象交互的方法。ConcreteMediator具体中介者实现中介者接口协调各个同事对象的交互。Colleague同事接口定义同事对象的接口包含与中介者的引用。ConcreteColleague具体同事类实现同事接口利用中介者进行交互。 定义中介者接口 // 中介者接口 public interface Mediator {void notify(Colleague colleague, String message); }具体中介者类 // 具体中介者 public class ConcreteMediator implements Mediator {private ConcreteColleagueA colleagueA;private ConcreteColleagueB colleagueB;public void setColleagueA(ConcreteColleagueA colleagueA) {this.colleagueA colleagueA;}public void setColleagueB(ConcreteColleagueB colleagueB) {this.colleagueB colleagueB;}Overridepublic void notify(Colleague colleague, String message) {if (colleague colleagueA) {System.out.println(Colleague A sends message: message);colleagueB.receive(message);} else if (colleague colleagueB) {System.out.println(Colleague B sends message: message);colleagueA.receive(message);}} }定义同事接口 // 同事接口 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); }具体同事类 // 具体同事类A public class ConcreteColleagueA extends Colleague {public ConcreteColleagueA(Mediator mediator) {super(mediator);}Overridepublic void send(String message) {mediator.notify(this, message);}Overridepublic void receive(String message) {System.out.println(ConcreteColleagueA received: message);} }// 具体同事类B public class ConcreteColleagueB extends Colleague {public ConcreteColleagueB(Mediator mediator) {super(mediator);}Overridepublic void send(String message) {mediator.notify(this, message);}Overridepublic void receive(String message) {System.out.println(ConcreteColleagueB received: message);} }客户端 public class Main {public static void main(String[] args) {ConcreteMediator mediator new ConcreteMediator();ConcreteColleagueA colleagueA new ConcreteColleagueA(mediator);ConcreteColleagueB colleagueB new ConcreteColleagueB(mediator);mediator.setColleagueA(colleagueA);mediator.setColleagueB(colleagueB);colleagueA.send(Hello from A);colleagueB.send(Hello from B);} }中介者模式的关键点 降低耦合通过中介者管理对象间的通信减少了对象之间的直接依赖提高了系统的灵活性。集中管理中介者集中管理了所有的交互逻辑使得对象间的交互变得简单而清晰。易于扩展如果需要新增同事类只需实现同事接口并在中介者中添加相应的逻辑不需要修改现有的代码。 优缺点 优点 降低复杂性通过中介者减少了对象之间的直接连接降低了系统的复杂性。便于扩展添加新的同事类或功能时只需修改中介者而不需要修改其他对象。集中化控制所有交互逻辑集中在中介者中便于管理和维护。 缺点 中介者过于复杂如果中介者需要处理的对象和逻辑较多可能导致中介者变得复杂和难以维护。增加了中介者的依赖所有对象都依赖于中介者可能成为系统中的单点故障。 适用场景 对象之间的复杂交互当多个对象之间有复杂的交互关系时使用中介者模式可以简化这些关系。需要松耦合设计在系统中希望降低对象之间的耦合度时中介者模式是一个不错的选择。动态交互需要在运行时动态改变对象之间的交互关系时适合使用中介者模式。 实际应用 GUI框架在图形用户界面中不同组件如按钮、文本框之间的交互可以通过中介者模式来管理。聊天系统在聊天室中用户通过中介者如聊天服务器发送和接收消息减少了用户之间的直接连接。工作流管理在工作流系统中不同任务之间的依赖和交互可以通过中介者模式进行有效管理。 总结 中介者模式通过引入中介者来管理对象间的交互降低了对象间的耦合度增强了系统的灵活性和可维护性。适用于对象之间存在复杂交互的场景但需注意中介者可能变得复杂需谨慎设计。 解释器模式Interpreter Pattern 定义解释器模式的核心思想是为一种特定的语言定义语法规则并提供一种解释执行这些语法的方式。通过创建一系列的解释器类来实现不同的语法规则从而能够解析和执行该语言的句子。 角色 Context上下文包含全局信息供解释器使用通常用于存储变量、状态等。AbstractExpression抽象表达式定义解释的方法并声明一个接受上下文的方法。TerminalExpression终结符表达式实现文法中的终结符规则直接解释基本元素。NonterminalExpression非终结符表达式实现文法中的非终结符规则通常由多个表达式组合而成。 定义上下文 // 上下文类 import java.util.HashMap; import java.util.Map;public class Context {private MapString, Integer variables new HashMap();public int getVariable(String key) {return variables.getOrDefault(key, 0);}public void setVariable(String key, int value) {variables.put(key, value);} }定义抽象表达式 // 抽象表达式 public abstract class AbstractExpression {public abstract int interpret(Context context); }终结符表达式 // 终结符表达式 public class TerminalExpression extends AbstractExpression {private String key;public TerminalExpression(String key) {this.key key;}Overridepublic int interpret(Context context) {return context.getVariable(key);} }非终结符表达式 // 非终结符表达式 public class NonterminalExpression extends AbstractExpression {private AbstractExpression leftExpression;private AbstractExpression rightExpression;public NonterminalExpression(AbstractExpression left, AbstractExpression right) {this.leftExpression left;this.rightExpression right;}Overridepublic int interpret(Context context) {return leftExpression.interpret(context) rightExpression.interpret(context); // 例如简单加法} }客户端 public class Main {public static void main(String[] args) {Context context new Context();context.setVariable(x, 10);context.setVariable(y, 5);// 表达式: x yAbstractExpression x new TerminalExpression(x);AbstractExpression y new TerminalExpression(y);AbstractExpression expression new NonterminalExpression(x, y);int result expression.interpret(context);System.out.println(Result: result); // 输出: Result: 15} }解释器模式的关键点 定义语言的语法通过抽象类和具体类的组合定义了语言的语法规则。上下文管理上下文对象负责存储和管理解析过程中所需的状态信息。可扩展性可以通过添加新的表达式类来扩展语言的语法和功能。 优缺点 优点 易于扩展新增语法规则只需增加新的解释器类不影响现有代码。清晰的语法结构通过类的结构清晰地定义了语法和逻辑。灵活性可以使用组合表达式来构造复杂的语法结构。 缺点 类的数量增加如果语法规则复杂可能导致需要创建大量的类增加系统的复杂性。性能问题在某些情况下解释执行可能导致性能问题尤其是在处理大量数据时。 适用场景 简单语言解释器需要实现简单的表达式计算或简单语言解析的场景。需要灵活语法的系统例如规则引擎、查询解析等需要动态解析和执行的系统。特定领域语言在某些特定领域如编程语言、配置文件等中定义和解释领域特定的语言。 实际应用 SQL解析器在数据库系统中解释SQL语句的执行过程。编译器编译器中的语法分析部分解析和执行代码。规则引擎通过定义规则和条件动态解析和执行逻辑。 总结 解释器模式通过定义语法和创建解释器提供了一种灵活的方式来解析和执行特定的语言或表达式。尽管可能增加类的数量和引入性能问题但在需要灵活性和扩展性的场合它提供了一种有效的解决方案。 空对象模式Null Object Pattern 定义空对象模式的核心思想是创建一个类的实例该实例在逻辑上表示“无”或“空”但仍然遵循该类的接口。这样客户端代码可以直接使用这些对象而不必担心它们是否为 null从而简化代码并提高可读性。 角色 Abstract Class抽象类定义行为的接口或抽象类。Real Object真实对象实现具体行为的类。Null Object空对象实现抽象类并提供一种无操作的默认实现。 定义抽象类 // 抽象类 public abstract class AbstractOperation {public abstract void doSomething(); }实现真实对象 // 真实对象 public class RealOperation extends AbstractOperation {Overridepublic void doSomething() {System.out.println(Performing a real operation.);} }实现空对象 // 空对象 public class NullOperation extends AbstractOperation {Overridepublic void doSomething() {// 不执行任何操作System.out.println(Doing nothing.);} }客户端 public class Main {public static void main(String[] args) {AbstractOperation realOperation new RealOperation();AbstractOperation nullOperation new NullOperation();performOperation(realOperation); // 输出: Performing a real operation.performOperation(nullOperation); // 输出: Doing nothing.}public static void performOperation(AbstractOperation operation) {operation.doSomething();} }空对象模式的关键点 避免 null 检查通过使用空对象消除了代码中对 null 值的频繁检查简化了逻辑。符合开放/关闭原则可以通过添加新的具体对象或空对象灵活地扩展系统而不影响现有代码。统一接口所有对象都遵循相同的接口客户端代码可以透明地使用它们。 优缺点 优点 简化代码减少了 null 检查使得代码更简洁、可读。提高健壮性避免了因 null 引发的空指针异常提高了系统的健壮性。灵活性便于扩展新的行为只需添加新的具体对象或空对象。 缺点 可能增加复杂性如果存在多个空对象可能导致系统中有多个类的实现增加了维护复杂性。不适合所有情况在某些场合空对象可能并不代表“无操作”使用 null 可能更合适。 适用场景 需要处理可选行为在某些情况下某些对象可能没有具体实现而使用空对象可以避免 null 检查。减少空指针异常在复杂系统中避免因空指针引起的异常提高代码的安全性。策略模式和命令模式在这些模式中可以使用空对象来实现无操作的行为。 实际应用 日志系统可以使用空日志对象来替代 null 日志对象避免日志记录时的空检查。配置系统在配置管理中使用空配置对象来表示缺失的配置。用户接口在用户管理系统中使用空用户对象来处理未找到用户的情况。 总结 空对象模式通过引入空对象来代替 null 值简化了代码并提高了系统的健壮性。适用于需要减少 null 检查和空指针异常的场景但也需注意其可能增加的复杂性。在设计中应谨慎使用以确保代码的清晰和易于维护。
http://www.hkea.cn/news/14324854/

相关文章:

  • 做网站卖链接中标公告 网站建设
  • 怎么做资源类网站淄博网站设计方案
  • 怎么样做外贸网站可以做婚礼鲜花布置的网站
  • 360免费建站视频wordpress插件商品对比
  • 免费模板网站制作网页制作公司的渠道通路
  • app公司定制开发asp模版网站如何做优化
  • 代理公司网站备案京东联盟怎么推广赚钱
  • 开封网站建设哪家好网站规划建设与管理维护课后答案6
  • iis发布网站后无法加载dll网站的详情页面设计
  • 重庆的seo服务公司优化大师安卓版
  • 如何规范网站使用微信软文范例大全100
  • 泉州网站建设公司招聘销售小程序商店图标
  • 郑州高端品牌网站建设营销策划包括哪些内容
  • 小说网站建设目的目前最好用的网络管理软件
  • 有没有设计网站在广州的网站已运行时间代码
  • 建设网站地图素材深圳建设局网站打不开
  • 嘉兴门户网站建设网站外包制作
  • 网站开发定制合同范本建一个网站需要购买域名 虚拟主机
  • 专做女装拿货的网站四川做网站优化价格
  • 安达市建设局网站国内做任务得数字货币的网站
  • 微信公众平台开发商宁波seo哪家最便宜
  • 网站建设策划文案企业邮箱怎么申请免费的
  • 网站导航栏兼容性建设银行官网招聘网站
  • 哪个网站上做ppt比较好看的邢台是不是又封了
  • 百度推广网络推广微信网站网络优化工程师是干什么的
  • 专业做淘宝开店的网站大庆互联网公司
  • oa办公系统网站开发西安市政道桥建设公司网站
  • 海南智能网站建设公司网站内链检测工具
  • 各大网站的软文怎么做做网站时的兼容问题
  • 犀牛云做网站如何医院网站建设需要多少钱