Java常用设计模式

常用设计模式

  • 一、策略模式
  • 二、工厂模式
  • 三、代理模式
  • 四、原型模式

一、策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,将每个算法都封装起来,使得它们可以互相替换,从而让算法的变化独立于使用算法的客户。

策略模式的结构包含三个角色:

  1. 环境(Context)角色:持有一个策略对象的引用,在运行时调用策略对象的算法。
  2. 抽象策略(Strategy)角色:定义了一个公共接口,各种不同的算法都实现这个接口。
  3. 具体策略(Concrete Strategy)角色:实现了抽象策略定义的接口,提供具体的算法实现。

策略模式的优点:

  1. 策略模式可以避免使用大量的条件语句来判断不同的算法,提高代码的可读性和可维护性。
  2. 策略模式可以让算法的变化独立于使用算法的客户,从而更容易地扩展和修改算法。
  3. 策略模式可以在运行时动态地切换算法,提高程序的灵活性和适应性。

策略模式的缺点:

  1. 策略模式增加了系统中类的数量,增加了系统的复杂度。
  2. 客户端需要知道所有的策略类,并自行决定使用哪一个策略,增加了客户端的复杂度和责任。

策略模式的应用场景:

  1. 在需要使用不同算法的场景中,例如排序、加密、压缩等。
  2. 在需要避免使用大量条件语句的场景中,例如根据不同的用户类型显示不同的广告。
  3. 在需要在运行时动态切换算法的场景中,例如网络负载均衡。

Java代码实现:

  1. 定义策略接口:

    public interface Strategy {
        public int calculate(int num1, int num2);
    }
    
  2. 实现具体的算法策略:

    public class AddStrategy implements Strategy {
        public int calculate(int num1, int num2) {
            return num1 + num2;
        }
    }
    
    public class SubtractStrategy implements Strategy {
        public int calculate(int num1, int num2) {
            return num1 - num2;
        }
    }
    
    public class MultiplyStrategy implements Strategy {
        public int calculate(int num1, int num2) {
            return num1 * num2;
        }
    }
    
    
  3. 定义环境类,持有策略对象的引用:

    public class Context {
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public void setStrategy(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public int executeStrategy(int num1, int num2) {
            return strategy.calculate(num1, num2);
        }
    }
    
  4. 在客户端中使用策略模式:

    public class Client {
        public static void main(String[] args) {
            Strategy addStrategy = new AddStrategy();
            Strategy subtractStrategy = new SubtractStrategy();
            Strategy multiplyStrategy = new MultiplyStrategy();
    
            Context context = new Context(addStrategy);
            System.out.println("Addition: " + context.executeStrategy(5, 3));
    
            context.setStrategy(subtractStrategy);
            System.out.println("Subtraction: " + context.executeStrategy(5, 3));
    
            context.setStrategy(multiplyStrategy);
            System.out.println("Multiplication: " + context.executeStrategy(5, 3));
        }
    }
    

    在这个示例中,我们定义了一个策略接口,并实现了三种具体的算法策略:加法、减法和乘法。然后我们定义了一个环境类Context,持有策略对象的引用,并在客户端中使用策略模式动态地切换算法策略。


二、工厂模式

工厂模式是一种创建型设计模式,其目的是提供一种简单、灵活的方式来创建对象,同时隐藏具体实现细节,使客户端代码与具体实现解耦。

工厂模式有三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。

简单工厂模式:由一个工厂类根据传入的参数决定创建哪一种产品类的实例。简单工厂模式适用于产品类较少的情况,但是随着产品类的增加,工厂类的职责会越来越多,不利于代码的维护和扩展。

工厂方法模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式适用于产品类较多的情况,每个产品类的创建由其对应的工厂类负责,符合开闭原则,但是增加了代码的复杂度。

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式适用于需要创建一组对象的情况,每个工厂类负责创建一组相关的产品,增加新的产品需要修改接口和所有的实现类,不符合开闭原则。

工厂模式的优点是将对象的创建和使用分离,使代码更易于维护和扩展。缺点是增加了代码的复杂度和类的数量。

在Java中,工厂模式的实现可以使用接口和抽象类来定义工厂类和产品类,具体的工厂类和产品类由实现类来完成。以下是一个简单工厂模式的示例代码:

// 抽象产品类
public abstract class Product {
    public abstract void use();
}

// 具体产品类A
public class ProductA extends Product {
    public void use() {
        System.out.println("使用产品A");
    }
}

// 具体产品类B
public class ProductB extends Product {
    public void use() {
        System.out.println("使用产品B");
    }
}

// 简单工厂类
public class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ProductA();
        } else if ("B".equals(type)) {
            return new ProductB();
        } else {
            throw new IllegalArgumentException("不支持的产品类型:" + type);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Product product = SimpleFactory.createProduct("A");
        product.use();
    }
}

三、代理模式

代理模式是一种结构型设计模式,它允许你提供一个对象作为另一个对象的替代品,以控制对该对象的访问。代理对象充当客户端与实际对象之间的中介,客户端通过代理访问实际对象,从而实现对实际对象的控制。

代理模式有三种类型:静态代理、动态代理和虚拟代理。其中静态代理是在编译时就已经确定了代理对象,而动态代理是在运行时根据需要动态生成代理对象,虚拟代理则是在需要时才加载实际对象。

代理模式的优点在于可以在不改变实际对象的情况下增强或控制对实际对象的访问。它还可以实现对象的延迟加载,提高系统的性能和效率。

下面是Java代码实现一个简单的代理模式:

// 定义一个接口
interface Subject {
    void request();
}

// 实际对象
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject request()");
    }
}

// 代理对象
class ProxySubject implements Subject {
    private RealSubject realSubject;

    public ProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("ProxySubject request()");
        realSubject.request();
    }
}

// 测试
public class ProxyPatternDemo {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        proxySubject.request();
    }
}


四、原型模式

原型模式是一种创建型设计模式,它允许通过克隆现有对象来创建新对象,而不是通过实例化一个类。这种方式可以减少对象创建的时间和成本,并且可以在运行时动态地创建新对象。

在原型模式中,一个原型对象是创建其他对象的模板。当需要创建一个新对象时,只需复制该原型对象并修改其属性即可。因此,原型模式适用于创建复杂的对象,这些对象的创建过程比较耗时或者需要大量的资源。

优点:

  1. 可以动态创建对象,避免了类的实例化过程,提高了效率。
  2. 可以避免复杂的对象构造函数,简化了对象的创建过程。
  3. 可以通过克隆来创建对象,避免了对原有代码的修改,保证了代码的稳定性。

缺点:

  1. 需要对每一个类进行克隆方法的实现,增加了代码量。
  2. 对象的复制过程可能比直接创建对象更加耗时。

在Java中,实现原型模式可以使用Java提供的Cloneable接口和Object类中的clone()方法。我们可以在需要克隆的类中实现Cloneable接口,并重写clone()方法,实现对象的克隆。例如:

public class Prototype implements Cloneable {
    
    private String name;
    
    public Prototype(String name) {
        this.name = name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

然后,我们可以使用原型对象来创建新对象:

Prototype prototype = new Prototype("原型对象");
Prototype clone = (Prototype) prototype.clone();
clone.setName("克隆对象");
System.out.println("原型对象的名称:" + prototype.getName());
System.out.println("克隆对象的名称:" + clone.getName());

你可能感兴趣的:(设计模式,java,设计模式)