设计模式分类
创建型模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 单例模式
- 原型模式
结构型模式
行为型模式
- 策略模式
- 观察者模式
- 责任链模式
- 备忘录模式
- 模板方法模式
- 迭代器模式
- 中介者模式
- 命令模式
- 访问者模式
- 解释器模式
- 状态模式
单例模式
定义:保证一个类仅有一个实例,并提供一个全局访问点
使用场景:想保证任何情况下都绝对只有一个实例
优点:
- 在内存里只有一个实例,减少开销
- 避免对资源的多重占用
- 设置全局访问点,严格控制访问
缺点:
- 没有借口,扩张困难
重点:
- 私有构造器
- 延迟加载
- 线程安全
- 序列化和反序列化安全
- 反射
代码实现
HungrySingleton
public class HungrySingleton implements Serializable,Cloneable{
private final static HungrySingleton hungrySingleton;
static{
hungrySingleton = new HungrySingleton();
}
//反射攻击解决方案
private HungrySingleton(){
if(hungrySingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
//序列化破坏单例模式原理及解决方案
private Object readResolve(){
return hungrySingleton;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return getInstance();
}
}
LazySingleton
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton(){
if(lazySingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
public synchronized static LazySingleton getInstance(){
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
LazyDoubleCheckSingleton
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
private LazyDoubleCheckSingleton(){
}
public static LazyDoubleCheckSingleton getInstance(){
if(lazyDoubleCheckSingleton == null){
synchronized (LazyDoubleCheckSingleton.class){
if(lazyDoubleCheckSingleton == null){
lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
}
}
}
return lazyDoubleCheckSingleton;
}
}
StaticInnerClassSingleton
public class StaticInnerClassSingleton {
private static class InnerClass{
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance(){
return InnerClass.staticInnerClassSingleton;
}
private StaticInnerClassSingleton(){
if(InnerClass.staticInnerClassSingleton != null){
throw new RuntimeException("单例构造器禁止反射调用");
}
}
}
EnumInstance
public enum EnumInstance {
INSTANCE{
protected void printTest(){
System.out.println("Print Test");
}
};
protected abstract void printTest();
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static EnumInstance getInstance(){
return INSTANCE;
}
}
ContainerSingleton
public class ContainerSingleton {
private ContainerSingleton(){
}
private static Map<String,Object> singletonMap = new HashMap<String,Object>();
public static void putInstance(String key,Object instance){
if(StringUtils.isNotBlank(key) && instance != null){
if(!singletonMap.containsKey(key)){
singletonMap.put(key,instance);
}
}
}
public static Object getInstance(String key){
return singletonMap.get(key);
}
}
ThreadLocalInstance
public class ThreadLocalInstance {
private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal
= new ThreadLocal<ThreadLocalInstance>(){
@Override
protected ThreadLocalInstance initialValue() {
return new ThreadLocalInstance();
}
};
private ThreadLocalInstance(){
}
public static ThreadLocalInstance getInstance(){
return threadLocalInstanceThreadLocal.get();
}
}
相关案例
代理模式
定义:为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介的作用
使用场景:保护目标对象、增强目标对象
优点:
- 能将代理对象与真实被调用的目标对象分离
- 一定程度上减低了系统的耦合度,扩展性好
- 保护目标对象、增强目标对象
缺点:
- 造成系统设计中类的数目增加
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
- 增加系统的复杂度
分类:
- 静态代理
- 动态代理(JDK、CGLib)
Spring代理方式选择:
- 当Bean有实现接口时,Spring使用JDK动态代理
- 当Bean没有实现接口时,Spring使用CGLib动态代理
-
可以强制使用CGLib
在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
参考资料:参考资料
- JDK比CGLib快20%
模式对比:
- 代理vs装饰者
- 代理vs适配器
静态代理
UML类图
代码实现
此处省略service、dao接口及其实现
//静态代理类
public class OrderServiceStaticProxy {
private IOrderService iOrderService;
public int saveOrder(Order order){
beforeMethod(order);
iOrderService = new OrderServiceImpl();
int result = iOrderService.saveOrder(order);
afterMethod();
return result;
}
private void beforeMethod(Order order){
System.out.println("静态代理 before code");
}
private void afterMethod(){
System.out.println("静态代理 after code");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(2);
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
orderServiceStaticProxy.saveOrder(order);
}
}
动态代理
UML类图
代码实现
//
public class OrderServiceDynamicProxy implements InvocationHandler {
private Object target;
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
public Object bind(){
Class cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object argObject = args[0];
beforeMethod(argObject);
Object object = method.invoke(target,args);
afterMethod();
return object;
}
private void beforeMethod(Object obj){
System.out.println("动态代理 before code" + obj);
}
private void afterMethod(){
System.out.println("动态代理 after code");
}
}
//
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(1);
IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
orderServiceDynamicProxy.saveOrder(order);
}
}
$Proxy0是由return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);而来的,该类继承了Proxy,实现了Interface:IOrderService。具体分析参考:java动态代理中的invoke方法是如何被自动调用的
相关案例
装饰者模式
定义:再不改变原有对象的基础上,将功能附加到对象上
提供了比继承更有弹性的替代方案(扩展原有对象功能)
使用场景:
- 扩展一个类的功能或给一个类添加附加职责
- 动态给一个对象添加功能,这些功能可以再动态撤销
优点:
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
- 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
- 符合开闭原则
缺点:
- 出现更多的代码、跟多的类、增加程序复杂性
- 动态装饰时,多层装饰时会更复杂
模式对比:
- 装饰者vs代理
- 装饰者vs适配器
UML类图
代码实现
//
public abstract class ABattercake {
protected abstract String getDesc();
protected abstract int cost();
}
public class Battercake extends ABattercake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
//
public abstract class AbstractDecorator extends ABattercake {
//重点是ABattercake
private ABattercake aBattercake;
public AbstractDecorator(ABattercake aBattercake) {
this.aBattercake = aBattercake;
}
protected abstract void doSomething();
@Override
protected String getDesc() {
return this.aBattercake.getDesc();
}
@Override
protected int cost() {
return this.aBattercake.cost();
}
}
//
public class EggDecorator extends AbstractDecorator {
public EggDecorator(ABattercake aBattercake) {
super(aBattercake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc()+" 加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost()+1;
}
}
//
public class SausageDecorator extends AbstractDecorator{
public SausageDecorator(ABattercake aBattercake) {
super(aBattercake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc()+" 加一根香肠";
}
@Override
protected int cost() {
return super.cost()+2;
}
}
//
public class Test {
public static void main(String[] args) {
ABattercake aBattercake;
aBattercake = new Battercake();
aBattercake = new EggDecorator(aBattercake);
aBattercake = new EggDecorator(aBattercake);
aBattercake = new SausageDecorator(aBattercake);
System.out.println(aBattercake.getDesc()+" 销售价格:"+aBattercake.cost());
}
}
相关案例
<span id="decorator">观察者模式</span>
定义:定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主对象,当主对象发生变化时,其他观察者都会收到通知并更新
提供了比继承更有弹性的替代方案(扩展原有对象功能)
使用场景:
- 关联行为场景,建立一套触发机制
优点:
- 观察者和被观察者之间建立一个抽象的耦合
- 支持广播通信
缺点:
- 过多细节依赖,增加时耗和程序复杂度
- 要避免循环调用
UML类图
代码实现
public class Question {
private String userName;
private String questionContent;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getQuestionContent() {
return questionContent;
}
public void setQuestionContent(String questionContent) {
this.questionContent = questionContent;
}
}
//
public class Course extends Observable{
private String courseName;
public Course(String courseName) {
this.courseName = courseName;
}
public String getCourseName() {
return courseName;
}
public void produceQuestion(Course course, Question question){
System.out.println(question.getUserName()+"在"+course.courseName+"提交了一个问题");
setChanged();
notifyObservers(question);
}
}
//
public class Teacher implements Observer{
private String teacherName;
public Teacher(String teacherName) {
this.teacherName = teacherName;
}
@Override
public void update(Observable o, Object arg) {
Course course = (Course)o;
Question question = (Question)arg;
System.out.println(teacherName+"老师的"+course.getCourseName()+"课程接收到一个"+question.getUserName()+"提交的问答:"+question.getQuestionContent());
}
}
//
public class Test {
public static void main(String[] args) {
Course course = new Course("Java设计模式");
Teacher teacher1 = new Teacher("Alpha");
Teacher teacher2 = new Teacher("Beta");
course.addObserver(teacher1);
course.addObserver(teacher2);
//业务逻辑代码
Question question = new Question();
question.setUserName("Andy");
question.setQuestionContent("Java的主函数如何编写");
course.produceQuestion(course,question);
}
}
//Guava observer
public class GuavaEvent {
//在观察者的方法上添加注解@Subscribe
@Subscribe
public void subscribe(String str){
//业务逻辑
System.out.println("执行subscribe方法,传入的参数是:" + str);
}
}
//Guava Test
public class GuavaEventTest {
public static void main(String[] args) {
EventBus eventbus = new EventBus();
GuavaEvent guavaEvent = new GuavaEvent();
eventbus.register(guavaEvent);
eventbus.post("post的内容");
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。