设计模式之创建型模式

1. 定义

在Java中,有23种经典的设计模式,它们分为三种类型:创建型模式、结构型模式和行为型模式。

创建型模式:创建型模式是一种设计模式,主要用于处理对象的创建过程,它将对象的创建和使用分离,使得系统更加灵活和可扩展。

  1. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。
  2. 工厂模式(Factory Pattern):定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。
  3. 抽象工厂模式(Abstract Factory Pattern):提供一个接口,用于创建一系列相关或相互依赖的对象,而不需要指定具体的类。
  4. 建造者模式(Builder Pattern):将一个复杂对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。
  5. 原型模式(Prototype Pattern):通过复制现有对象来创建新对象,而不是通过实例化。

结构型模式;结构型设计模式主要关注对象组合的方式,用于描述如何将类或对象结合在一起形成更大的结构。

  1. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以一起工作。
  2. 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们可以独立地变化。
  3. 组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
  4. 装饰者模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,而不影响原有对象的结构。
  5. 外观模式(Facade Pattern):为子系统中的一组接口提供一个统一的接口,使得子系统更容易使用。
  6. 享元模式(Flyweight Pattern):共享对象以减少内存使用或提高性能。
  7. 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。

行为型模式:行为型设计模式主要关注对象之间的通信和职责分配,描述了对象之间的相互作用和责任分配方式。

  1. 策略模式(Strategy Pattern):定义一系列算法,封装每个算法,并使它们可以互相替换。
  2. 模板方法模式(Template Method Pattern):定义一个算法的框架,将具体步骤延迟到子类中实现。
  3. 观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象改变状态时,所有依赖它的对象都会收到通知并自动更新。
  4. 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。
  5. 责任链模式(Chain of Responsibility Pattern):将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。
  6. 命令模式(Command Pattern):将请求封装成一个对象,从而可以用不同的请求对客户端进行参数化。
  7. 状态模式(State Pattern):允许对象在其内部状态改变时改变它的行为。
  8. 访问者模式(Visitor Pattern):将算法与对象结构分离,使得可以在不改变这些对象的前提下定义新的操作。
  9. 中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互。
  10. 备忘录模式(Memento Pattern):在不破坏封装的前提下捕获一个对象的内部状态,并在需要时恢复。
    11.解释器模式(Interpreter Pattern):它用于定义一种语言的文法,并且解释该语言中的句子,该模式通常用于解决一些重复出现的问题。

创建型模式

1.单例模式

饿汉模式

示例中,静态变量 instance 在类加载时就被初始化,并且通过 getInstance() 方法获取单例对象的时候,直接返回该静态变量的实例。饿汉模式简单易用,线程安全,但可能会导致资源浪费。

public class Singleton {
    private static final Singleton instance = new Singleton();

    // 私有构造方法,防止外部实例化
    private Singleton() {
    }

    // 提供静态方法获取单例对象
    public static Singleton getInstance() {
        return instance;
    }
}

饱汉模式

示例中,通过双重检查锁的方式保证了在多线程环境下获取单例对象的线程安全性。首先检查是否已经创建了单例对象,如果没有则进入同步块,在同步块内再次检查是否已经创建了单例对象,如果没有则创建单例对象。饱汉模式延迟了单例对象的创建时间,节约了资源并提高了性能,但需要考虑多线程环境下的线程安全性。

public class Singleton {
	//使用了 volatile 关键字来确保 instance 变量的可见性
    private static volatile Singleton instance = null;

    // 私有构造方法,防止外部实例化
    private Singleton() {
    }

    // 提供静态方法获取单例对象,使用双重检查,加锁确保线程安全
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态嵌套类单例模式

常见且推荐的单例模式实现方式,结合了懒加载(节约资源)和线程安全(单例对象唯一)的优点,当然还有代码简单的很。

示例中,Singleton 类的私有静态内部类 SingletonHolder 中包含了一个静态 final 的 Singleton 实例,利用类加载的特性保证了线程安全的创建单例对象。当调用 Singleton.getInstance() 方法时,会首次加载 SingletonHolder 类,并创建 Singleton 实例,保证了懒加载的效果。

public class Singleton {
    
