学习工厂,单例,代理设计模式

92 阅读3分钟

工厂模式

核心思想:定义一个创建对象的接口,由子类决定实例化哪个类。

实现方式:将对象的创建逻辑放到子类中,而不是在客户端代码中。

// 产品接口
public interface Product {
    void operation();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductA operation");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductB operation");
    }
}

// 工厂接口
public abstract class Creator {
    public abstract Product factoryMethod();
}

// 具体工厂A
public class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体工厂B
public class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Creator creator = new ConcreteCreatorA();
        Product product = creator.factoryMethod();
        product.operation();
    }
}

单例模式

核心思想:确保一个类只有一个实例,并提供一个全局访问点。

实现方式:通过私有化构造函数和提供一个静态方法来获取实例。

public class Singleton {
    // static 禁止类加载时实例化
    // volatile 当多个线程都想进行创建实例操作时,将实例变量共享,能够随时察觉到别的线程的实例创建。
    //           同时能够禁止指令重排序。instance = new Single();这个操作分为三步,
    //                                1.分配内存
    //                                2.初始化对象(调用构造函数)
    //                                3.把引用赋值给instance,
    //           当A线程进行instance = new Single时如果指令重排序了,1,2,3变成了1,3,2那B线程在执行外层判断时正好读取了执行了3未执行2的实例对象,会返回未初始化的instance对象。
    private static volatile Singleton instance;

    // 私有的构造函数
    private Singleton() {};

    // 提供的全局访问点,使用双重检测机制保证线程安全。
    //为什么用static修饰该方法
    //  普通实例方法必须先有实例才能调用而这个方法第一次调用时是处于没有实例的情况,用来创建实例的(矛盾点)
    //  static使方法属于类而非实例,实现Singleton.getInstance()直接调用
    private static Singleton getInstance(){
        if(instance == null){ //过滤已初始化的情况,避免同步开销
            synchronized(Singleton.class){}{ //即使多个线程通过了外层检测,这一步也规定了只能有一个线程创建实例
                if(instance == null){
                    instance = new Singleton();//避免重复创建
                }
            }
        }

        return instance;
    }
}

代理模式

核心思想:为其他对象提供一种代理来控制对这个对象的访问。 实现方式:通过定义代理类来控制对真实对象的访问。

// 抽象主题接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject request");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();  // 代理控制对真实主题的访问
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();  // 通过代理访问真实主题
    }
}

策略模式

核心思想:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

实现方式:通过定义策略接口和具体策略类,将算法封装为对象,并在运行时选择使用。

// 策略接口
public interface Strategy {
    void execute();
}

// 具体策略A
public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy A");
    }
}

// 具体策略B
public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy B");
    }
}

// 上下文类
public class Context {
    private Strategy strategy;

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy() {
        strategy.execute();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setStrategy(new ConcreteStrategyA());
        context.executeStrategy();  // 执行策略A

        context.setStrategy(new ConcreteStrategyB());
        context.executeStrategy();  // 执行策略B
    }
}