设计模式分析

什么是设计模式?

设计模式是软件开发过程中经常遇到的问题的通用解决方案类似于前人总结的经验,遇到相似问题的时候有个参考。

设计模式七大基本原则?

  • 单一职责:一个类应该只作一件事情。将功能分为小的独立的单元。
  • 开放封闭原则:对扩展开放,对修改关闭。
  • 里氏替换原则:任何一个父类出现的地方,都可以用子类替换,而不会导致错误或者异常。
  • 依赖倒置:高层模块不应该依赖于底层,应该依赖于抽象,实现解耦。
  • 接口隔离:一个类不应该强迫它的客户端依赖于它们不需要的方法,接口应该小而专注,不应该包含多余的方法。

责任链模式?

  • 一种行为型设计模式,使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合。
  • 请求沿着链传递,直到有对象处理为止。
  • 分为三个角色:
    • Handler:抽象处理者,定义了一个处理请求的接口或者抽象类,通常会包含一个指向链中下一个处理者的引用。
    • ConcreteHandler:具体处理者,实现抽象处理者的处理方法,如果能处理就处理,不能就转发给下一个。
    • client:客户端,创建处理链,并向链的第一个处理者对象提交请求。
  • 工作流程:
    • 客户端将请求发送给链上的第一个处理者对象
    • 接收到请求后是否能处理
      • 可以就处理
      • 不可以就转发给链上的下一个处理者
    • 过程重复
  • 场景:
    • 过滤器链
    • 日志记录
    • 异常处理
    • 认证授权
  • 优缺点:
    • 降低耦合度
  • 实际举例:
    • 比如在线商店,用户下单的时候需要
      • 检查订单信息是否完整
      • 检查商品库存是否充足
      • 检查用户余额是否充足
      • 确认订单,更新商品库存和用户余额
public abstract OrderHandler{
    procted OrderHandler next;
    public void setNext(OrderHandler next){
    this.next=next;
}
    void handler(Order order);
}
public class CheckOrderHandler extends OrderHandler {
  
    @Override
    public void hand1e(Order order) {
//检查订单信息是否完整
        if (order.isInfoComplete()) {
//如果订单信息完整,则将请求传递给下一个处理者
            next.handle(order);
        } else {
//如果订单信息不完整,则直接返回错误信息
            throw new RuntimeException("订 单信息不完整");
        }
    }

    public class CheckStockHandler implements OrderHandler {

        public CheckStockHandler(OrderHandler next) {
            this.next = next;
        }

        @Override
        public void hand1e(Order order) {
//检查商品库存是否充足.
            if (order.getStock() >= order.getQuantity()) {
//如果库存充足,则将请求传递给下一个处理者
                next.handle(order); 
            } else {
//如果库存不足,则直接返回错误信息
                throw new RuntimeException(" 商品库存不足");
            }
        }
    }

    public class CheckBalanceHandler implements OrderHandler {
      

        public CheckBalanceHandler(OrderHandler next) {
            this.next = next;
        }

        @Override
        public void handle(Order order) {
//检查用户余额是否充足.
            if (order.getBalance() >= order.getAmount()) {
//如果余额充足,则将请求传递给下一个处理者.
                next.handle(order); 
            } else {
//如果余额不足,则直接返回错误信息
                throw new RuntimeException("用户 余额不足");
            }
        }
    }

    public class ConfirmOrderHandler implements OrderHandler {
        @Override
        public void handle(Order order) {
//确认订单,更新商品库存和用户余额
            order.confirm();
        }
    }
//客户端代码示例
        CheckOrderHandler checkOrderHandler = new
                CheckOrderHandler();
        CheckStockHandler checkStockHandler = new CheckStockHand1er();
        CheckBalanceHandler checkBalanceHandler = new CheckBalanceHandler();
        ConfirmOrderHandler conf
        irmOrderHandler =new

                ConfirmOrderHand1er();
//将处理器按照一定顺序组成责任链
        checkOrderHand1er.setNext(checkStockHandler);
        checkStockHand1er.setNext(checkBalanceHandler);
        checkBalanceHand1er.setNext(confirmOrderHandler);
        // 处理订单
        Order order = new Order();
        checkOrderHandler.handle(order);

工厂模式?

  • 创建型设计模式主要创建对现象,而不暴露对象的逻辑给客户端。
  • 简单工厂
    • 简单工厂模式的角色包括三个:

      • 抽象产品 角色

