设计模式

设计模式分类

创建型模式

  1. 工厂方法模式
  2. 抽象工厂模式
  3. 建造者模式
  4. 单例模式
  5. 原型模式

结构型模式

  1. 适配器模式
  2. 装饰者模式
  3. 代理模式
  4. 外观模式
  5. 桥接模式
  6. 组合模式
  7. 享元模式

行为型模式

  1. 策略模式
  2. 观察者模式
  3. 责任链模式
  4. 备忘录模式
  5. 模板方法模式
  6. 迭代器模式
  7. 中介者模式
  8. 命令模式
  9. 访问者模式
  10. 解释器模式
  11. 状态模式

单例模式

定义:保证一个类仅有一个实例,并提供一个全局访问点

使用场景:想保证任何情况下都绝对只有一个实例

优点:

  • 在内存里只有一个实例,减少开销
  • 避免对资源的多重占用
  • 设置全局访问点,严格控制访问

缺点:

  • 没有借口,扩张困难

重点:

  • 私有构造器
  • 延迟加载
  • 线程安全
  • 序列化和反序列化安全
  • 反射

代码实现

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());

    }
}

相关案例

img
img
img

观察者模式

定义:定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主对象,当主对象发生变化时,其他观察者都会收到通知并更新

提供了比继承更有弹性的替代方案(扩展原有对象功能)

使用场景:

  • 关联行为场景,建立一套触发机制

优点:

  • 观察者和被观察者之间建立一个抽象的耦合
  • 支持广播通信

缺点:

  • 过多细节依赖,增加时耗和程序复杂度
  • 要避免循环调用

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的内容");
    }
}

相关案例

img

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值