设计模式_23种设计模式详细解析

本文详细介绍了23种设计模式,包括单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式、代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式、组合模式、模板方法模式、策略模式、命令模式、责任链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式。每个模式都阐述了定义、特点、结构与实现以及应用场景,并通过具体的例子,如Spring、JDK、Tomcat中的应用,来帮助理解这些模式的实际应用。
摘要由CSDN通过智能技术生成

文章目录

参考

http://c.biancheng.net/view/1348.html

单例模式 Singleton

定义与特点

一个类只有一个实例,且该类能自行创建这个实例的一种模式。

  • 单例类只有一个实例对象;
  • 该单例对象必须由单例类自行创建;
  • 单例类对外提供一个访问该单例的全局访问点;

结构与实现

在这里插入图片描述

饿汉式单例

该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。

public class Hungry {
   
	//私有化构造器,避免外部创建对象
	private Hungry() {
   };
	//定义一个静态成员属性,初始化实例对象
	private static final Hungry instance=new Hungry();
	/**
	 * 定义一个公共的静态方法,返回唯一的对象时实例
	 * @return
	 */
	public static Hungry getInstance() {
   
		return instance;
	}
}

懒汉式单例(静态内部类实现)

public class Lazy {
   
	//私有化构造器,防止外部调用
	private Lazy() {
   };
	/**
	 * 静态内部类中定义一个外部类对象的成员属性
	 * 为了解决线程安全问题
	 * synchronized代码块效率低
	 * 利用静态内部类在外部类初始化时不加载,调用静态内部类时才初始化
	 * static属性只加载一次
	 * @author 83998
	 *
	 */
	private static class Inner {
   
		private static Lazy instance=new Lazy();
	}
	
	public static Lazy getInstance() {
   
		return Inner.instance;
	}
}

懒汉式单例(DCL实现)

/**
 * 单例模式:在多线程环境下,对外仅存在一个对象
 * 1.提供私有的静态属性,存储对象的地址
 * 2.构造器私有化,避免外部新建对象
 * 3.提供公共的静态方法,获取属性
 * 懒汉式套路
 * @author Chill Lyn
 *
 */
public class DoubleCheckedLocking {
   
//	1.提供私有的静态属性,存储对象的地址
//	volatile避免多线程double check时出现指令重排
	private static volatile DoubleCheckedLocking instance;

//	2.构造器私有化,避免外部新建对象
	private DoubleCheckedLocking() {
   

	}

//	3.提供公共的静态方法,获取属性
	public static DoubleCheckedLocking get() {
   
//		double check
		if (null != instance) {
   
			return instance;
		}
		synchronized (DoubleCheckedLocking.class) {
   

			if (null == instance) {
   
				instance = new DoubleCheckedLocking();
			}
			return instance;
		}
	}
}

应用场景

  • 在特定应用场景中,某类要求只生成一个对象时。比如,每个国家只有一个总统。
  • 对象需要被共享的场景。Web中的配置对象、数据库连接池等。
  • 对象频繁实例化和被销毁的场景。线程池、网络连接池等。

