• Java面向对象七大原则以及设计模式单例模式和工厂模式简单工厂模式


    面向对象的七大原则(OOP)

    1,开闭原则:

    对扩展开发,对修改关闭

    2.里氏替换原则:

    继承必须确保超类所拥有的子类的性质在子类中仍然成立

    3.依赖倒置原则:

    面向接口编程,不要面向实现编程,降低程序之间的耦合性

    4.单一职责原则:

    控制类的粒度大小,将对象解耦,提高其内聚性

    5.接口隔离原则:

    要为各个类创建他们专用的接口

    6.迪米特法则:

    只于你的直接朋友交谈,不跟陌生人交谈

    7.合成复用法则:

    尽量先使用组合或者聚合等关联来实现,其次才考虑使用集成关系来实现

    单例模式

    饿汉模式

    public class Hunger{
        private Hunger(){}
        private final static Hunger HUNGER_SINGLTON = new Hunger();
        public static Hunger getInstrente(){
            return HUNGER_SINGLTON;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    懒汉模式

    第一种,不考虑安全的问题

    public class LayzeMan{
        private static LayzMan LAYZE_MAN;
        private LayzeMan(){
            System.out.println(Thread.currentThread().getName()+"ok");
        }
        public static LayzeMan getInstrence(){
            if(LAYZE_MAN == null){
                LATZE_MAN = new LayzeMan();
            }
            return LAYZE_MAN;
        }
    }
    /**
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    该单例模式在使用普通创建对象时,可以实现对象的单例

    还存在两个问题

    1. 使用多线程可以破坏该单例模式
    2. 使用反射可以破坏该单例模式

    解决多线程破坏单例模式的方法

    public class Layze{
        private volatile static Layze lay;
        private Layze(){
            
        }
        /**
        三重检测锁   DCL模式
        **/
        public static Layze getInstance(){
            if(lay == null){
                synchorized(Layze.class){
                    if(lzy == null){
                         lay = new Layze();   
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    此时使用多线程破坏单例模式的问题已经可以解决

    解决反射破坏单例模式的问题

    public calss LayzeMan{
        private static volatile LayzeMan layze;
        private LayzeMan(){
            synchorized(LayzeMan.class){
                if(layze !=null){
                    throw new RuntimeException("不要试图使用反射去破坏我的单例模式");
                }
            }
        }
        public static LayzeMan getInstrence(){
            if(layze == null){
                synchorized(LayzeMan.class){
                    if(layze == null){
                        layze = new LayzeMan();
                    }
                }
            }
            return layze;
        }
    }
    class test{
        public static void main(String[] args){
            LayzeMan layzeMan = LayzeMan.getInstrence();
            Constructor<LazyPJie> declaredConstructor = LazyPJie.class.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            LazyPJie lazyPJie1 = declaredConstructor.newInstance();
            System.out.println(lazyPJie);
            System.out.println(lazyPJie1);
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    此时会报错

    Exception in thread "main" java.lang.reflect.InvocationTargetException
    	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    	at com.itcast.designMode.single.Test01.main(LazyPJie.java:41)
    Caused by: java.lang.RuntimeException: 不要试图使用反射破坏单例模式
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    此时还会有一个问题:就是在类中判断对象是否为空时,判断了有没有第一个对象用普通方式去创建对象的时候,这个时候使用反射的时候就会报出异常,但是,此时如果两个对象都使用反射去创建就会出问题,单例模式就会又被破坏

    代码如下
     public static void main(String[] args) throws Exception {
         /* LazyPJie lazyPJie = LazyPJie.getInstance();*/
          Constructor<LazyPJie> declaredConstructor = LazyPJie.class.getDeclaredConstructor(null);
          declaredConstructor.setAccessible(true);
          LazyPJie lazyPJie1 = declaredConstructor.newInstance();
          LazyPJie lazyPJie = declaredConstructor.newInstance();
          System.out.println(lazyPJie);
          System.out.println(lazyPJie1);
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    解决完全使用反射破坏单例模式

    public calss LayzeMan{
        private static volatile LayzeMan layze;
        private static boolean flag = flase;
        private LayzeMan(){
            synchorized(LayzeMan.class){
               if(!flag){
                   flag = ture;
               }else{
                    throw new RuntimeException("不要试图使用反射去破坏我的单例模式");
               }
            }
        }
        public static LayzeMan getInstrence(){
            if(layze == null){
                synchorized(LayzeMan.class){
                    if(layze == null){
                        layze = new LayzeMan();
                    }
                }
            }
            return layze;
        }
    }
    class test{
        public static void main(String[] args) throws Exception {
         /* LazyPJie lazyPJie = LazyPJie.getInstance();*/
          Constructor<LazyPJie> declaredConstructor = LazyPJie.class.getDeclaredConstructor(null);
          declaredConstructor.setAccessible(true);
          LazyPJie lazyPJie1 = declaredConstructor.newInstance();
          LazyPJie lazyPJie = declaredConstructor.newInstance();
          System.out.println(lazyPJie);
          System.out.println(lazyPJie1);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    枚举(天然的单例模式)

    package com.itcast.designMode.single;
    
    /**
     * author:hlc
     * date:2023/9/18
     */
    public enum EnumClass {
       ENUM_CLASS;
       public EnumClass getEnumClass(){
          return ENUM_CLASS;
       }
    }
    class Test03{
       public static void main(String[] args) {
          EnumClass enumClass = EnumClass.ENUM_CLASS;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    静态内部类

    package com.itcast.designMode.single;
    
    /**
     * author:hlc
     * date:2023/9/18
     */
    public class Holder {
       /**
        * 静态内部类实现单例模式
        */
       private Holder(){}
       public static Holder getInstance(){
          return InnerClass.HOLDER;
       }
       public static class InnerClass{
          private static final Holder HOLDER = new Holder();
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    工厂模式

    1. 实现了创建者和调用者的分离
    2. 满足原则
      1. 开闭原则
      2. 依赖倒转原则
      3. 迪米特法则

    实例化对象不使用new,而是使用方法

    简单工厂模式

    package com.itcast.designMode.factory;
    
    public interface Car {
       void name();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package com.itcast.designMode.factory;
    
    /**
     * author:hlc
     * date:2023/9/18
     */
    public class Tesila implements Car{
       @Override
       public void name() {
          System.out.println("特斯拉");
       }
    }
    
    
    
    package com.itcast.designMode.factory;
    
    /**
     * author:hlc
     * date:2023/9/18
     */
    public class WuLing implements Car{
       @Override
       public void name() {
          System.out.println("五菱");
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    package com.itcast.designMode.factory;
    
    /**
     * author:hlc
     * date:2023/9/18
     */
    public class CarFactory {
       public static Car getCar(String name){
          if (name.equals("五菱")){
             return new WuLing();
          }else if (name.equals("特斯拉")){
             return new Tesila();
          }else {
             return null;
          }
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
     public static void main(String[] args) {
          Car car = CarFactory.getCar("五菱");
          Car car1 = CarFactory.getCar("特斯拉");
          car1.name();
          car.name();
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    IOC和DI入门案例
    群公告详情
    Mybatis-注解开发
    【机器学习项目实战10例】(二):利用LightGBM实现天气变化的时间序列预测
    数组方法深入探究(1)--at&copyWithin
    Ubuntu 20.04上docker安装RabbitMQ并确保可以访问RabbitMQ的管理界面
    Web前端:全栈、MEAN、MERN,应该选择那个开发栈?
    由于找不到vcruntime140_1.dll,无法继续执行代码重新安装程序可能会解决此问题
    Python爬虫与数据可视化源码免费领取
    MySql——性能分析
  • 原文地址:https://blog.csdn.net/qq_56403451/article/details/133000541