[英]C# restricting use of a class
下面的代码完成了我想做的事情。 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();
}
限制对类构造函数的访问。 如果将它们声明为“内部”,则这些类只能由您的代码创建。
如果您正在寻找抵御的实例UsersMenu
, DropdownMenu2
和Home
从外部HeaderNavigationMenu
但仍然是相同的项目作为内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
外部实例化内部类,只有HeaderNavigationMenu
可以访问工厂方法。
我真的不明白你的使用情况是什么,我从来没有编码这样的,但只露出所需的行为的一种方式HeaderNavigationMenu
是使类内部和私有变量,然后仅露出SelectOption3()
方法, 如下。
如果您取消注释该行
//Home home = new Home();
您将得到一个编译器错误。
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
//Home home = new Home();
}
}
public class HeaderNavigationMenu
{
UsersMenu usersMenu;
Home home;
DropdownMenu2 dropdownMenu2;
public HeaderNavigationMenu()
{
usersMenu = new UsersMenu();
home = new Home();
dropdownMenu2 = new DropdownMenu2();
}
public void DropdownMenu2SelectOption3()
{
dropdownMenu2.SelectOption3();
}
class UsersMenu
{
}
class Home
{
}
class DropdownMenu2
{
public void SelectOption3()
{
}
}
}
您可以将UsersMenu
, Home
和DropdownMenu2
Home
public abstract
类。 然后将private
类嵌套在HeaderNavigationMenu
内部, 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
属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.