Java 日常开发中常用的几种设计模式

276 阅读4分钟

单例模式

单例模式有多种,此处只列举几种推荐的方法

静态内部类(饿汉)

/**
 * 静态内部类实现
 */
public class SingletonDemo3 {

    private static class SingletonClassInstance{
        private static final SingletonDemo3 instance=new SingletonDemo3();
        static {
            System.out.println("静态内部类创建");
        }
    }

    public SingletonDemo3(){
        System.out.println("SingletonDemo3创建");
    }

    public static SingletonDemo3 getInstance(){
        return SingletonClassInstance.instance;
    }

    public  void test(){
        System.out.println("1");
    }
}

双检锁(懒汉)


/**
 * 双检锁/双重校验锁
 * Created by HeyS1 on 2018/2/26.
 */
public class DoubleLock {
    private volatile static DoubleLock singleton;
    public static DoubleLock getSingleton() {
        if (singleton == null) {
            synchronized (DoubleLock.class) {
                if (singleton == null) {
                    singleton = new DoubleLock();
                }
            }
        }
        return singleton;
    }
}

枚举(推荐)

/**
 * 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
 * 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,
 * 绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
 * 不能通过 reflection attack 来调用私有构造方法。
 *
 *    public static void main(String[] args){
        EnumLoading.INSTANCE.otherMethods();
      }
 */
enum EnumLoading {

    INSTANCE;

    public void otherMethods() {
        System.out.println("Something");
    }
}

工厂模式

工厂模式有效解决了创建对象时的不确定性。使用的办法就是将创建对象的时机延迟到了每一个具体的创建工厂中,让具体工厂自行解决对象的复杂创建过程

mybatis中的org.apache.ibatis.logging.LogFactory是一个经典的例子,以下demo代码模拟一个简单的LogFactory


/**
 * @author yejunxi 2022/02/18
 */
public class FactoryDemo {

    public interface Log {
        void info();
    }

    public class Log4j implements Log {
        @Override
        public void info() {
        }
    }

    public class LogBack implements Log {
        @Override
        public void info() {

        }
    }

    public static class Factory {
        /**
         * 此处不一定是传clazz,也可以是string等,根据业务灵活变动
         */
        public static <T> T getLog(Class<? extends T> clazz) {
            try {
                return clazz.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public static void main(String[] args) {
        Log log4j = Factory.getLog(Log4j.class);
        Log logback = Factory.getLog(LogBack.class);
        //...
    }
}

代理模式

/**
 * 代理模式
 */
public class Test {

    interface OrderService {
        void save();
    }

    static class OrderServiceImpl implements OrderService {
        @Override
        public void save() {
            System.out.println("保存订单");
        }
    }

    static class OrderProxy implements InvocationHandler {
        private OrderService orderService;

        public OrderService getProxyInterface(OrderService orderService) {
            this.orderService=orderService;
            return (OrderService) Proxy.newProxyInstance(
                    orderService.getClass().getClassLoader(),
                    orderService.getClass().getInterfaces(),
                    this
            );
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("打印日志,当前执行的方法名:" + method.getName());
            return method.invoke(orderService, args);
        }
    }

    public static void main(String[] args) {
        //订单service
        OrderService orderService=new OrderServiceImpl();
        //代理
        OrderProxy proxy = new OrderProxy();
        OrderService orderServiceProxy = proxy.getProxyInterface(orderService);
        //执行方法
        orderServiceProxy.save();
    }
}

观察者模式


/**
 * 观察者模式
 */
public class Test {

    /**
     * 被观察者
     */
    static class OrderServiceImpl extends Observable {
        public void save() {
            System.out.println("保存订单");
            //标记被观察者已改动
            this.setChanged();
            //然后主动通知,这里用的是推的方式
            this.notifyObservers("订单id");
            // 也可以使用拉的方式
            // this.notifyObservers();
        }
    }

    /**
     * 观察者,保存订单后发送邮件
     */
    static class AfterSaveObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            //采用推的方式,获得推送对象
            System.out.println(arg);
            //拉的方式需要主动去获取
            //...
        }
    }