    private Singleton() {
        // 私有构造方法
    }
    
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

2.工厂模式

简单工厂模式
由一个工厂类根据传入的参数决定创建哪一种产品类的实例。客户端只需要传入一个参数,无需关心具体的实例化过程。

示例中,通过调用 SimpleFactory 的 createProduct 方法,根据传入的参数决定创建哪种产品类的实例。客户端只需要传入参数,无需关心具体的产品类实例化过程,实现了对象的解耦和封装。

// 抽象产品类
interface Product {
    void produce();
}

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

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

// 简单工厂类
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;
    }
}

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

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

先看下伪代码:
工厂方法

示例中,每个具体工厂类(ConcreteFactoryA 和 ConcreteFactoryB)只负责创建一种具体产品(ConcreteProductA 和 ConcreteProductB),符合工厂方法模式的定义。

// 抽象产品类
interface Product {
    void produce();
}

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

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

// 工厂接口
interface Factory {
    Product createProduct();
}

// 具体工厂类A
class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂类B
class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.produce();
        
        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.produce();
    }
}

3. 抽象工厂模式

通常会定义一个抽象工厂接口,其中包含多个抽象的工厂方法,每个工厂方法用于创建一种产品。
抽象工厂模式适合于需要创建一系列相关或相互依赖的对象,并且需要在运行时切换不同产品族的情况。它也符合开闭原则,对修改关闭、对扩展开放。

先看下伪代码:

这时候,我不想只卖菜了,我还要卖奶茶,怎么办呢?再建个奶茶工厂~~~好麻烦啊
抽象工厂来了!!1
请定义一个联名的抽象类:我有两个方法,做奶茶 and 做美食(不要问为什么不接口里面定义两个方法,一个类只能做一件事情,都要做两件事了,那只能抽象出来了呗,不过也可以看情况转换,他们一定程度上功能相似)

抽象工厂
懂了吧,产品组选抽象工厂

示例中,抽象工厂模式通过引入抽象工厂接口 AbstractFactory 和多个具体工厂类(ConcreteFactory1 和 ConcreteFactory2)来实现对象的创建。客户端通过实例化具体的工厂类并调用工厂方法来获取产品对象,实现了对象的解耦合和灵活性。

// 抽象产品A
interface ProductA {
    void produce();
}

// 具体产品A1
class ConcreteProductA1 implements ProductA {
    @Override
    public void produce() {
        System.out.println("Producing Product A1");
    }
}

// 具体产品A2
class ConcreteProductA2 implements ProductA {
    @Override
    public void produce() {
        System.out.println("Producing Product A2");
    }
}

// 抽象产品B
interface ProductB {
    void consume();
}

// 具体产品B1
class ConcreteProductB1 implements ProductB {
    @Override
    public void consume() {
        System.out.println("Consuming Product B1");
    }
}

// 具体产品B2
class ConcreteProductB2 implements ProductB {
    @Override
    public void consume() {
        System.out.println("Consuming Product B2");
    }
}

// 抽象工厂接口
interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        ProductB productB1 = factory1.createProductB();
        productA1.produce();
        productB1.consume();

        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        ProductB productB2 = factory2.createProductB();
        productA2.produce();
        productB2.consume();
    }
}

4. 建造者模式

建造者模式通过一个指挥者(Director)和多个建造者(Builder)来创建对象,以简化对象的构建过程。

我们代码中最常用的应该就是Lombok 中使用 @Builder 注解来实现建造者模式了吧,如下所示:

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class Person {
    private String name;
    private int age;
    private String gender;

    public static void main(String[] args) {
        Person person = Person.builder()
                .name("Alice")
                .age(25)
                .gender("Female")
                .build();

        System.out.println(person);
    }
}

