• pyhhou
    2019-03-11
    仅仅在这个代码基础上改的话:
    public HelloWords getInstance(String language) {
          if (language.equals(ENGLISH.language)) {
                return ENGLISH;
          }
          
          if (language.equals(MANDARIN.language)) {
               return MANDARIN;
          }
          
          throw IllegalArgumentException("This language doesn't exist");
    }

    用 private 来定义构造方法是为了防止类的使用者通过 new 的方式来产生新的对象,在这样的方式下,类的使用者只能通过类中的 static 对象中的 getInstance 方法来获取已经存在的对象,从而减轻了内存管理的负担

    不用 private 来定义变量是因为类的使用者通过 getInstance 方法只能获取类的实例,也就是对象,但是对于对象里面的内容(language、greeting)还需进一步的获取; 用 final 去定义这些变量是为了防止类的使用者更改 static 对象中的内容,因为更改后会导致内容发生全局性的改变,从而和对象本身不匹配

    但是个人认为这样的设计并没有很好的体现我们之前讲的 “简单直观” 的理念,首先这里存在着很深的嵌套,就是:类 -> static 对象 -> getInstance 方法 -> static 对象 -> 变量,这么分析看来设计并不直观,对于我来说,刚开始理解还比较的困难,所以可以考虑前面的将这里的 getInstance 方法改为 static 的方法,另外就是可以设一个 getGreeting 的方法去取得 instance 中的内容,用户通过函数 API 的方式获取内部信息而不是直接获取,在这种情况下我们可以将变量设为 private,这样比较好的隐藏内部实现,当然我们也可以使用之前提到的 enum 去实现:
    static enum Hellowords {
         ENGLISH ("English", "Hello"),
         MANDARIN ("Ni Hao");
        
         final String language;
         final String greeting;

         private HelloWords(String language, String greeting) {
               this.language = language;
               this.greeting = greeting;
         }
    }
    展开

    作者回复: 你的留言里,有大量的深入思考,要点赞!

    
     6
  • 轻歌赋
    2019-02-25
    因为这是final修饰的变量,又是string,属性不可改变
    可以考虑改成enum,或者是单例模式
    单例模式推荐内部静态类持有的方式,相对更简单
    如果使用容器化管理,例如spring,可以考虑注册成两个bean,通过规范约束不得创建,但是编程层面的约束力相对薄弱

    作者回复: 嗯,可以考虑使用内部静态类持有的方式。

    
     3
  • 君不得闲
    2019-02-25
    public static HelloWords getInstance(String language){
            if ("English".equals(language)) {
                return ENGLISH;
            }

            if ("Mandarin".equals(language)) {
                return MANDARIN;
            }

            throw new IllegalStateException("This language is not supported");
        }

    构造方法没有实例化是为了避免使用者调用生成多实例,违背设计减少实例数量的初衷。
    至于变量为什么不使用private关键字百思不得其解。因为如果没有修饰符修饰就代表只要是相同包内都可以对该类生成的实例的变量进行直接修改,但是final关键字又对这种修改做了限制,说明这两个是不可修改的常量,因为没有static修饰,说明这个常量是实例私有的,个人想法是已经用final了就没有必要用private修饰的多此一举了,就像接口的方法不用特意声明public abstract一样。
    展开

    作者回复: 异常类型使用IllegalArgumentException或者一个检查型异常,会好一点点。

    
     2
  • Geek_28d7fe
    2019-05-21
    单例模式破坏类的封装,现在很多开源代码尽量避免使用单例,是不是能不用单例就不用单例

    作者回复: 很多场景下,单例模式是优先选择。 比如enum就是单例模式的典范。所以,要看具体的场景,具体的状况。

    
     1
  • 天佑
    2019-03-11
    在编写代码时,如果能够引用,就坚决不要拷贝,老师您好,这样子做不会出现安全问题么,那入参防御性复制的使用场景是什么,有点糊涂了,期待老师答疑。

    作者回复: 有安全问题,就不算可以引用了。什么时候防御性复制,什么时候不用复制,我们在第三部分还会说这个问题。

    
     1
  • 往事随风,顺其自然
    2019-02-25
    构造器使用私有的,不允许实例化多个类,减少实例数量,变量没有私有化是因为string 不可变的类。
    
     1
  • sovran
    2019-12-08
    还有一种方法,复用同一块内存,减少不必要的内存申请释放。 程序开始就申请一块全局的内存,在软件运行的不同的阶段存储不一样的变量。 比如C语言的union结构。
    
    
  • 李米
    2019-12-07
    最好的优化就是不用,不用线程同步,不使用内存。老师的风格让我想起来奇葩说里的李诞:名画的最好归宿就是烧了。~老师技术不但实力强,还是个逗逼
    
    
  • Sisyphus235
    2019-05-23
    内存管理这里说的大多是 Java 的语境,能够给一些通用的经验,如何在其他语言和框架下处理,而不是使用特定的包或者语言工具?

    作者回复: 这些原则同样适用于其他语言。你可以试试把它们运用到C++/C/GoLang等其他语言.

    
    
  • 天佑
    2019-04-14
    “在编写代码时,如果能够引用,就坚决不要拷贝”
    这里不适用公共接口设计场景吧,考虑可变量的危害。

    作者回复: 是的。这里我加了个限定词“如果能够引用”,读到后面的文章,就知道这个限定词的作用了。外部接口,可变量要遵循审慎的原则,尽量拷贝或者规范明确标明不拷贝;内部实现的代码,如果清楚可变量的传递和变化不会捣乱,使用引用就行。

    
    
  • 徐题
    2019-03-06
    final修饰的类,它的成员变量也是final的吗?

    作者回复: 不是,除非成员变量使用了final修饰符。修饰符修饰什么,就对什么起作用,不要扩大范围。

    
    
  • 草原上的奔跑
    2019-03-02
    单例模式用枚举来实现比较好,不用考虑多线程同步问题,JVM会处理好。关于类的成员变量没有限定修饰符,那就是包共享的,用final修饰,则初始化后不可更改,String又是一个immutable的类,则成员变量可以当成常量在包中共享,且无并发问题。
    
    
我们在线,来聊聊吧