下面的代码完成了我想要的工作。 Main方法中的代码外观和行为完全符合要求。但是,如果Userer,Home和DropdownMenu2类只能由HeaderNavigationMenu使用,则可以防止其他开发人员尝试在HeaderNavigationMenu类之外使用它们,这将是更好的选择。此外,大多数文章都不愿公开所有内容。
问题: 在此情况下使用的设计模式是否合适?在这种情况下是否有更好,更可接受的使用方式?
编辑:进行此设计的原因。
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenu();
Home = new Home();
DropdownMenu2 = new DropdownMenu2();
}
public UsersMenu UsersMenu { get; set; }
public Home Home { get; set; }
public DropdownMenu2 DropdownMenu2 { get; set; }
}
public class UsersMenu
{
...
}
public class Home
{
...
}
public class DropdownMenu2
{
public void SelectOption3()
{
...
}
...
}
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
Home home = new Home();
}
答案 0 :(得分:3)
限制对类构造函数的访问。如果将它们声明为“内部”,则这些类只能由您的代码创建。
答案 1 :(得分:2)
如果您希望防止UsersMenu
外部的DropdownMenu2
,Home
和HeaderNavigationMenu
实例化,但仍与{{1}然后有一个巧妙的技巧可以实现此行为。您可以将公共嵌套类与私有构造函数一起使用,这些私有构造函数会静态初始化其自己的工厂方法。基本模板是:
HeaderNavigationMenu
在您的示例中实现了以下概念:
public class Outer{
private static Func<Inner> _innerFactory;
public Inner ExposedInner {get; private set;}
public Outer(){
// Force the static initializer to run.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);
// Call the newly created factory method instead of a regular constructor.
ExposedInner = _innerFactory();
}
public class Inner {
static Inner(){
// Initialize Outer's static factory method.
_innerFactory = () => new Inner();
}
// Inner cannot be instantiated (without reflection) because its constructor is private.
private Inner(){}
// This method is now exposed for anyone to use.
public void DoStuff(){ Console.WriteLine("Did stuff"); }
}
}
有了这个,您仍然可以使用内部类的所有公共属性,但是没有人可以从class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// This line will no longer work because the constructors
// for the inner classes are private.
HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();
Console.ReadKey();
}
}
public class HeaderNavigationMenu
{
//Private factory methods that are statically initialized
private static Func<UsersMenuImpl> _createUsers;
private static Func<DropdownMenu2Impl> _createDropdown;
private static Func<HomeImpl> _createHome;
public HeaderNavigationMenu()
{
//Force the static constructors to run
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);
UsersMenu = _createUsers();
Home = _createHome();
DropdownMenu2 = _createDropdown();
}
public UsersMenuImpl UsersMenu { get; set; }
public HomeImpl Home { get; set; }
public DropdownMenu2Impl DropdownMenu2 { get; set; }
public class UsersMenuImpl
{
//Static constructor to make the class factory method
static UsersMenuImpl()
{
_createUsers = () => new UsersMenuImpl();
}
private UsersMenuImpl() { }
}
public class HomeImpl
{
//Static constructor to make the class factory method
static HomeImpl()
{
_createHome = () => new HomeImpl();
}
private HomeImpl() { }
}
public class DropdownMenu2Impl
{
//Static constructor to make the class factory method
static DropdownMenu2Impl()
{
_createDropdown = () => new DropdownMenu2Impl();
}
private DropdownMenu2Impl() { }
public void SelectOption3()
{
}
}
}
外部实例化内部类,只有HeaderNavigationMenu
可以访问内部类。工厂方法。
答案 2 :(得分:1)
我不太了解您的用例,也从未这样编码,但是仅公开ENCODING
所需行为的一种方法是将类内部化,并将变量设为私有,然后如下所示,仅公开HeaderNavigationMenu
方法。
如果您取消注释该行
SelectOption3()
您将收到编译器错误。
//Home home = new Home();
答案 3 :(得分:1)
您可以创建UsersMenu
,Home
和DropdownMenu2
public abstract
类。然后将private
类嵌套在HeaderNavigationMenu
内部,以扩展public abstract
版本。
public abstract class UsersMenu
{
}
public abstract class Home
{
}
public abstract class DropdownMenu2
{
public void SelectOption3()
{
// Code for SelectOption3...
}
}
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenuImpl();
Home = new HomeImpl();
DropdownMenu2 = new DropdownMenu2Impl();
}
public UsersMenu UsersMenu { get; }
public Home Home { get; }
public DropdownMenu2 DropdownMenu2 { get; }
private class UsersMenuImpl : UsersMenu
{
}
private class HomeImpl : Home
{
}
private class DropdownMenu2Impl : DropdownMenu2
{
}
}
高级开发人员可以查看和使用UsersMenu
,Home
和DropdownMenu2
abstract
类,但是不能创建它们的实例。只有HeaderNavigationMenu
可以。
当然,另一个开发人员总是可以创建从public abstract
派生的自己的类,但是您只能做很多事情。 UsersMenu
,Home
和DropdownMenu2
必须是public
,才能成为public
属性。