      • public abstract class Weapon {
            /**
             * 所有的武器都有攻击行为
             */
            public abstract void attack();
        }
      • 具体产品角色

      • public class Tank extends Weapon{
            @Override
            public void attack() {
                System.out.println("坦克开炮!");
            }
        }
        
        
        /**
         * 战斗机(具体产品角色)
         * @version 1.0
         * @className Fighter
         * @since 1.0
         **/
        public class Fighter extends Weapon{
            @Override
            public void attack() {
                System.out.println("战斗机投下原子弹!");
            }
        }
        
        
        /**
         * 匕首(具体产品角色)
         * @version 1.0
         * @className Dagger
         * @since 1.0
         **/
        public class Dagger extends Weapon{
            @Override
            public void attack() {
                System.out.println("砍他丫的!");
            }
        }
      • 工厂类 角色

      • public class WeaponFactory {
            /**
             * 根据不同的武器类型生产武器
             * @param weaponType 武器类型
             * @return 武器对象
             */
            public static Weapon get(String weaponType){
                if (weaponType == null || weaponType.trim().length() == 0) {
                    return null;
                }
                Weapon weapon = null;
                if ("TANK".equals(weaponType)) {
                    weapon = new Tank();
                } else if ("FIGHTER".equals(weaponType)) {
                    weapon = new Fighter();
                } else if ("DAGGER".equals(weaponType)) {
                    weapon = new Dagger();
                } else {
                    throw new RuntimeException("不支持该武器!");
                }
                return weapon;
            }
        }

        优点:不需要关注对象创建细节,要什么对象直接向工厂要就可以,初步实现了生产和消费的分离。缺点:工厂为上帝类,不能出问题;不符合OCP开闭原则,扩展时需要修改工厂类。

      • spring通过依赖注入和面向接口编程解决

  • 工厂方法
    • 工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点。

      工厂方法模式的角色包括:

      • 抽象工厂角色

      • 
        /**
         * 武器工厂接口(抽象工厂角色)
         * @author 动力节点
         * @version 1.0
         * @className WeaponFactory
         * @since 1.0
         **/
        public interface WeaponFactory {
            Weapon get();
        }
      • 具体工厂角色

      • /**
         * 具体工厂角色
         * @author 动力节点
         * @version 1.0
         * @className GunFactory
         * @since 1.0
         **/
        public class GunFactory implements WeaponFactory{
            @Override
            public Weapon get() {
                return new Gun();
            }
        }
        package com.powernode.factory;
        
        /**
         * 具体工厂角色
         * @author 动力节点
         * @version 1.0
         * @className FighterFactory
         * @since 1.0
         **/
        public class FighterFactory implements WeaponFactory{
            @Override
            public Weapon get() {
                return new Fighter();
            }
        }

      • 抽象产品角色

      • /**
         * 武器类(抽象产品角色)
         * @author 动力节点
         * @version 1.0
         * @className Weapon
         * @since 1.0
         **/
        public abstract class Weapon {
            /**
             * 所有武器都有攻击行为
             */
            public abstract void attack();
        }
      • 具体产品角色

      • /**
         * 具体产品角色
         * @author 动力节点
         * @version 1.0
         * @className Gun
         * @since 1.0
         **/
        public class Gun extends Weapon{
            @Override
            public void attack() {
                System.out.println("开枪射击!");
            }
        }
        package com.powernode.factory;
        
        /**
         * 具体产品角色
         * @author 动力节点
         * @version 1.0
         * @className Fighter
         * @since 1.0
         **/
        public class Fighter extends Weapon{
            @Override
            public void attack() {
                System.out.println("战斗机发射核弹!");
            }
        }

        扩展时增加一个产品+工厂,缺点:类爆炸

  • 抽象工厂模式:

    • 抽象工厂中包含4个角色:

      • 抽象工厂角色

      • public abstract class AbstractFactory {
            public abstract Weapon getWeapon(String type);
            public abstract Fruit getFruit(String type);
        }
      • 具体工厂角色

      • public class WeaponFactory extends AbstractFactory{
        
            public Weapon getWeapon(String type){
                if (type == null || type.trim().length() == 0) {
                    return null;
                }
                if ("Gun".equals(type)) {
                    return new Gun();
                } else if ("Dagger".equals(type)) {
                    return new Dagger();
                } else {
                    throw new RuntimeException("无法生产该武器");
                }
            }
        
            @Override
            public Fruit getFruit(String type) {
                return null;
            }
        }
        
        
        
