创建型
1、单例模式
单例模式确保一个类只有一个实例。
单例模式可以有多种实现,其中分为懒汉式和饿汉式。
懒汉式指的是直到使用时才进行实例化,例如spring的BeanFactory就是使用懒汉式加载,好处就是可以节省资源,更快的启动。但是它是线程不安全的,不安全之处体现在它可能会被多次实例化,因此实现方式可以是枚举、静态内部类、双重校验锁等。其中枚举可以防止反射攻击。
饿汉式指的是直接在应用启动时就将其实例化,很显然是线程安全的。例如在spring中的applicationContext中就是用饿汉式加载bean的。
枚举实现
package DesignPattern.Singleton;
public enum Singleton {//枚举实现
INSTANCE;
private String objName;
public String getObjName() {
return objName;
}
public void setObjName(String objName) {
this.objName = objName;
}
public static void main(String[] args) {
// 单例测试
Singleton firstSingleton = Singleton.INSTANCE;
firstSingleton.setObjName("firstName");
System.out.println(firstSingleton.getObjName());
Singleton secondSingleton = Singleton.INSTANCE;
secondSingleton.setObjName("secondName");
System.out.println(firstSingleton.getObjName());
System.out.println(secondSingleton.getObjName());
// 反射获取实例测试
try {
Singleton[] enumConstants = Singleton.class.getEnumConstants();
for (Singleton enumConstant : enumConstants) {
System.out.println(enumConstant.getObjName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
双重校验锁
package DesignPattern.Singleton;
/**
* uniqueInstance 只需要被实例化一次,之后就可以直接使用了。
* 加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。
*
* 双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。
*/
public class DoubleTestSync {
private volatile static DoubleTestSync uniqueInstance;
private DoubleTestSync() {
}
public static DoubleTestSync getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (DoubleTestSync.class) {
if (uniqueInstance == null) {
uniqueInstance = new DoubleTestSync();
}
}
}
return uniqueInstance;
}
/**
* 考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,
* 如果两个线程都执行了 if 语句,那么两个线程都会进入 if 语句块内。
* 虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton();
* 这条语句,只是先后的问题,那么就会进行两次实例化。因此必须使用双重校验锁,
* 也就是需要使用两个 if 语句:第一个 if 语句用来避免 uniqueInstance 已经被实例化之后的加锁操作,
* 而第二个 if 语句进行了加锁,
* 所以只能有一个线程进入,就不会出现 uniqueInstance == null 时两个线程同时进行实例化操作。
*/
/*
if (uniqueInstance == null) {
synchronized (Singleton.class) {
uniqueInstance = new Singleton();
}
}
*/
}
2、工厂模式
工厂模式又分为三种——简单工厂、工厂方法、抽象工厂
工厂方法又可以拆分为实例工厂方法和静态工厂方法,静态工厂方法就是将工厂变成静态的,并不需要将其实例化。
简单工厂
简单工厂把实例化的操作单独放到一个类中,这个类就是简单工厂类,让简单工厂类来决定应该实例化哪个子类。
这样客户类就可以实现与具体子类的解耦。
public interface Product {
}
//------------------------------------------------------------------
public class ConcreteProduct2 implements Product {
{
System.out.println(ConcreteProduct2.class.getName());
}
}
//------------------------------------------------------------------
public class ConcreteProduct1 implements Product {
{
System.out.println(ConcreteProduct1.class.getName());
}
}
//------------------------------------------------------------------
public class SimpleFactory {
public Product createProduct(int type) {
if (type == 1) {
return new ConcreteProduct1();
} else if (type == 2) {
return new ConcreteProduct2();
}
return new ConcreteProduct();
}
}
//------------------------------------------------------------------
public class Client {
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
Product product = simpleFactory.createProduct(1);
// do something with the product
}
}
工厂方法
工厂方法和简单工厂的区别在于:
简单工厂是由另一个类来创建对象,所谓的另一个类,指的是和要创建的对象完全无关的一个类,类似于switch的作用。
而工厂方法则是交由一个抽象的工厂类(注意这里不是抽象工厂)的子类来实例化对象。
public interface Product {}
public class ConcreteProduct implements Product{}
public class ConcreteProduct1 implements Product {}
public class ConcreteProduct2 implements Product {}
public abstract class Factory {
abstract public Product factoryMethod();
public void doSomething() {
Product product = factoryMethod();
// do something with the product
}
}
public class ConcreteFactory extends Factory {
public Product factoryMethod() {
System.out.println(this.getClass().getName());
return new ConcreteProduct();
}
}
public class ConcreteFactory1 extends Factory {
public Product factoryMethod() {
System.out.println(this.getClass().getName());
return new ConcreteProduct1();
}
}
public class ConcreteFactory2 extends Factory {
public Product factoryMethod() {
System.out.println(this.getClass().getName());
return new ConcreteProduct2();
}
}
/**
* 在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
*
* Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,
* 这个产品对象由 factoryMethod() 方法创建。该方法是抽象的,需要由子类去实现。
*/
public class Client {
public static void main(String[] args) {
Product product = new ConcreteFactory().factoryMethod();
Product concreteProduct1 = new ConcreteFactory1().factoryMethod();
Product concreteProduct2 = new ConcreteFactory2().factoryMethod();
}
}
抽象工厂
抽象工厂创建出来的对象会是一堆相关联的对象,这些对象是相关的,换句话说,这些对象必须要一起被创建出来,而工厂方法只需要创建出一个对象。
但是抽象工厂模式内部使用到了工厂方法模式,具体看下面的实现。
public class AbstractProductA {}
public class ProductA1 extends AbstractProductA {}
public class ProductA2 extends AbstractProductA {}
//-------------------------------------------------------------
public class AbstractProductB {}
public class ProductB1 extends AbstractProductB {}
public class ProductB2 extends AbstractProductB {}
//-------------------------------------------------------------
public abstract class AbstractFactory {
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();
}
//-------------------------------------------------------------
public class ConcreteFactory1 extends AbstractFactory {
AbstractProductA createProductA() {
System.out.println(ProductA1.class.getName());
return new ProductA1();
}
AbstractProductB createProductB() {
System.out.println(ProductB1.class.getName());
return new ProductB1();
}
}
//-------------------------------------------------------------
public class ConcreteFactory2 extends AbstractFactory {
AbstractProductA createProductA() {
System.out.println(ProductA2.class.getName());
return new ProductA2();
}
AbstractProductB createProductB() {
System.out.println(ProductA2.class.getName());
return new ProductB2();
}
}
//-------------------------------------------------------------
/**
* 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,
* 并且这些对象是相关的,也就是说必须一起创建出来。
* 而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
*
* 抽象工厂模式用到了工厂方法模式来创建单一对象,
* AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,
* 这两个方法单独来看就是在创建一个对象,
* 这符合工厂方法模式的定义。
*
* 至于创建对象的家族这一概念是在 Client 体现,
* Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,
* 在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。
*
* 从高层次来看,抽象工厂使用了组合,
* 即 Cilent 组合了 AbstractFactory,
* 而工厂方法模式使用了继承。
*/
public class Client {
public static void main(String[] args) {
AbstractFactory abstractFactory1 = new ConcreteFactory1();
AbstractProductA productA1 = abstractFactory1.createProductA();
AbstractProductB productB1 = abstractFactory1.createProductB();
AbstractFactory abstractFactory2 = new ConcreteFactory2();
AbstractProductA productA2 = abstractFactory2.createProductA();
AbstractProductB productB2 = abstractFactory2.createProductB();
// do something with productA and productB
}
结构型
1、适配器模式
简而言之,适配器模式就是将一个类接口转换成另一个用户需要的接口。
在springMVC中也有使用到适配器模式,例如HandlerAdapter。
为什么springMVC要使用适配器模式呢,原因是这样能更加易于扩展。
很显然,handler可以有多种实现,例如实现HttpRequestHandler接口或者实现Controller接口。
在一个controller可以有多种实现的情况下,如果没有适配器模式,则需要用到大量的if else来判断究竟是实现了哪一种,当我们要添加一种新的实现的时候,就需要修改原先的if else代码,这违反了开闭原则。
因此引入了适配器模式,这样,我们在添加新的实现时,只需要再实现一个新的适配器即可。
public interface Duck {
void quack();
}
//--------------------------------------------
public interface Turkey {
void gobble();
}
//--------------------------------------------
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("gobble!");
}
}
//--------------------------------------------
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack() {
turkey.gobble();
}
}
//--------------------------------------------
public class Client {
public static void main(String[] args) {
Turkey turkey = new WildTurkey();
Duck duck = new TurkeyAdapter(turkey);
duck.quack();
}
}
2、装饰者模式
在Java的IO流中,也运用到了装饰者模式。
Java中一些IO流有一个有参的构造方法,例如BufferedInputStream,它的构造方法需要提供一个InputStream的子类
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
之所以要这么做,主要是为了解决Java中没有多继承的问题,同时防止出现太多类。
简单实现如下
public interface Beverage {
double cost();
}
//------------------------------------------------------
public abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
}
//------------------------------------------------------
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 1 + beverage.cost();
}
}
//------------------------------------------------------
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 1 + beverage.cost();
}
}
//------------------------------------------------------
public class DarkRoast implements Beverage {
@Override
public double cost() {
return 1;
}
}
//------------------------------------------------------
public class HouseBlend implements Beverage {
@Override
public double cost() {
return 1;
}
}
//------------------------------------------------------
public class Client {
public static void main(String[] args) {
Beverage beverage = new HouseBlend();//选择主料
beverage = new Mocha(beverage);//添加Mocha
beverage = new Milk(beverage);//添加牛奶
System.out.println(beverage.cost());
//BufferedInputStream stream = new BufferedInputStream(new FileInputStream(new File("")));
}
}
3、代理模式
在springAOP中,代理模式经常被使用。
简单来说,代理模式指的是一个对象的行为并不由该对象本身去执行,而是交给它的代理人去控制。
例如springAOP中的before、after等等都是由代理来完成的。
需要注意的是,jdk动态代理需要实现接口,而CGLIB则是通过继承实现,因此当被代理类被声明为final时,不能使用CGLIB。
public interface Star
{
String sing(String name);
String dance(String name);
}
//---------------------------------------------------------------
public class LiuDeHua implements Star
{
@Override
public String sing(String name)
{
System.out.println("给我一杯忘情水");
return "唱完" ;
}
@Override
public String dance(String name)
{
System.out.println("开心的马骝");
return "跳完" ;
}
}
//---------------------------------------------------------------
public class StarProxy implements InvocationHandler {
// 目标类,也就是被代理对象
private Object target;
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里可以做增强
System.out.println("收钱");
Object result = method.invoke(target, args);
return result;
}
// 生成代理类
public Object CreatProxyedObj() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
//---------------------------------------------------------------
public class Client {
public static void main(String[] args) {
Star ldh = new LiuDeHua();//刘德华
StarProxy proxy = new StarProxy();//创建代理对象
proxy.setTarget(ldh);//将被代理对象set到代理对象中
Object obj = proxy.CreatProxyedObj();//得到一个已经增强过的对象
Star star = (Star) obj;//此时这个接口内的方法均已被增强过
/** 控制台将会输出下面的内容
*
* 收钱
* 开心的马骝
*/
star.dance("");
}
}
行为型
1、迭代器模式
java中有很多类都使用到了迭代器模式。
List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> integerIterator = list.iterator();
简单实现如下所示
public interface Aggregate {
Iterator createIterator();
}
//-----------------------------------------
public class ConcreteAggregate implements Aggregate {
private Integer[] items;
public ConcreteAggregate() {
items = new Integer[10];
for (int i = 0; i < items.length; i++) {
items[i] = i;
}
}
@Override
public Iterator createIterator() {
return new ConcreteIterator<Integer>(items);
}
}
//-----------------------------------------
public interface Iterator<Item> {
Item next();
boolean hasNext();
}
//-----------------------------------------
public class ConcreteIterator<Item> implements Iterator {
private Item[] items;
private int position = 0;
public ConcreteIterator(Item[] items) {
this.items = items;
}
@Override
public Object next() {
return items[position++];
}
@Override
public boolean hasNext() {
return position < items.length;
}
}
//-----------------------------------------
/**
* Aggregate 是聚合类,其中 createIterator() 方法可以产生一个 Iterator;
* Iterator 主要定义了 hasNext() 和 next() 方法。
* Client 组合了 Aggregate,为了迭代遍历 Aggregate,也需要组合 Iterator。
*/
public class Client {
public static void main(String[] args) {
Aggregate aggregate = new ConcreteAggregate();
Iterator<Integer> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
2、观察者模式
spring和java中都大量使用到了这种模式。
这种模式适用于一对多的对象关系,当一个对象的状态发生改变时,就会通知所有的观察者(依赖被观察对象的对象),做出相应的反应,事件驱动机制属于观察者模式的一种实现。
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObserver();
}
//---------------------------------------------------------------------------------
/**
* 定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
*
* 主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。
*/
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;//温度
private float humidity;//湿度
private float pressure;//气压
public WeatherData() {
observers = new ArrayList<>();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObserver();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
@Override
public void notifyObserver() {
for (Observer o : observers) {
o.update(temperature, humidity, pressure);
}
}
}
//---------------------------------------------------------------------------------
public interface Observer {
void update(float temp, float humidity, float pressure);
}
//---------------------------------------------------------------------------------
public class CurrentConditionsDisplay implements Observer {
public CurrentConditionsDisplay(Subject weatherData) {
weatherData.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
System.out.println("CurrentConditionsDisplay.update: " + temp + " " + humidity + " " + pressure);
}
}
//---------------------------------------------------------------------------------
public class StatisticsDisplay implements Observer {
public StatisticsDisplay(Subject weatherData) {
weatherData.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
System.out.println("StatisticsDisplay.update: " + temp + " " + humidity + " " + pressure);
}
}
//---------------------------------------------------------------------------------
/**
* 主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,
* 主题是通过维护一张观察者列表来实现这些操作的。
*
* 观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。
*/
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
weatherData.setMeasurements(0, 0, 0);
weatherData.setMeasurements(1, 1, 1);
}
}
3、责任链模式
SpringMVC的HandlerExecutionChain就属于责任链的一种实现。
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。
简单实现如下。
public enum RequestType {
TYPE1, TYPE2
}
public class Request {
private RequestType type;
private String name;
public Request(RequestType type, String name) {
this.type = type;
this.name = name;
}
public RequestType getType() {
return type;
}
public String getName() {
return name;
}
}
//------------------------------------------------------
public abstract class Handler {
protected Handler successor;
public Handler(Handler successor) {
this.successor = successor;
}
protected abstract void handleRequest(Request request);
}
//------------------------------------------------------------
public class ConcreteHandler1 extends Handler {
public ConcreteHandler1(Handler successor) {
super(successor);
}
@Override
protected void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE1) {
System.out.println(request.getName() + " is handle by ConcreteHandler1");
return;
}
if (successor != null) {
successor.handleRequest(request);
}
}
}
//-------------------------------------------------------------
public class ConcreteHandler2 extends Handler {
public ConcreteHandler2(Handler successor) {
super(successor);
}
@Override
protected void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE2) {
System.out.println(request.getName() + " is handle by ConcreteHandler2");
return;
}
if (successor != null) {
successor.handleRequest(request);
}
}
}
//------------------------------------------------------------------
/**
* 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
* 将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。
*/
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1(null);
Handler handler2 = new ConcreteHandler2(handler1);
Request request1 = new Request(RequestType.TYPE1, "request1");
handler2.handleRequest(request1);
Request request2 = new Request(RequestType.TYPE2, "request2");
handler2.handleRequest(request2);
}
}