前言
以下是对常见的几种设计模式的介绍
实现代码的github地址:https://github.com/Chenrencun/design-pattern
正文
一、单例模式
1、定义:
一个类只有一个实例,且该类能自行创建这个实例的一种模式。
2、结构:
(1)单例类:包含一个实例且能自行创建这个实例的类。
3、实现代码:
(1)饿汉式:
public class HungrySingle { private static final HungrySingle singleton = new HungrySingle(); private HungrySingle(){ } public static HungrySingle getInstance(){ return singleton; } }
(2)懒汉式:
①单线程(线程不安全):
public class LazySingletonForNotSafe { private static LazySingletonForNotSafe lazySingleton; private LazySingletonForNotSafe(){ } public static LazySingletonForNotSafe getInstance(){ if (lazySingleton == null){ lazySingleton = new LazySingletonForNotSafe(); } return lazySingleton; } }
②多线程(线程安全):
public class LazySingletonForSafe { //volatile关键字,保证可见性 private static volatile LazySingletonForSafe singleton; private LazySingletonForSafe(){ } public static LazySingletonForSafe getInstance(){ if (singleton == null){ synchronized (LazySingletonForSafe.class){ if (singleton == null){ singleton = new LazySingletonForSafe(); } } } return singleton; } }
二、工厂方法模式:
1、定义:
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。
2、结构:
(1)抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
(2)具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
(3)抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
(4)具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
3、实现代码:
(1)抽象产品接口:
public interface Product { public void show(); }
(2)具体产品类:
public class ConcreteProduct1 implements Product{ @Override public void show() { System.out.println("具体产品1显示------"); } } public class ConcreteProduct2 implements Product{ @Override public void show() { System.out.println("具体产品2显示---------"); } }
(3)抽象工厂接口:
public interface Factory { public Product create(); }
(4)具体工厂类:
public class ConcreteFactory1 implements Factory{ @Override public Product create() { System.out.println("具体工厂1生成—>具体产品1"); return new ConcreteProduct1(); } } public class ConcreteFactory2 implements Factory{ @Override public Product create() { System.out.println("具体工厂2生成—>具体产品2"); return new ConcreteProduct2(); } }
三、抽象工厂模式:
1、定义:
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
2、结构:
(1)抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
(2)具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
(3)抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
(4)具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。
3、实现代码:
(1)抽象产品接口:
public interface FirstProduct { public void show(); } public interface SecondProduct { public void show(); }
(2)具体产品类:
public class ConcreteFirstProduct1 implements FirstProduct { public void show() { System.out.println("显示具体产品11------"); } } public class ConcreteSecondProduct1 implements SecondProduct { public void show() { System.out.println("显示具体产品21------"); } }
(3)抽象工厂接口:
public interface Factory { public FirstProduct createFirstProduct(); public SecondProduct createSecondProduct(); }
(4)具体工厂类:
public class ConcreteFactory1 implements Factory{ public FirstProduct createFirstProduct() { return new ConcreteFirstProduct1(); } public SecondProduct createSecondProduct() { return new ConcreteSecondProduct1(); } }
四、代理模式:
1、定义:
给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
2、结构:
(1)抽象主题类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
(2)具体主题类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
(3)代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
3、实现代码:
(1)普通代理:
①抽象主题接口:
public interface Subject { void request(); }
②具体主题类:
public class ConcreteSubject implements Subject{ public void request() { System.out.println("具体主题类的request方法"); } }
③代理类:
public class Proxy implements Subject{ private Subject subject; public Proxy(Subject subject){ this.subject = subject; } public void request() { before(); subject.request(); after(); } private void before(){ System.out.println("执行方法前-----dosomething"); } private void after(){ System.out.println("执行方法后-----dosomething"); } }
(2)动态代理:
①抽象主题接口:
public interface Subject { void request(); }
②具体主题类:
public class ConcreteSubject implements Subject { public void request() { System.out.println("具体主题类的request方法"); } }
③代理类:
public class DynamicProxy implements InvocationHandler { private Object object; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(object, args); after(); return result; } public Object getProxy(Object object){ this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this); } private void before(){ System.out.println("执行方法前-----dosomething"); } private void after(){ System.out.println("执行方法后-----dosomething"); } }
(3)CGLib代理:
①抽象主题接口:
public interface Subject { void request(); }
②具体主题类:
public class ConcreteSubject implements Subject { public void request() { System.out.println("具体主题类的request方法"); } }
③代理类:
public class CGLibProxy implements MethodInterceptor { private Object object; public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { before(); Object result = method.invoke(object, objects); after(); return result; } public Object getProxy(Object object){ this.object = object; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(object.getClass()); enhancer.setCallback(this); Object result = enhancer.create(); return result; } private void before(){ System.out.println("执行方法前-----dosomething"); } private void after(){ System.out.println("执行方法后-----dosomething"); } }
五、适配器模式:
1、定义:
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
2、结构:
(1)目标接口:当前系统业务所期待的接口,它可以是抽象类或接口。
(2)适配者类:它是被访问和适配的现存组件库中的组件接口。
(3)适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
3、实现代码:
(1)类适配器:通过继承的方式进行适配。
①目标接口:
public interface Target { void request(); }
②适配者类:
public class Adaptee { public void specialRequest(){ System.out.println("执行适配者类的specialRequest方法"); } }
③适配器类:
public class Adapter extends Adaptee implements Target{ public void request() { specialRequest(); } }
(2)对象适配器:通过组合/聚合的方式进行适配。
①目标接口:
public interface Target { void request(); }
②适配者类:
public class Adaptee { public void specialRequest(){ System.out.println("执行适配者类的specialRequest方法"); } }
③适配器类:
public class Adapter implements Target{ private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee = adaptee; } public void request() { adaptee.specialRequest(); } }
六、模板方法模式:
1、定义:
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
2、结构:
(1)抽象类:负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
①模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
②基本方法:是整个算法中的一个步骤,包含以下几种类型。
抽象方法:在抽象类中申明,由具体子类实现。
具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
(2)具体子类:实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
3、实现代码:
(1)抽象类:
public abstract class AbstractClass { // 模板方法 public void templateMethod(){ concreteMethod(); abstractMethod1(); // 钩子方法进行逻辑判断 if (hookMethod()){ abstractMethod2(); } } // 具体方法(基本方法) public void concreteMethod(){ System.out.println("执行具体方法"); } // 抽象方法(基本方法) public abstract void abstractMethod1(); // 抽象方法(基本方法) public abstract void abstractMethod2(); // 钩子方法(基本方法) public boolean hookMethod(){ return true; } }
(2)具体子类:
public class ConcreteClass extends AbstractClass{ public void abstractMethod1() { System.out.println("执行具体子类的重写方法1"); } public void abstractMethod2() { System.out.println("执行具体子类的重写方法2"); } @Override public boolean hookMethod() { return false; } }
七、策略模式
1、定义:
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
2、结构:
(1)抽象策略类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
(2)具体策略类:实现了抽象策略定义的接口,提供具体的算法实现。
(3)环境类:持有一个策略类的引用,最终给客户端调用。
3、实现代码:
(1)抽象策略类:
public interface Strategy { void strategyMethod(); }
(2)具体策略类:
public class ConcreteStrategy1 implements Strategy{ public void strategyMethod() { System.out.println("访问具体策略类1的算法"); } } public class ConcreteStrategy2 implements Strategy{ public void strategyMethod() { System.out.println("访问具体策略类2的算法"); } }
(3)环境类:
public class Context { private Strategy strategy; public Context(Strategy strategy){ this.strategy = strategy; } public void strategyMethod(){ strategy.strategyMethod(); } }
八、观察者模式
1、定义:
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
2、结构:
(1)抽象目标类:它提供了增加、删除观察者对象的抽象方法,以及通知所有观察者的抽象方法。
(2)具体目标类:它提供了一个用于保存观察者对象的聚集类,实现抽象目标中的增加、删除观察者对象的方法以及通知方法。
(3)抽象观察者类:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
(4)具体观察者类:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
3、实现代码:
(1)抽象目标类:
public interface Target { void addObserver(Observer observer); void removeObserver(Observer observer); void notifyObserver(); }
(2)具体目标类:
public class ConcreteTarget implements Target{ private List<Observer> observerList = new ArrayList<Observer>(); public void addObserver(Observer observer) { observerList.add(observer); } public void removeObserver(Observer observer) { observerList.remove(observer); } public void notifyObserver() { for (Observer observer:observerList ) { observer.responseMethod(); } } }
(3)抽象观察者类:
public interface Observer { void responseMethod(); }
(4)具体观察者类:
public class ConcreteObserver1 implements Observer{ public void responseMethod() { System.out.println("执行具体观察者1的方法"); } } public class ConcreteObserver2 implements Observer{ public void responseMethod() { System.out.println("执行具体观察者2的方法"); } }