建造者模式通常包含以下几个角色:

  1. 产品(Product):表示被构建的复杂对象。
  2. 抽象建造者(Builder):定义构建产品各个部件的抽象接口。
  3. 具体建造者(Concrete Builder):实现抽象建造者接口,负责实际构建产品的各个部件。
  4. 指挥者(Director):负责调用具体建造者来构建产品对象,并定义构建的顺序和流程。

建造者模式通过抽象建造者接口、具体建造者类和指挥者来实现对象的构建过程。具体建造者类负责构建产品的各个部件,指挥者负责调用具体建造者来构建产品对象。客户端通过指挥者来构建不同的产品对象,而不需要直接与具体建造者类交互。

建造者模式适用于构建复杂对象,且构建过程需要独立于其表示。它可以灵活地构建不同的产品对象,而不需要知道产品的具体构建细节。建造者模式也符合单一职责原则,每个具体建造者只负责构建一个产品的各个部件。

// 产品类
class Product {
    private String partA;
    private String partB;
    
    public void setPartA(String partA) {
        this.partA = partA;
    }
    
    public void setPartB(String partB) {
        this.partB = partB;
    }
    
    public void show() {
        System.out.println("Product parts: " + partA + " and " + partB);
    }
}

// 抽象建造者
interface Builder {
    void buildPartA();
    void buildPartB();
    Product getResult();
}

// 具体建造者A
class ConcreteBuilderA implements Builder {
    private Product product = new Product();
    
    @Override
    public void buildPartA() {
        product.setPartA("Part A from Builder A");
    }
    
    @Override
    public void buildPartB() {
        product.setPartB("Part B from Builder A");
    }
    
    @Override
    public Product getResult() {
        return product;
    }
}

// 具体建造者B
class ConcreteBuilderB implements Builder {
    private Product product = new Product();
    
    @Override
    public void buildPartA() {
        product.setPartA("Part A from Builder B");
    }
    
    @Override
    public void buildPartB() {
        product.setPartB("Part B from Builder B");
    }
    
    @Override
    public Product getResult() {
        return product;
    }
}

// 指挥者
class Director {
    public Product construct(Builder builder) {
        builder.buildPartA();
        builder.buildPartB();
        return builder.getResult();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Director director = new Director();
        
        Builder builderA = new ConcreteBuilderA();
        Product productA = director.construct(builderA);
        productA.show();
        
        Builder builderB = new ConcreteBuilderB();
        Product productB = director.construct(builderB);
        productB.show();
    }
}

5. 原型模式

它允许通过复制现有对象来创建新对象,而无需显式地使用构造函数。

核心概念:

  1. 原型接口(Prototype):定义了克隆方法的接口,所有实现该接口的类都需要实现克隆方法。
  2. 具体原型类(ConcretePrototype):实现了原型接口的具体类,负责实现克隆方法。
  3. 客户端(Client):创建新对象时,通过原型对象复制来获得新对象。

示例中,我们定义了一个原型接口 Prototype,并实现了具体原型类 ConcretePrototype,该类实现了克隆方法。在客户端代码中,我们创建了一个原型对象并通过克隆方法复制出一个新对象。

// 原型接口
interface Prototype {
    Prototype clone();
}

// 具体原型类
class ConcretePrototype implements Prototype {
    private String property;

    public ConcretePrototype(String property) {
        this.property = property;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototype(this.property);
    }

    public String getProperty() {
        return property;
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Prototype prototype = new ConcretePrototype("property value");
        Prototype clone = prototype.clone();

        System.out.println("Original Object Property: " + ((ConcretePrototype) prototype).getProperty());
        System.out.println("Cloned Object Property: " + ((ConcretePrototype) clone).getProperty());
    }
}

还没写~~
结构型模式

  1. 适配器模式
  2. 桥接模式
  3. 组合模式
  4. 装饰者模式
  5. 外观模式
  6. 享元模式
  7. 代理模式

行为型

  1. 策略模式
  2. 模板方法模式
  3. 观察者模式
  4. 迭代器模式
  5. 责任链模式
  6. 命令模式
  7. 状态模式
  8. 访问者模式
  9. 中介者模式
  10. 备忘录模式
    11.解释器模式
  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值