常见设计模式
一.设计模式的基本原则
1. S 单一职责 single
一个模块负责一个功能
一个类负责一个业务
一个API去实现一个功能
不同的功能分隔开。一个类如果需要变化,最好只能有一个维度的原因。
2. O 开闭原则 open
对什么开放:对扩展开放
扩展:新功能—》可以(提倡)去增加代码(增加一个类)
项目不断迭代(增加新的需求)
对什么封闭:对修改封闭
不建议去修改代码 (尤其是一些底层的API)
牵一发而动全身。
3. L Loskov原则(里氏替换原则)
里氏替换原则(LSP)指的是所有引用基类的地方都可以透明的使用其子类的对象
可以理解为:只要有父类出现的地方,都可以使用子类来替代。而且不会出现任何错误或者异常。但是反过来却不行。子类出现的地方,不能使用父类来替代。
//写法1
UserDao dao = new UserDaoImpl2();
dao.findUserByid();
dao.findUserByName();
//写法2
UserDaoImpl2 dao = new UserDaoImpl2 ();
dao.findUserByid();
dao.findUserByName();
idea帮我们重写的equal就不满足里氏替换原则,它重写的方法不能再同父类比较,返会的都是false
4 . I 接口隔离原则
接口:interface (功能)
隔离:分开
不同功能的接口,最好放在不同的interface里。
一个接口里最好不要集成太多的功能,
否则用户去实现该接口会比较麻烦。
5. D 依赖倒置原则 depend(Spring DI IOC APSPECTJ)
具体依赖于抽象,而非抽象依赖于具体。
先去设计抽象的DAO (接口)
二.常见设计模式
1. 单例模式(Singleton Pattern)
全局只包含一个自己的实例
哪些场合需要用到单例?
Servlet
ServletContext
1.1 单例:线程不安全的懒汉
public class Singleton{
private static Singleton singleton1;
private Singleton();
public static Singlton getSingleton(){
if(singleton1!=null){
return singleton1;
}
return singlteton1=new Singleton();
}
}
1.2 单例:线程安全的懒汉
public class Singleton{
private static Singleton singleton1;
private Singleton();
public static synchronized Singleton getSingleton(){
if(singleton1==null){
return singleton1=new Singleton();
}
else
return singleton1;
}
}
1.3 单例:线程安全的立即加载
public class Singleton{
private Singleton();
private static Singleton Singleton1=new Singleton();
public static Singleton getSingleton(){
return singleton1;
}
}
1.4 单例:线程安全的懒加载--静态内部类实现
public class Singleton{
private Singleton();
public static Singleton getsingleton1(){
return inner.getsingletion();
}
static class inner{
private static Singleton singleton1=new Singleton();
public static Singleton getSingleton(){
return singleton1;
}
}
}
2. 工厂模式 (Factory Pattern)
生成产品的工厂,生产对象
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
Animal animal = AnimalFactory.create();
2.1 简单工厂
通过给定的参数的不同,返回不同的实例
当我们去新增新的实例的时候,需要修改代码(和开闭原则有些许出入)
2.2 工厂方法
通过接口指定工厂的规范
工厂方法模式,创建一个工厂接口和创建多个工厂实现类
完全遵从开闭原则,不对任何已有代码进行修改,直接新增一个类。
3. 建造者 (Builder Pattern)
侧重点:参数的设置
4. 代理模式(Proxy Pattern)
KeXue上网——代理服务器
为某个对象提供一个代理对象以控制对这个对象的访问
代理对象:中介
代理类 负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
被代理对象(委托类):业主。
代理类
负责为 委托类 预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
包装对象 和 被包装对象 能不能看成是一种代理?
代理对象:包装对象
被代理对象:被包装对象。
4.1 静态代理
4.2 动态代理
4.2.1 jdk动态代理
jdk动态代理的委托类必须实现 InvocationHandler接口,重写 Proxy.newProxyInstance方法。
jdk提供了一个Proxy类。有一个静态方法,可以用来产生动态代理对象。
如何使用
Modifier and Type | Method and Description |
---|---|
static Object |
newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h) 返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。 |
传入参数:
Loader有个要求,代理对象的类加载器要跟被代理对象的一致。
Interfaces 被代理对象的接口
InvocationHandler 调用处理器:匿名内部类:传入对象:(Object proxy, Method method ,Object[] args)
Object proxy: 生成的代理对象
Method :代理对象正在执行的方法
Object[] args :调用代理对象执行方法的参数(因为传入参数有可能是一个或者多个所以用数组存储)
Object invoke = method.invoke(委托类对象,args):这里传入的args可以在传入之间进行处理
返回值就是委托类对象对应方法执行后的返回值
委托类:房东 代理类:中介 调用代理类的方法,代理类对传入的参数处理后再交给委托类
用于事务,TransactionUtil是事务工具类,具体的事务开始关闭在Transactionutil中实现
也可以将