    public static void main(String[] args) {
        AfterSaveObserver observer = new AfterSaveObserver();
        OrderServiceImpl orderService = new OrderServiceImpl();
        orderService.addObserver(observer);
        orderService.save();
    }
}

第二种实现方式

/**
 * 使用PropertyChangeSupport实现观察者模式
 */
public class Test {

    static class User {

        private String name;
        private PropertyChangeSupport listeners = new PropertyChangeSupport(this);

        public User() {
            this.name = "my name";
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            String oldValue = this.name;
            this.name = name;
            //发布监听事件  
            firePropertyChange("name", oldValue, name);
        }

        public void addPropertyChangeListener(PropertyChangeListener listener) {
            listeners.addPropertyChangeListener(listener);
        }

        public void removePropertyChangeListener(PropertyChangeListener listener) {
            listeners.removePropertyChangeListener(listener);
        }

        protected void firePropertyChange(String prop, Object oldValue, Object newValue) {
            listeners.firePropertyChange(prop, oldValue, newValue);
        }
    }


    public static void main(String[] args) {
        User user = new User();
        user.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                System.out.println("OldValue:" + evt.getOldValue());
                System.out.println("NewValue:" + evt.getNewValue());
                System.out.println("tPropertyName:" + evt.getPropertyName());
            }
        });
        user.setName("new Name");
    }
}

策略模式

/**
 * 策略模式
 */
public class Test {

    /**
     * 发送红包
     */
    interface SendRedEp {
        void send();
    }

    /**
     * 策略1
     */
    static class Lv1 implements SendRedEp {
        @Override
        public void send() {
            System.out.println("发送5元红包");
        }
    }

    /**
     * 策略2
     */
    static class Lv2 implements SendRedEp {
        @Override
        public void send() {
            System.out.println("发送10元红包");
        }
    }

    /**
     * 给用户发红包
     */
    static class UserServiceImpl {
        public void send(SendRedEp sendRedEp) {
            sendRedEp.send();
        }
    }

    public static void main(String[] args) {
        UserServiceImpl service = new UserServiceImpl();
        
        //若用户是LV1则发红56元红包
        SendRedEp lv1 = new Lv1();
        service.send(lv1);
        
        // 日常使用中,利用Hashmap存储策略以等级为key,策略类为value 代替if else更实用
        // 或利用spring ioc容器获取策略
    }


}

责任链模式

在职责链模式中,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发出请求就可以了。 而每个职责对象也不用管请求者或者是其他的职责对象,只负责处理自己的部分,其他的就交给其他的职责对象去处理。 也就是说,请求者和接收者是完全解耦的。


/**
 * 责任链
 */
public class Test {

    static abstract class Handler {
        /**
         * 下一个链
         */
        protected Handler nextHandler;

        public void setNextHandler(Handler handler) {
            this.nextHandler = handler;
        }

        abstract void handle(Object order);
    }


    static class EmailHandler extends Handler {
        @Override
        void handle(Object order) {
            if (1 == 1) {
                //根据业务判断该订单是否发送邮件
                System.out.println("发送邮件");
            }
            //处理下一个链
            if (this.nextHandler != null) {
                this.nextHandler.handle(order);
            }
        }
    }

    static class SmsHandler extends Handler {
        @Override
        void handle(Object order) {
            if (1 == 2) {
                //根据业务判断该订单是否发送短信
                System.out.println("需发送短信");
            }else {
                System.out.println("无需发送短信");
            }
            //处理下一个链
            if (this.nextHandler != null) {
                this.nextHandler.handle(order);
            }
        }
    }

    public static void main(String[] args) {
        EmailHandler emailHandler = new EmailHandler();
        SmsHandler smsHandler = new SmsHandler();
        //组成链
        emailHandler.setNextHandler(smsHandler);

        //从第一个链开始执行
        emailHandler.handle("模拟对象对象");
    }
}