Spring中的单例模式

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   
	//首先尝试从单例对象缓存中读取
	Object singletonObject = this.singletonObjects.get(beanName);
	//如果没有,加锁
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   
		synchronized (this.singletonObjects) {
   
			//double check
			singletonObject = this.earlySingletonObjects.get(beanName);
			//如果没有就创建
			if (singletonObject == null && allowEarlyReference) {
   
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
   
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

Tomcat中的单例模式

所有的Filter,Servlet和Listener的实现类。

原型模式Prototype

定义与特点

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

  • 高效

结构与实现

Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。

  • 抽象原型类:规定了具体原型对象必须实现的接口。Clonable接口。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
    在这里插入图片描述
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.*;

public class CreateObject {
   
    public static void main(String[] args) {
   
        //1.直接new一个person对象
        Person p1 = new Person("cl", 18, new Clothes("black"));

        //2. clone()
        try {
   
            Person p4= (Person) p1.clone();
            p4.setName("ddd");
            System.out.println(p4.toString());
        } catch (CloneNotSupportedException e) {
   
            e.printStackTrace();
        }
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person implements Serializable, Cloneable {
   

    private String name;
    private transient Integer age;
    private Clothes clothes;

    /**
     * deep clone;
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
   
        Person person = (Person) super.clone();
        person.setClothes((Clothes) person.getClothes().clone());
        return person;
    }
}

@Data
@AllArgsConstructor
class Clothes implements Serializable,Cloneable {
   
    private String color;

    /**
     * shallow clone;
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
   
        return super.clone();
    }
}

应用场景

  • 对象之间相同或相似,即只是个别的几个属性不同的时候。
  • 对象的创建过程比较麻烦,但复制比较简单的时候。

工厂方法模式(Factory Method)

定义与特点

定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

被创建的对象称为“产品”,创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

结构与实现

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
    在这里插入图片描述
/**
 * 抽象工厂
 */
public interface PetFactory {
   
    Pet getPet();
}

/**
 * 抽象产品
 */
interface Pet {
   
    void voice();
}

/**
 * 具体工厂
 */
class DogFactory implements PetFactory {
   

    @Override
    public Pet getPet() {
   
        return new Dog();
    }
}
/**
 * 具体工厂
 */
class CatFactory implements PetFactory {
   

    @Override
    public Pet getPet() {
   
        return new Cat();
    }
}
/**
 * 具体产品
 */
class Dog implements Pet {
   

    @Override
    public void voice() {
   
        System.out.println("wang");
    }
}

/**
 * 具体产品
 */
class Cat implements Pet {
   

    @Override
    public void voice() {
   
        System.out.println("mew");
    }
}

class Test {
   
    public static void main(String[] args) {
   
        DogFactory dogFactory = new DogFactory();
        dogFactory.getPet().voice();
        CatFactory catFactory = new CatFactory();
        catFactory.getPet().voice();
    }
}

应用场景

  • 客户只知道创建产品的工厂名,而不知道具体的产品名。
  • 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
  • 客户不关心创建产品的细节,只关心产品的品牌。

Spring中的工厂方法模式

FactoryBean相当于抽象工厂

public interface FactoryBean<T> {
   
	@Nullable
	T getObject() throws Exception;
}

FactoryBean的实现类相当于具体工厂

JDK中的工厂方法模式

• java.lang.Object#toString() (在其子类中可以覆盖该方法)
• java.lang.Class#newInstance()
• java.lang.Integer#valueOf(String) (Boolean, Byte, Character,Short, Long, Float 和 Double与之类似)
• java.lang.Class#forName()
• java.lang.reflect.Array#newInstance()
• java.lang.reflect.Constructor#newInstance()

Tomcat中的工厂方法模式

Tomcat在启动的过程中关于SeverSocket的生成使用的是工厂生成的而不是自己new出来的。实际上这些socket就是后期tomcat接收请求时的socket。

serverSocket = serverSocketFactory.createSocket(getPort(),
                        getBacklog());

Tomcat在处理请求的时候,当请求到达StandardWrapperValveinvoke()方法中,在调用指定的servelt实例之前,先创建对应servlet的filterChain,代码如下:

//获取工厂实例
 ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
//使用工厂实例创建 filterChain实例
 ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);

扩展-简单工厂模式

当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。
在这里插入图片描述

public class PetFactory {
   

    public static Pet getInstance(String className){
   
        Pet pet=null;
        try {
   
            pet= (Pet) Class.forName(className).newInstance();
        } catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) {
   
            e.printStackTrace();
        }
        return pet;
    }
}


interface Pet {
   
    void voice();
}

class Cat implements Pet {
   
    @Override
    public void voice() {
   
        System.out.println("mew");
    }
}

class Dog implements Pet {
   
    @Override
    public void voice() {
   
        System.out.println("wang");
    }
}

Spring中的简单工厂模式

Spring中BeanFactory相当于抽象工厂,getBean(String name)根据名字来获得bean对象,相当于简单工厂模式

抽象工厂模式(AbstractFactory)

定义和特点

工厂方法模式中考虑的是一类产品的生产。同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品。

抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

  • 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
  • 系统一次只可能消费其中某一族产品,即同族的产品一起使用。

抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当增加一个新的产品族时不需要修改原代码,满足开闭原则。

其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改

结构与实现

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系
    在这里插入图片描述
import lombok.extern.java.Log;

/**
 * 抽象工厂
 */
public interface Factory {
   

    Phone createPhone(
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值