c# - 使用 Builder 模式和受保护的访问修饰符
问题描述
我正在读一本设计模式的书,下面是作者使用的一些代码示例。作者尝试将 html 构建器构建为:
public class HtmlElement
{
public string Name, Text;
public List<HtmlElement> Elements = new List<HtmlElement>();
public HtmlElement() { }
public HtmlElement(string name, string text)
{
Name = name;
Text = text;
}
// factory method
public static HtmlBuilder Create(string name)
{
return new HtmlBuilder(name);
}
}
//builder class
public class HtmlBuilder
{
protected readonly string rootName;
protected HtmlElement root = new HtmlElement();
public HtmlBuilder(string rootName)
{
this.rootName = rootName;
root.Name = rootName;
}
public HtmlBuilder AddChild(string childName, string childText)
{
var e = new HtmlElement(childName, childText);
root.Elements.Add(e);
return this; //fluent api
}
// to return a HtmlElement object
public static implicit operator HtmlElement(HtmlBuilder builder)
{
return builder.root;
}
public override string ToString() => root.ToString();
}
然后作者说:
“为了简单地强制用户在构造HtmlElement
对象时使用 Builder,我们将HtmlElement
类的所有构造函数隐藏为”:
public class HtmlElement
{
...
protected HtmlElement() { }
protected HtmlElement(string name, string text)
{
Name = name;
Text = text;
}
...
}
所以用户可以去喜欢
HtmlElement root = HtmlElement.Create("ul").AddChildFluent("li", "hello").AddChildFluent("li", "world");
Console.WriteLine(root);
这里是我不明白的,作者将HtmlElement
's 构造函数的访问修饰符更改为protected
,这意味着HtmlBuilder
该类无法访问受保护的构造函数,例如
protected HtmlElement root = new HtmlElement(); // not allowed
那么这是否意味着我们需要让HtmlBuilder
继承自HtmlElement
?但是它们根本不是继承上下文,那么我该如何修改呢?
解决方案
那个代码是错误的。构建器类无法访问。作者可能打算使用工厂方法。
我完全不同意作者的观点。
永远不要试图强迫用户以某种方式使用类来适应某种模式。构建器模式的重点是在构建对象时降低复杂性,而不是让它变得更难。
当构建对象链而不是像 HTML 元素这样的简单对象时,最常使用构建器模式。例如,您可以拥有一个 CarBuilder 来构建具有引擎、变速箱和所有其他获得功能性汽车所需的对象的汽车。
您可能有一个SafeCarBuilder
使用更强大的底盘但相同的引擎和一个FastCarBuilder
使用默认底盘但向引擎添加涡轮增压器的车型。
推荐阅读
- apache-kafka - 向 Sprong Cloud DataFlow UI 公开 Kafka 属性
- javascript - 如何使用crome.js 允许用户上传他们的个人资料图片?
- javascript - 转换为对象时如何键入猫鼬模型
- java - 有没有办法在java中查看堆栈内存?
- c# - 如何确保 DataGridView 列只接受整数?
- azure - 访问 Azure ARM 模板中的机密
- sql - sqlite3 行号
- r - 将表列转换为空间对象
- reactjs - 如何在 material-ui 样式/JSS 中选择 id?
- php - 导航到所有租户路由重定向回“/”,注册路由除外 - hyn/multitenant