Java中有23种设计模式,主要分为三类:创建型模式、结构型模式和行为型模式。
创建型模式
创建型模式关注于对象的创建,提供了更灵活的对象创建方式。主要包括以下几种:
单例模式: 确保一个类只有一个实例,并提供一个全局访问点。
工厂模式: 包括简单工厂、工厂方法模式和抽象工厂模式。
建造者模式: 通过多个简单的对象逐步构建成一个复杂的对象。
原型模式: 通过复制现有的实例来创建新对象。
抽象工厂模式: 创建相关或相互依赖的对象家族,而不需要明确指定具体类。
结构型模式
结构型模式涉及对象/类之间的关系,主要包括以下几种:
适配器模式: 将一个类的接口转换成客户端希望的另一个接口。
装饰器模式: 动态地给一个对象添加一些额外的职责。
代理模式: 为其他对象提供一种代理以控制对这个对象的访问。
外观模式: 提供一个统一的接口,用来访问子系统中的一群接口。
桥接模式: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
组合模式: 将对象组合成树形结构以表示部分-整体层次结构。
享元模式: 通过共享已经创建的对象来减少内存使用和提高效率。
行为型模式
行为型模式涉及对象/类的行为、状态、流程,主要包括以下几种:
策略模式: 定义一系列算法,并将每一个算法封装起来,使它们可以相互替换。
模板方法模式: 定义一个操作中的算法的骨架,将算法的一些步骤延迟到子类中。
观察者模式: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
迭代子模式: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无需暴露该对象的内部表示。
责任链模式: 将请求发送到多个对象中的一个,这些对象共享响应职责。
命令模式: 将一个请求或者操作封装到一个对象中。
备忘录模式: 在不破坏封装的前提下,捕获和恢复对象的状态。
状态模式: 允许一个对象在其内部状态改变时改变它的行为。
访问者模式: 在不修改集合元素的前提下,为集合中的每个元素操作提供一个访问接口。
中介者模式: 用一个中介对象来封装一系列的对象交互。
解释器模式: 提供一个简单的语法分析机制,用于解释和执行字符串表达式。
-
什么是工厂模式? 工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪一个类。工厂模式让一个类的实例化延迟到其子类。
-
工厂模式有哪几种类型? 工厂模式主要有三种类型:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
-
简单工厂模式是如何实现的? 简单工厂模式通过一个静态方法来创建对象,这个方法根据传入的参数来决定创建哪种类型的对象。
public class SimpleFactory { public static Product createProduct(String type) { if (type.equals("A")) { return new ProductA(); } else if (type.equals("B")) { return new ProductB(); } return null; } } -
工厂方法模式与简单工厂模式有什么区别? 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。
public abstract class Product { public abstract void use(); } public class ConcreteProductA extends Product { @Override public void use() { System.out.println("Using Product A"); } } public class ConcreteProductB extends Product { @Override public void use() { System.out.println("Using Product B"); } } public abstract class Factory { public abstract Product createProduct(); } public class ConcreteFactoryA extends Factory { @Override public Product createProduct() { return new ConcreteProductA(); } } public class ConcreteFactoryB extends Factory { @Override public Product createProduct() { return new ConcreteProductB(); } } -
抽象工厂模式与工厂方法模式有什么区别? 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂模式可以创建多个相关的产品族。
public interface AbstractFactory { Product createProduct(); } public class ConcreteFactory1 implements AbstractFactory { @Override public Product createProduct() { return new Product1(); } } public class ConcreteFactory2 implements AbstractFactory { @Override public Product createProduct() { return new Product2(); } } -
在什么情况下应该使用工厂模式? 工厂模式适用于以下情况:
- 当一个类不知道它所需要的对象的确切类型时。
- 当一个类希望由其子类来指定创建的对象时。
- 当将创建对象的逻辑集中在一个地方时(例如,在一个工厂类中)。
- 当需要避免客户端直接创建对象时。
-
如何实现一个简单的工厂方法模式?
public interface Shape { void draw(); } public class Circle implements Shape { @Override public void draw() { System.out.println("Drawing Circle"); } } public class Square implements Shape { @Override public void draw() { System.out.println("Drawing Square"); } } public abstract class ShapeFactory { public abstract Shape createShape(); } public class CircleFactory extends ShapeFactory { @Override public Shape createShape() { return new Circle(); } } public class SquareFactory extends ShapeFactory { @Override public Shape createShape() { return new Square(); } } -
如何在Java中使用反射来实现工厂模式? 使用反射可以在运行时动态地创建对象,从而实现更灵活的工厂模式。
public class ReflectiveFactory { public static Object createInstance(String className) throws Exception { Class<?> clazz = Class.forName(className); return clazz.getDeclaredConstructor().newInstance(); } } -
工厂模式有哪些优点和缺点? 优点:
- 解耦了客户端代码与具体实现类。
- 易于扩展和维护。
- 集中管理对象的创建过程。
缺点:
- 可能会增加系统的复杂度。
- 对于简单场景可能显得过于复杂。
-
请举例说明如何使用工厂模式来解决实际问题? 假设我们有一个日志记录系统,可以使用工厂模式根据配置动态创建不同类型的日志处理器(例如文件日志、数据库日志、控制台日志)。这样可以避免在客户端代码中直接实例化具体的日志处理器,从而提高代码的灵活性和可维护性。
public interface Logger { void log(String message); } public class FileLogger implements Logger { @Override public void log(String message) { System.out.println("Logging to file: " + message); } } public class DbLogger implements Logger { @Override public void log(String message) { System.out.println("Logging to database: " + message); } } public class ConsoleLogger implements Logger { @Override public void log(String message) { System.out.println("Logging to console: " + message); } } public class LoggerFactory { public static Logger getLogger(String type) { if (type.equals("FILE")) { return new FileLogger(); } else if (type.equals("DB")) { return new DbLogger(); } else { return new ConsoleLogger(); } } }