可以查阅JAVA快速入门体验
设计模式的六大原则是一组指导性原则,它们帮助开发人员设计出灵活、可维护和可扩展的软件系统。以下是这些原则的简要介绍:
这些原则共同为软件设计提供了指导,帮助开发人员构建高质量、可维护的系统。请注意,这些原则并非硬性规定,而是在实践中的经验总结,根据具体情况进行灵活应用。
Java中常用的设计模式有23种,这些模式是根据软件设计中常见的问题和解决方案而被提出的。以下是这些设计模式的分类和简要介绍:
这些设计模式提供了在软件开发过程中常见问题的解决方案,并且可以帮助提高代码的可维护性、灵活性和复用性。在实际开发中,根据具体的需求和情况选择合适的设计模式是很重要的。
主要对单例、代理和策略模式进行详解。
单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取该实例。它常用于需要共享资源或控制某些唯一资源的情况下。
单例模式的实现方式有多种,以下是其中两种常见的方式。
在首次调用获取实例的方法时才创建实例。如果实例已经存在,则直接返回该实例。这种方式延迟了实例的创建,但在多线程环境下需要注意线程安全。
示例代码如下:
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数,防止外部实例化
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式(Eager Initialization): 在类加载时就创建实例,确保实例的唯一性。这种方式简单直接,但可能会造成资源浪费,因为实例在整个程序生命周期中都存在。
示例代码如下:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
// 私有构造函数,防止外部实例化
}
public static Singleton getInstance() {
return instance;
}
}
以上代码中,通过将构造函数设为私有,防止外部直接实例化Singleton类。getInstance()方法提供了全局访问点,返回Singleton类的唯一实例。
使用示例:
public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
// 使用singleton对象进行操作
}
}
通过调用Singleton.getInstance()方法获取Singleton类的实例,然后可以使用该实例进行相应的操作。
需要注意的是,单例模式并不适用于所有场景,因为它引入了全局状态和共享资源,可能会增加代码的复杂性和耦合度。在使用单例模式时,需要权衡其优缺点,并根据具体需求进行选择。
代理模式是一种结构型设计模式,它允许通过创建一个代理对象来控制对另一个对象的访问。代理对象充当了客户端和目标对象之间的中介,可以在访问目标对象时添加额外的功能或控制。
代理模式的实现方式有多种,以下是其中两种常见的方式。
在编译时就已经确定代理类和目标类的关系,即代理类是通过手动编码创建的。静态代理需要为每个目标类编写一个代理类,这样会导致代码冗余。
示例代码如下(Java):
// 目标接口
public interface Image {
void display();
}
// 目标类
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 代理类
public class ImageProxy implements Image {
private RealImage realImage;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
在上述示例中,Image 接口定义了目标类和代理类的共同行为,RealImage 是目标类,负责加载和显示图像。ImageProxy 是代理类,用于控制对 RealImage 的访问。当调用 display() 方法时,代理类会首先判断目标对象是否已经创建,若未创建则创建目标对象,然后调用目标对象的 display() 方法。
使用示例(Java):
public class Main {
public static void main(String[] args) {
Image image = new ImageProxy("image.jpg");
image.display();
}
}
在运行时动态生成代理类,无需手动编写代理类。通过使用 Java 提供的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。
示例代码如下(Java):
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 目标接口
public interface Image {
void display();
}
// 目标类
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// InvocationHandler 实现类
public class ImageInvocationHandler implements InvocationHandler {
private Object target;
public ImageInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
// 使用动态代理创建代理对象
public class ProxyFactory {
public static Object createProxy(Object target) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new ImageInvocationHandler(target)
);
}
}
在上述示例中,Image 接口和 RealImage 类与静态代理示例中相同。ImageInvocationHandler 类是实现 InvocationHandler 接口的代理处理器类,用于在调用目标方法前后添加额外的逻辑。ProxyFactory 类用于创建动态代理对象。
使用示例(Java):
public class Main {
public static void main(String[] args) {
Image realImage = new RealImage("image.jpg");
Image imageProxy = (Image) ProxyFactory.createProxy(realImage);
imageProxy.display();
}
}
在上述示例中,通过调用 ProxyFactory.createProxy() 方法创建了一个代理对象 imageProxy,并将其转换为 Image 接口类型。当调用代理对象的 display() 方法时,代理处理器会先执行自定义的逻辑,然后再调用目标对象的 display() 方法。
需要注意的是,代理模式可以提供额外的功能,例如延迟加载、权限控制、日志记录等。通过代理对象,可以在不修改目标对象的前提下,对其进行控制和增强。
策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。该模式将算法封装成独立的策略类,并使这些策略类可以相互替换,从而使得算法的变化独立于使用算法的客户端。
策略模式由三个主要角色组成:
下面是一个示例代码,以展示策略模式的实现方式(Java):
// 抽象策略接口
public interface SortingStrategy {
void sort(int[] array);
}
// 具体策略类 - 冒泡排序
public class BubbleSortStrategy implements SortingStrategy {
public void sort(int[] array) {
System.out.println("Sorting array using Bubble Sort");
// 冒泡排序的具体实现
}
}
// 具体策略类 - 快速排序
public class QuickSortStrategy implements SortingStrategy {
public void sort(int[] array) {
System.out.println("Sorting array using Quick Sort");
// 快速排序的具体实现
}
}
// 环境类
public class SortManager {
private SortingStrategy sortingStrategy;
public void setSortingStrategy(SortingStrategy sortingStrategy) {
this.sortingStrategy = sortingStrategy;
}
public void sortArray(int[] array) {
if (sortingStrategy != null) {
sortingStrategy.sort(array);
}
}
}
在上述示例中,SortingStrategy 是抽象策略接口,定义了排序算法的方法 sort()。BubbleSortStrategy 和 QuickSortStrategy 是具体策略类,分别实现了冒泡排序和快速排序算法。
SortManager 是环境类,它持有一个策略对象,并在需要时调用策略对象的 sort() 方法来进行排序操作。
使用示例(Java):
public class Main {
public static void main(String[] args) {
int[] array = {5, 2, 8, 3, 1};
SortManager sortManager = new SortManager();
// 使用冒泡排序策略
sortManager.setSortingStrategy(new BubbleSortStrategy());
sortManager.sortArray(array);
// 使用快速排序策略
sortManager.setSortingStrategy(new QuickSortStrategy());
sortManager.sortArray(array);
}
}
在上述示例中,首先创建了一个整型数组 array,然后通过创建 SortManager 对象来进行排序操作。通过调用 setSortingStrategy() 方法,可以在运行时设置不同的排序策略,然后调用 sortArray() 方法进行排序。
策略模式的优点是可以灵活地替换算法,使得算法的变化独立于使用算法的客户端。此外,策略模式还可以避免使用大量的条件语句来选择不同的算法,提高了代码的可读性和可维护性。
至此,JAVA设计模式全解(独家AI解析)分享完成,后续会陆续输出更多JAVA相关的篇章;查阅过程中若遇到问题欢迎留言或私信交流。