1.单例模式
应用场景:顾名思义,自始至终都操作的是同一个对象的时候,需要用单例模式
/**
* 单例懒汉式(比较常用)
*/
public class SingletonPatternLazy {
private static SingletonPatternLazy singletonPattern = null;
//私有构造
private SingletonPatternLazy(){}
//获取实例
public static SingletonPatternLazy getInstance(){
return SingletonPatternInstance.SingletonPatternLazy;
}
//内部类中初始化SingletonPatternLazy的实例
private static class SingletonPatternInstance {
private final static SingletonPatternLazy singletonPattern = new SingletonPatternLazy();
}
}
/**
* 单例饿汉式(没什么用,知道有就行了)
*/
public class SingletonPattern {
//初始化实例
private final static SingletonPattern singletonPattern = new SingletonPattern();
//私有构造
private SingletonPattern(){}
//获取实例
public static SingletonPattern getInstance(){
return singletonPattern;
}
}
//main方法测试
public static void testSingletonPattern(){
//线程1获取一次实例并打印
Thread thread1 = new Thread(new Runnable() {
public void run() {
SingletonPatternLazy instance = SingletonPatternLazy.getInstance();
System.out.println(instance);
}
});
//线程2获取一次实例并打印
Thread thread2 = new Thread(new Runnable() {
public void run() {
SingletonPatternLazy instance = SingletonPatternLazy.getInstance();
System.out.println(instance);
}
});
thread1.start();
thread2.start();
}
这里有一个小小的误区:
/**
* 单例懒汉式(这种方式有bug)
*/
public class SingletonPatternLazy {
private static SingletonPatternLazy singletonPattern = null;
//私有构造
private SingletonPatternLazy(){}
//同步获取实例
private static synchronized SingletonPatternLazy newInstance(){
return new SingletonPatternLazy();
}
//如果为实例null才同步获取实例
public static SingletonPatternLazy getInstance(){
if(singletonPattern == null){
singletonPattern = newInstance();
}
return singletonPattern;
}
}
上述代码也是一种单例模式,bug就在于,如果在同步获取实例的时候,有一个比较耗时的操作,那么会导致第二个线程进来的时候,第一个线程的singletonPattern 仍然未获取到实例,因此会去新获取一个实例,存在线程安全,这种方法正确的写法是:
/**
* 单例懒汉式(最标准的单例模式)
*/
public class SingletonPatternLazy {
private static SingletonPatternLazy singletonPattern = null;
//私有构造
private SingletonPatternLazy(){}
//如果为实例null才同步获取实例
public static synchronized SingletonPatternLazy getInstance(){
if(singletonPattern == null){
singletonPattern = new SingletonPatternLazy();
}
return singletonPattern;
}
}
但这种方式在多线程环境下每次获取实例的时候都同步执行,效率低,不推荐
2.工厂方法模式
应用场景:
当我们需要获取同一规范下的各个不同实现的对象,并且再获取这些对象的时候比较麻烦的情况下,可以考虑使用工厂模式。
在扩展规范的实现的时候,同时又需要去扩展工厂,为了便于扩展,适应于开闭原则,因此产生了工厂方法模式,即一个工厂只创建规范下的一个实现的对象。
不同的对象的创建对应不同的工厂,那么这些不同的工厂就可以抽象出一个模板出来,或者提前定义一个接口出来。
/*
* 需要被使用工厂创建的source
*/
//Person规范
public interface Person {
void work();
}
//Person的一个具体实现,Man
public class Man implements Person {
private Man(){}
public void work() {
System.out.println("Man work...");
}
}
//Person的一个具体实现,Women
public class Women implements Person {
private Women(){}
public void work() {
System.out.println("Women work...");
}
}
/*
* 工厂相关
*/
//工厂规范
public interface PersonFactory {
Person getInstance() throws Exception;
}
//工厂规范的一个实现ManFactory
public class ManFactory implements PersonFactory {
private final String CLASSFORNAME = "cn.qu.factorymethod.po.Man";
private Man man = null;
//同步获取Man的实例,之所以用同步是因为融入了单例模式
public synchronized Man getInstance() throws Exception {
if(man == null){
@SuppressWarnings("unchecked")
Class<Man> forName = (Class<Man>) Class.forName(CLASSFORNAME);
Constructor<Man> declaredConstructor = forName.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
man = declaredConstructor.newInstance();
}
return man;
}
}
//工厂规范的一个实现WomenFactory
public class WomenFactory implements PersonFactory {
private final String CLASSFORNAME = "cn.qu.factorymethod.po.Women";
private Women women = null;
public synchronized Women getInstance() throws Exception {
if(women == null){
@SuppressWarnings("unchecked")
Class<Women> forName = (Class<Women>) Class.forName(CLASSFORNAME);
Constructor<Women> declaredConstructor = forName.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
women = declaredConstructor.newInstance();
}
return women;
}
}
/*
* 工厂方法模式测试
*/
public static void testFactoryMethod() {
try{
final ManFactory manFactory = new ManFactory();
final WomenFactory womenFactory = new WomenFactory();
Thread thread1 = new Thread(new Runnable() {
public void run() {
try {
Man man = manFactory.getInstance();
System.out.println("thread1.man:" + man);
Women women = womenFactory.getInstance();
System.out.println("thread1.women:" + women);
} catch (Exception e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
Man man = manFactory.getInstance();
System.out.println("thread2.man:" + man);
Women women = womenFactory.getInstance();
System.out.println("thread2.women:" + women);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}catch (Exception e) {
e.printStackTrace();
}
}
3.静态代理模式
应用场景:用的不太多,一般用动态代理
//被代理的规范
public interface IPerson {
void doSome();
}
//被代理的实现
public class Person implements IPerson{
public void doSome(){
System.out.println("基本功能...");
}
}
//代理类
public class PersonProxy implements IPerson{
private IPerson person;
//构造需要一个被代理的对象
public PersonProxy(IPerson person){
this.person = person;
}
public void doSome(){
before();
person.doSome();
after();
}
public void before(){
System.out.println("before...");
}
public void after(){
System.out.println("after...");
}
}
/*
*测试静态代理
*/
public static void testProxy(){
IPerson proxy = new PersonProxy(new Person());
proxy.doSome();
}
4.动态代理模式
应用场景:spring的aop底层就是基于动态代理,当我们需要横向且动态对程序进行扩展,即扩展任意对象的方法的时候,可以用到动态代理
//被代理规范
public interface ISource {
void doSome(String inputSome);
}
//被代理的实现
public class SourceImpl implements ISource{
public void doSome(String inputSome){
System.out.println("基本功能,输出内容:" + inputSome);
}
}
//创建一个简单的代理内容的实现类
public class BeforeAfterInvocationHandler implements InvocationHandler {
private Object source;
public BeforeAfterInvocationHandler(Object source){
this.source = source;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
method.invoke(source, args);
after();
return null;
}
public void before(){
System.out.println("------执行before-------");
}
public void after(){
System.out.println("------执行after-------");
}
/**
* 获取t对象的代理对象
* @param t 被代理的对象
* @return 返回代理对象
*/
@SuppressWarnings("all")
public static <T> T getProxy(T t){
BeforeAfterInvocationHandler invocationHandler = new BeforeAfterInvocationHandler(t);
Class[] interfaces = t.getClass().getInterfaces();
T tProxy = (T) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(), interfaces, invocationHandler);
return tProxy;
}
}
//测试动态代理
public static void testDynamicProxy(){
ISource source = new SourceImpl();
BeforeAfterInvocationHandler.getProxy(source).doSome("这是动态代理测试的输出内容");
}
5.装饰者模式
应用场景:当我们需要动态的横向扩展程序的时候,即动态的扩展某一对象的方法,可以用装饰者模式
注意与动态代理的区别:
动态代理是对任意对象的方法扩展,但扩展的内容是固定不变的
装饰者模式是对某一个对象的方法扩展,扩展的内容是可以动态变化的
//被装饰的规范
public interface IPerson {
void doSome();
}
//被装饰规范的实现
public class PersonImpl implements IPerson {
public void doSome() {
System.out.println("吃饭功能....");
}
}
//抽象装饰器
public abstract class PersonDecorator implements IPerson {
private IPerson person;
public PersonDecorator(IPerson person){
this.person = person;
}
//调用当前构造中接受的person实例的dosome()
public void doSome() {
person.doSome();
}
}
//装饰器Student
public class Student extends PersonDecorator {
//构造需要提供一个person实例
public Student(IPerson person){
//把构造参数交给父类
super(person);
}
public void doSome(){
/*
*首先,调用父类的doSome()
*然后,父类中又调用当前构造中接受的person实例的dosome()
*/
super.doSome();
System.out.println("学习功能...");
}
}
//装饰器Worker
public class Worker extends PersonDecorator {
public Worker(IPerson person){
super(person);
}
public void doSome(){
super.doSome();
System.out.println("工作功能...");
}
}
//测试装饰者模式
public static void testDecorator(){
//基本的person
PersonImpl person = new PersonImpl();
System.out.println("--------------person: --------------");
//基本的person所做的事
person.doSome();
//被worker装饰过的基本person
Worker worker = new Worker(person);
System.out.println("--------------worker: --------------");
//被worker装饰过的person所做的事
worker.doSome();
//被学生装饰过的worker
Student student = new Student(worker);
System.out.println("--------------student: --------------");
//被学生装饰过的worker所做的事
student.doSome();
}
6.适配器模式
6.1类适配
应用场景:比如应用中有一个类A,还有一个规范B,且规范B的某一个或多个方法具有和类A相同的实现,因此就不需要再单独去实现这些方法了,可以新增一个规范B的适配器类C,直接去继承类A,然后再实现规范B剩下的方法(当然前提是不去让类A直接实现规范B)
//适配的类型SourceCamera
public class SourceCamera {
public void photograph(){
System.out.println("拍照功能...");
}
}
//被适配的规范IPhone
public interface IPhone {
public void call();
public void photograph();
}
//适配器PhoneAdapter
public class PhoneAdapter extends SourceCamera implements IPhone {
public void call() {
System.out.println("打电话功能...");
}
}
//测试适配器模式(适配类)
public static void testAdapter() {
IPhone phone = new PhoneAdapter();
phone.call();
phone.photograph();
}
6.2对象适配
应用场景:与上述类似,只是类A中的方法与规范B中方法的声明不同,但是同时还想让规范B具有类A的功能,那么可以新增一个规范B的适配器类C,在构造类C的时候,把类A的对象传进来,在类C中调用类A的相关方法
//适配的类型SourceCamera
public class SourceCamera {
public void paizhao(){
System.out.println("拍照功能...");
}
}
//被适配的规范IPhone
public interface IPhone {
public void call();
public void photograph();
}
//适配器PhoneAdapter
public class PhoneAdapter implements IPhone {
private SourceCamera camera;
public PhoneAdapter(){}
public PhoneAdapter(SourceCamera camera){
this.camera = camera;
}
public void call() {
System.out.println("打电话功能...");
}
public void photograph() {
camera.paizhao();
}
}
//测试适配器模式(适配对象)
public static void testAdapter() {
IPhone phone = new PhoneAdapter(new SourceCamera());
phone.call();
phone.photograph();
}
6.3接口适配
应用场景:如果需要分别实现规范中的方法,可以使用这种模式
//被适配的规范
public interface IPhone {
public void call();
public void photograph();
public void music();
public void sendMsg();
}
//抽象适配器
public abstract class PhoneAdapter implements IPhone {
public void call() {
System.out.println("call........");
}
public void photograph(){}
public void music(){}
public void sendMsg() {
System.out.println("sendMsg........");
}
}
//适配的类型MiPhone
public class MiPhone extends PhoneAdapter{
@Override
public void photograph() {
System.out.println("MiPhone.photograph...");
}
}
//适配的类型VivoPhone
public class VivoPhone extends PhoneAdapter {
@Override
public void music() {
System.out.println("VivoPhone.music...");
}
}
//测试接口适配
public static void testAdapter() {
IPhone miPhone = new MiPhone();
miPhone.call();
miPhone.photograph();
IPhone vivoPhone = new VivoPhone();
vivoPhone.sendMsg();
vivoPhone.music();
}
7.桥接模式
应用场景:当我们需要操作规范,但又无法固定实现的时候,可以提供一组规范,让客户方来实现,我们操作的时候只需注入客户方的实现对象,这种模式就是桥接模式,例如:jdbc定义了驱动规范,各个数据库厂商提供不同的驱动实现
//需要桥接的规范IBridgeAble
public interface IBridgeAble {
public void doSome(String arg0, String arg1);
}
//定义对该规范的伪实现BridgeAble
public class BridgeAble implements IBridgeAble {
private IBridgeAble bridgeAble;
public BridgeAble(IBridgeAble bridgeAble){
this.bridgeAble = bridgeAble;
}
public void doSome(String arg0, String arg1) {
bridgeAble.doSome(arg0, arg1);
}
}
//A客户方提供的实现BrideAbleImplA
public class BrideAbleImplA implements IBridgeAble{
public void doSome(String arg0, String arg1) {
System.out.println("BrideAbleImplA.arg0: " + arg0 + " BrideAbleImplA.arg1: " + arg1);
}
}
//B客户方提供的实现BrideAbleImplB
public class BrideAbleImplB implements IBridgeAble{
public void doSome(String arg0, String arg1) {
System.out.println("BrideAbleImplB.arg0: " + arg0 + " BrideAbleImplB.arg1: " + arg1);
}
}
//测试桥接模式
public static void testBridge(){
BridgeAble bridge = new BridgeAble(new BrideAbleImplA());
bridge.doSome("A", "A1");
}
8.观察者模式
应用场景:观察者模式略微难理解,但十分重要,例如监听器就需要使用观察者模式来实现
//定义观察者规范
public interface IObserver {
public void operate();
}
//观察者ObserverOne,额外提供了单例模式获取对象,通常情况观察者,都是单例的
public class ObserverOne implements IObserver{
private ObserverOne(){}
public void operate() {
System.out.println("观察者1观察到了变化");
}
public static ObserverOne getInstance(){
return GetInstance.object;
}
private static class GetInstance{
private final static ObserverOne object = new ObserverOne();
}
}
//观察者ObserverTwo
public class ObserverTwo implements IObserver{
public ObserverTwo(){}
public void operate() {
System.out.println("观察者2观察到了变化");
}
public static ObserverTwo getInstance(){
return GetInstance.object;
}
static class GetInstance{
private final static ObserverTwo object = new ObserverTwo();
}
}
//抽象的观察对象BeObserver
public abstract class BeObserver {
private Set<IObserver> observers = new HashSet<IObserver>();
//添加观察者
public void addObserver(IObserver observer){
observers.add(observer);
}
//删除观察者
public void removeObserver(IObserver observer){
observers.remove(observer);
}
//通知所有观察者
public void notifyObservers(){
for (IObserver observer : observers) {
observer.operate();
}
}
public abstract void doSome();
}
//观察的对象BeObserverImpl
public class BeObserverImpl extends BeObserver{
@Override
public void doSome() {
boolean isNotify = false;
//执行一段逻辑后判断,是否需要通知观察者
isNotify = true;
if(isNotify){
//通知所有的观察者
super.notifyObservers();
}
}
}
//测试观察者模式
public static void testObserver(){
//构建一个观察对象
BeObserver beObserver = new BeObserverImpl();
//添加观察者
beObserver.addObserver(ObserverOne.getInstance());
beObserver.addObserver(ObserverTwo.getInstance());
//观察对象做了一些事情,并被观察者观察到
beObserver.doSome();
}