        public class FruitFactory extends AbstractFactory{
            @Override
            public Weapon getWeapon(String type) {
                return null;
            }
        
            public Fruit getFruit(String type){
                if (type == null || type.trim().length() == 0) {
                    return null;
                }
                if ("Orange".equals(type)) {
                    return new Orange();
                } else if ("Apple".equals(type)) {
                    return new Apple();
                } else {
                    throw new RuntimeException("我家果园不产这种水果");
                }
            }
        }
      • 抽象产品角色

      • 具体产品角色

      • public abstract class Weapon {
            public abstract void attack();
        }
        package com.powernode.product;
        
        
        public class Gun extends Weapon{
            @Override
            public void attack() {
                System.out.println("开枪射击!");
            }
        }
        
        public class Dagger extends Weapon{
            @Override
            public void attack() {
                System.out.println("砍丫的!");
            }
        }

        优点:能保证一个工厂只使用一个类型的

        • 缺点:不符合OCP、

单例模式?

  • 首先从单例模式关键点入手:
    • 私有的构造方法
    • 私有静态实例变量
    • 共有静态方法
  • 常见的单例模式:
    • 饿汉式:final直接就保证了多线程的安全性了
public class Hungry {
    static final Hungry hungry=new Hungry();
    private Hungry(){
 
    }
    public static Hungry newInstance() {
        return hungry;
    }
 
}

  • 懒汉式:
public class Lazy {
    static Lazy lazy=null;
    private Lazy(){
 
    }
 
    public static synchronized Lazy newInstance() {
        if (lazy==null){
            lazy=new Lazy();
        }
        return lazy;
    }
 
    //双重锁定检查,这里的对象要用volatile,意义在于避免每次都加锁
    public static Lazy getInstance(){
        if (lazy==null){
            synchronized (Lazy.class){
                if (lazy==null){
                    lazy=new Lazy();
                }
            }
        }
        return lazy;
    }
}

两种,为了解决并发问题,一种是锁方法,第二种是双重锁定检查,双重的要加volatile

静态内部类:初始化的懒加载

public class Singleton {
    private Singleton() {}
 
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
 
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚举单例,防止反射攻击,实例在类加载时就创建,线程安全,反序列化其他的是通过UNSAFE机制创建对象,解决了破坏单例的问题,最好的,枚举常量事实上就是类加载时初始化时创建的对象!!!

public enum Singleton {
    SINGLETON(1);
    int value;

    Singleton(int value) {
        this.value = value;
    }
}
/**
 * javap -c反编译
 *  public static com.单例模式.Singleton valueOf(java.lang.String);
 *     Code:
 *        0: ldc           #1                  // class com/单例模式/Singleton
 *        2: aload_0
 *        3: invokestatic  #16                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
 *        6: checkcast     #1                  // class com/单例模式/Singleton
 *        9: areturn
 *
 *   static {};
 *     Code:
 *        0: new           #1                  // class com/单例模式/Singleton
 *        3: dup
 *        4: ldc           #30                 // String SINGLETON
 *        6: iconst_0
 *        7: iconst_1
 *        8: invokespecial #31                 // Method "<init>":(Ljava/lang/String;II)V
 *       11: putstatic     #3                  // Field SINGLETON:Lcom/单例模式/Singleton;
 *       14: invokestatic  #34                 // Method $values:()[Lcom/单例模式/Singleton;
 *       17: putstatic     #7                  // Field $VALUES:[Lcom/单例模式/Singleton;
 *       20: return
 * }
 */

单例模式带来的问题,和i++过程一样,需要三个步骤

分配内存空间给对象。
初始化对象。
将对象引用赋给引用变量。
但是因为指令重排,可能会变成
分配内存空间给对象。
将对象引用赋给引用变量。
初始化对象。
此时就出现了,后面进来的线程已经获得了引用,但是还没初始化,就会错误。所以要声明volatile

策略模式和模板设计模式?

  • 策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。策略模式让算法独立于使用它的客户而变化。
  • 模板方法模式:
    • 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
  • public enum Singleton {
        SINGLETON(1) {
            @Override
            int doSome() {
                return value;
            }
        };
        int value;
    
        Singleton(int value) {
            this.value = value;
        }
    
        public void doSomething() {
            System.out.println(doSome());
        }
    
        abstract int doSome();
    }

生产者消费者模式?

  •  概念:生产者—消费者模式是一种常见的设计模式,用于在多线程环境中协调生产者和消费者之间的工作。它通过使用一个共享的缓冲区来实现生产者和消费者之间的解耦,使得生产者和消费者可以独立地执行,而不会相互阻塞。

