什么是一些常见的,现实世界的例子使用Builder模式的?它给你带来了什么?为什么不使用工厂模式?
假设我有两个C++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
Run Code Online (Sandbox Code Playgroud)
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
Run Code Online (Sandbox Code Playgroud)
人们可能期望将n其设置为2.
事实证明,n设置为1.为什么?
我了解到,当您在Java中修改变量时,它不会更改它所基于的变量
int a = new Integer(5);
int b = a;
b = b + b;
System.out.println(a); // 5 as expected
System.out.println(b); // 10 as expected
Run Code Online (Sandbox Code Playgroud)
我假设对象有类似的东西.考虑这个课程.
public class SomeObject {
public String text;
public SomeObject(String text) {
this.setText(text);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Run Code Online (Sandbox Code Playgroud)
在我尝试这段代码后,我感到困惑.
SomeObject s1 = new SomeObject("first");
SomeObject s2 = s1;
s2.setText("second");
System.out.println(s1.getText()); // second as UNexpected
System.out.println(s2.getText()); // second as expected
Run Code Online (Sandbox Code Playgroud)
请向我解释为什么更改任何对象会影响另一个对象.我知道变量文本的值存储在两个对象的内存中的相同位置.
为什么变量的值是独立的但与对象相关?
另外,如果简单的赋值不能完成工作,如何复制SomeObject?
我有一个抽象类和派生类.看看提供的代码: -
public abstract class Parent{
public Parent(){
init();
}
public abstract void init();
}
public class Child extends Parent{
private String mTitle = null;
public Child(){
super();
System.out.println(mTitle.toString());
}
public void init(){
mTitle = "It' a test";
}
}
Run Code Online (Sandbox Code Playgroud)
当我执行上面的代码时,它将在打印mTitle的值时抛出NullPointerException.如果检查父构造函数中的代码,我调用了抽象方法,它将调用派生类的init方法,在抽象方法中,我将mTitle值的值初始化为="它是一个测试";
在调用父构造函数派生类之后必须调用System.out.println.
如果它以这种方式进行,那么为什么它会抛出NullPointerException.
但是,如果我只是离开mTitle的赋值它不会抛出异常,如: -
private String mTitle;
Run Code Online (Sandbox Code Playgroud)
如果在调用类的构造时发生变量的初始化,并且我们知道默认情况下全局对象已初始化为null.但在这种情况下,它不会抛出异常.
假设我有一个Java类
abstract class Base {
abstract void init();
...
}
Run Code Online (Sandbox Code Playgroud)
而且我知道每个派生类都必须init()在它构造之后调用.当然,我可以简单地在派生类的构造函数中调用它:
class Derived1 extends Base {
Derived1() {
...
init();
}
}
class Derived2 extends Base {
Derived2() {
...
init();
}
}
Run Code Online (Sandbox Code Playgroud)
但这会破坏"不要重复自己"的原则而且会很糟糕(而且会有很多子类Base).当然,init()调用不能进入Base()构造函数,因为它会被执行得太早.
任何想法如何绕过这个问题?我也很高兴看到Scala解决方案.
更新:这是工厂方法方法的通用版本:
interface Maker<T extends Base> {
T make();
}
class Base {
...
static <T extends Base> T makeAndInit(Maker<T> maker) {
T result = maker.make();
result.init();
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
更新2:这个问题基本上是"你如何使用模板方法为构造函数"?答案似乎是,"你可以,但这是一个坏主意".所以我可以做一个模板工厂(模板方法+抽象工厂).
我经常在代码中看到这个,但是当我说到它时,我不知道这种'模式'的名称
我有一个带有2个参数的方法,它调用一个有3个参数的重载方法,并故意将第3个参数设置为空字符串.
public void DoWork(string name, string phoneNumber)
{
DoWork(name, phoneNumber, string.Empty)
}
private void DoWork(string name, string phoneNumber, string emailAddress)
{
//do the work
}
Run Code Online (Sandbox Code Playgroud)
我这样做的原因是不重复代码,并允许现有的调用者仍然调用只有2个参数的方法.
这是一种模式,它有一个名字吗?
我尝试从父类的构造函数中调用重写方法,并注意到跨语言的不同行为.
C++- 回声A.foo()
class A{
public:
A(){foo();}
virtual void foo(){cout<<"A.foo()";}
};
class B : public A{
public:
B(){}
void foo(){cout<<"B.foo()";}
};
int main(){
B *b = new B();
}
Run Code Online (Sandbox Code Playgroud)
Java- 回声B.foo()
class A{
public A(){foo();}
public void foo(){System.out.println("A.foo()");}
}
class B extends A{
public void foo(){System.out.println("B.foo()");}
}
class Demo{
public static void main(String args[]){
B b = new B();
}
}
Run Code Online (Sandbox Code Playgroud)
C#- 回声B.foo()
class A{
public A(){foo();}
public virtual void foo(){Console.WriteLine("A.foo()");}
}
class B …Run Code Online (Sandbox Code Playgroud) 如果我有一个带有重载构造函数的客户类(默认值和带有params的客户类),在Overloaded构造函数中设置类成员的正确方法是什么?使用"this"引用还是使用setter方法?
只是不确定适当的方法是什么.
public class Customer {
private String firstName;
private String lastName;
private int age;
public Customer() {}
//This Way
public Customer(String firstName, String lastName, int age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// Or this way?
public Customer(String firstName, String lastName, int age)
{
setFirstName(firstName);
setLastName(lastName);
setAge(age);
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @param firstName the firstName to set
*/
public void setFirstName(String firstName) …Run Code Online (Sandbox Code Playgroud) 假设我有一个实现Runnable接口的抽象Base类.
public abstract class Base implements Runnable {
protected int param;
public Base(final int param) {
System.out.println("Base constructor");
this.param = param;
// I'm using this param here
new Thread(this).start();
System.out.println("Derivative thread created with param " + param);
}
@Override
abstract public void run();
}
Run Code Online (Sandbox Code Playgroud)
这是一些衍生类.
public class Derivative extends Base {
public Derivative(final int param) {
super(param);
}
@Override
public void run() {
System.out.println("Derivative is running with param " + param);
}
public static void main(String[] args) {
Derivative thread …Run Code Online (Sandbox Code Playgroud) java ×9
abstract ×2
c# ×2
c++ ×2
constructor ×2
inheritance ×2
builder ×1
exception ×1
methods ×1
object ×1
oop ×1
overloading ×1
overriding ×1
pointers ×1
polymorphism ×1
reference ×1
scala ×1
terminology ×1
variables ×1
virtual ×1