Oop 确定构造函数、初始化和重置方法任务的最佳实践是什么

Oop 确定构造函数、初始化和重置方法任务的最佳实践是什么,oop,constructor,initialization,reset,Oop,Constructor,Initialization,Reset,这是一个通用的OOP问题,尽管我是用Java设计的。我不是想解决某个特定的问题,只是想通过一些设计原则来思考。 根据我的经验,我已经养成了将对象设置分为三个阶段的习惯 我们的目标是最大限度地减少:额外的工作、混乱的代码和严重的可扩展性 施工 必须采取的最低限度的行动 创建有效对象,传递 存在性检验 仅“一次”实例化和初始化,永远不会被过度使用,在对象的生命周期内不会改变/变化的非变量对象 初始化最终成员 本质上是一个运行时存根 初始化 使对象有用 实例化和初始化可公开访问的成员 实例化和初始化作

这是一个通用的OOP问题,尽管我是用Java设计的。我不是想解决某个特定的问题,只是想通过一些设计原则来思考。
根据我的经验,我已经养成了将对象设置分为三个阶段的习惯

我们的目标是最大限度地减少:额外的工作、混乱的代码和严重的可扩展性


施工

  • 必须采取的最低限度的行动 创建有效对象,传递 存在性检验
  • 仅“一次”实例化和初始化,永远不会被过度使用,在对象的生命周期内不会改变/变化的非变量对象
  • 初始化最终成员
  • 本质上是一个运行时存根
  • 初始化

  • 使对象有用
  • 实例化和初始化可公开访问的成员
  • 实例化和初始化作为变量值的私有成员
  • 对象现在应该通过外部测试而不会产生异常(假设代码是正确的)
  • 重置

  • 不实例化任何内容
  • 将默认值指定给所有变量公共/私有成员
  • 将对象返回到精确的状态
  • 玩具示例:

    public class TestObject {
       private int priv_a;
       private final int priv_b;
       private static int priv_c;
       private static final int priv_d = 4;
    
       private Integer priv_aI;
       private final Integer priv_bI;
       private static Integer priv_cI;
       private static final Integer priv_dI = 4;  
    
       public int pub_a;
       public final int pub_b;
       public static int pub_c;
       public static final int pub_d = 4;
    
       public Integer pub_aI;
       public final Integer pub_bI;
       public static Integer pub_cI;
       public static final Integer pub_dI = 4;   
    
       TestObject(){
            priv_b = 2;
            priv_bI = new Integer(2);
            pub_b = 2;
            pub_bI = new Integer(2);
       }
    
       public void init() {
           priv_a = 1;
           priv_c = 3;
           priv_aI = new Integer(1);
           priv_cI = new Integer(3);
    
           pub_a = 1;
           pub_c = 3;
           pub_aI = new Integer(1);
           pub_cI = new Integer(3);
       }
    
       public void reset() {
           priv_a = 1;
           priv_c = 3;
           priv_aI = 1;
           priv_cI = 3;
    
           pub_a = 1;
           pub_c = 3;
           pub_aI = 1;
           pub_cI = 3;
       }  
    }
    

    不能说我曾经使用过这种模式,但我使用过类似的方法来减少代码重复。例如,当您有一个对象,该对象可以通过构造函数创建,也可以通过工厂方法从另一个对象(如DTO)创建。在这种情况下,我通常会有一个内部初始值设定项来填充双方都使用的对象的属性。不能说我曾经使用过“重置”方法,如果它所做的只是复制创建新对象的过程,我也看不到真正需要这种方法


    最近,我只使用默认构造函数和属性设置器来初始化对象。新的C++语法允许使用“构造函数”格式来轻松地使用这一点,这使得我们很容易使用支持参数化的构造函数消失。

    < P>我来自C++背景,其中规则与java有点不同,但我认为这两个阶段的初始化原则适用于一般情况。 施工

  • 在施工时可以做的一切都应该在施工时完成
  • 尽量减少在调用
    init()
    之前尝试使用对象可能导致的“不良”程度
  • 所有成员变量都需要一个值,即使它通常是无效的sentry值(例如,将指针设置为null)。我认为Java默认情况下会将所有变量初始化为零,所以如果这是一个有效的数字,您需要选择其他变量
  • 初始化

  • 初始化那些依赖于其他对象存在的成员变量。基本上,做你在施工时不能做的事情
  • 确保您的对象现在处于完整的、随时可用的状态。如果不存在,请考虑抛出异常。
  • 重置

  • 当您想要调用这样一个函数时,请仔细考虑系统将处于什么状态。从头开始创建一个新对象可能更好,即使这个操作看起来很昂贵。分析您的代码以确定这是否是一个问题
  • 假设您获得了第1项,请考虑编写一种方法来处理两个代码:<代码> ReSET()/<代码>和构造函数需要做的事情。这简化了维护并避免了代码重复
  • 将对象返回到
    init()
    之后的状态

  • 我将以一种不需要“init”方法的方式设计我的类。我认为一个类的所有方法,尤其是公共方法,都应该保证对象在成功完成后始终处于“有效”状态,并且不需要调用其他方法


    构造函数也是如此。创建对象时,应该将其视为已初始化并准备好使用(这就是构造函数的作用,实现这一点有很多技巧)。否则,您可以安全使用它的唯一方法是检查对象是否已在每个其他公共方法的开头初始化

    是否有原因
    init()
    reset()
    需要不同?在这个简单的例子中,很难理解为什么“不实例化任何东西”规则很重要

    除此之外,我认为对象一经构建就应该很有用。如果有原因——一些循环依赖或继承问题——在构造之后必须“初始化”对象,我会将构造函数和初始化隐藏在静态工厂方法后面。(并且可能会将初始化代码移动到单独的configurator对象,以便更好地测量。)


    否则,调用方总是同时调用构造函数和
    init()
    ,这是一种非标准模式。我们有一些旧的,非常有用的代码,在这里可以做到这一点;这是一个抽象的对话框类,每次有人扩展它时,他们都会忘记调用
    constructUI()
    ,然后他们会浪费15分钟去想为什么他们的新对话框是空的。

    很有趣。如果您有一个需要执行IO操作的对象,我特别发现这种构造非常有用。我不希望任何东西直接或间接地在其构造函数中执行IO操作。它使对象成为一场噩梦。

    我对重置的理解是,它是一种将对象恢复到原始状态的方法,该状态与数据、信息排列、更接近状态机的东西有关,而不是运行程序的“状态”。是的,但是,为什么要维护另一个方法,该方法与创建新对象的操作相同呢。如果对象是一个单例对象,或者创建起来很昂贵,但是重置起来很便宜,但是有一个常规的