    • java可以用LinkedBlockingQueue实现!!!

  • public static void main(String[] args) throws InterruptedException {
            BlockingQueue<String> queue = new LinkedBlockingQueue<>();
            AtomicInteger integer = new AtomicInteger(1);
            Thread.ofVirtual().start(() -> {
                while (true) {
                    queue.add(integer.getAndIncrement() + "");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread.sleep(100);
            Thread.ofVirtual().start(() -> {
                while (true) {
                    try {
                        System.out.println(queue.poll(1, TimeUnit.MINUTES));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            Thread.sleep(10000);
        }
    

观察者模式?

  • 定义了对象间的一对多依赖关系,当一个对象的状态发生改变的时候,所有依赖与它的对象都会得到通知并且自动更新。

  • 示例:ABCD四个线程,当A线程完成后BCD启动

  • 抽象观察者:

    public abstract class 抽象观察者 extends Thread {
    
        protected void doSomething() {
            this.start();
        }
    }

  • 具体观察者:
    public class 具体观察者A extends 抽象观察者 {
        @Override
        public void run() {
            System.out.println("A观察者启动");
        }
    
    }
     
  •  抽象主题类:
    abstract class 抽象主题类 extends Thread{
        //维护观察者列表
        private final Set<抽象观察者> observers = new HashSet<>();
    
        // 注册观察者
        public void attach(抽象观察者 observer) {
            observers.add(observer);
        }
    
        // 移除观察者
        public void detach(抽象观察者 observer) {
            observers.remove(observer);
        }
    
        // 通知所有观察者
        protected void notifyObservers() {
            for (抽象观察者 observer : observers) {
                observer.doSomething();
            }
        }
    }

  • 具体主题类:
    public class 主题类 extends 抽象主题类{
    
    
        @Override
        public void run() {
            // 模拟线程A的工作
            System.out.println("线程A工作中...");
            try {
                Thread.sleep(2000); // 模拟一些工作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程A完成工作");
            // 通知所有观察者
            notifyObservers();
        }
    }
     

代理模式?

  • 代理类和目标类

  • 静态代理 

    • 静态代理就是保留目标对象,去增强去调用

    • 假设有一个目标对象OrderService

      public class Client {
          public static void main(String[] args) {
              // 创建目标对象
              OrderService target = new OrderServiceImpl();
              // 创建代理对象
              OrderService proxy = new OrderServiceProxy(target);
              // 调用代理对象的代理方法
              proxy.generate();
              proxy.modify();
              proxy.detail();
          }
      }

      缺点是一个接口就要写一个代理类,导致类爆炸,速度快

  • 动态代理
    •  JDK动态代理:这里可能会想,那岂不是所有方法都要执行invoke了,其实可以在invoke中加判断是否被这个注解修饰了
    • public static void main(String[] args) {
              // 第一步:创建目标对象
              OrderService target = new OrderServiceImpl();
              // 第二步:创建代理对象
              OrderService orderServiceProxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), 调用处理器对象);
              // 第三步:调用代理对象的代理方法
              orderServiceProxy.detail();
      }
      
      public class TimerInvocationHandler implements InvocationHandler {
          // 目标对象
          private Object target;
      
          // 通过构造方法来传目标对象
          public TimerInvocationHandler(Object target) {
              this.target = target;
          }
      
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              return null;
          }
      }

    • CGLIB动态代理:通过继承的方式
      •  
        public static void main(String[] args) {
                // 创建字节码增强器
                Enhancer enhancer = new Enhancer();
                // 告诉cglib要继承哪个类
                enhancer.setSuperclass(UserService.class);
                // 设置回调接口
                enhancer.setCallback(方法拦截器对象);
                // 生成源码,编译class,加载到JVM,并创建代理对象
                UserService userServiceProxy = (UserService)enhancer.create();
        
                userServiceProxy.login();
                userServiceProxy.logout();
        
            }
        public class TimerMethodInterceptor implements MethodInterceptor {
            @Override
            public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                // 前增强
                long begin = System.currentTimeMillis();
                // 调用目标
                Object retValue = methodProxy.invokeSuper(target, objects);
                // 后增强
                long end = System.currentTimeMillis();
                System.out.println("耗时" + (end - begin) + "毫秒");
                // 一定要返回
                return retValue;
            }
        }

        为什么有了JDK动态代理还要有CGLIB:无接口的类和更高的性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值