今天我在采访中遇到了一个问题。是否可以在Singleton类上应用继承概念?我说因为构造函数是私有的,所以我们不能扩展那个Singleton类。
他问我的下一件事是在Singleton类上应用继承。因此,我将Singleton的构造函数视为受保护的思想,即child的构造函数也受到保护。但我错了,孩子的修饰符可能等于或高于此值。
所以,我请他就这种情况给出一个真实世界的例子。他无法给我一个,并说我无法提出问题,并希望我告诉他们这种情况是否可能。
我有点空白。我的问题是,
答案 0 :(得分:11)
是,这在技术上是可行的,因为singleton是一种设计模式,而不是可能具有继承限制的语言结构。我只是重新实现子类中的public [Object] getInstance()
方法(见下文)。
而且,是的,单身人士也可以从继承中受益,因为他们可能与其他单身人士分享相似但不具有识别性的行为。
public class ParentSingleton {
private static ParentSingleton instance;
protected ParentSingleton() {
}
public static synchronized ParentSingleton getInstance() {
if (instance == null) {
instance = new ParentSingleton();
}
return instance;
}
public int a() {
// (..)
}
}
public class ChildSingleton extends ParentSingleton {
private static ChildSingleton instance;
public static synchronized ParentSingleton getInstance() {
if (instance == null) {
instance = new ChildSingleton();
}
return instance;
}
}
编辑:正如Eyal在下面的评论中指出的那样,超级类中的构造函数必须受到保护(而不是私有),否则它们将不会被子类和代码甚至不会编译。
答案 1 :(得分:11)
引用bible:
[...]时使用Singleton模式 唯一的实例应该是可扩展的 通过子类化,客户端应该是 能够使用扩展实例 没有修改他们的代码。
Singleton模式有几个 好处:[...] 3.允许改进业务和代表。单身人士 class可以是子类,也可以是 易于配置应用程序 这个扩展类的一个实例。 您可以使用配置应用程序 您需要的类的实例 运行时间。
至于如何实现这一点:本书提出了几种方法,其中最复杂的是注册表,其中的实例按名称查找。
答案 2 :(得分:10)
您可以使用一堆公共属性和方法创建一个抽象基类,然后创建一些子类作为单例类。那就是“以一种有用的方式应用继承概念”。
但是你不能做的是创建一个严格实现的单例类的子类。如果将单例类构造函数声明为private
,则子类将无法编译。如果您使用其他访问权限声明它,则可以在另一个类中使用构造函数来创建多个实例...因此,它不是严格意义上的单例。如果你将单例声明为abstract
,则根本无法实例化...因此它不是单例。
答案 3 :(得分:4)
它可能真的能够共同攻击任何东西,但在这种情况下它并不是真的可行。没有真正的理由将单例模式与继承一起使用,它只是不适合它。
答案 4 :(得分:3)
私有构造函数对该单例类的其他内部类是可见的。所以是的,从技术上讲,带有私有构造函数的单例类可以通过其内部类进行扩展。但为什么你会这样做的事情超出我的范围。
答案 5 :(得分:2)
下面是GOF中关于创建具有继承的单例的单例模式的一种实现。这里应该修改父类以添加新的派生类。环境变量可用于实例化适当的派生类构造函数。
Mainfile – 1
#include <iostream>
#include <string>
#include "Singleton.h"
using namespace std;
int main(){
Singleton::instant().print();
cin.get();
}
Singleton.h
#pragma once
#include <iostream>
using std::cout;
class Singleton{
public:
static Singleton & instant();
virtual void print(){cout<<"Singleton";}
protected:
Singleton(){};
private:
static Singleton * instance_;
Singleton(const Singleton & );
void operator=(const Singleton & );
};
Singleton.cpp
#include "Singleton.h"
#include "Dotted.h"
Singleton * Singleton::instance_ = 0;
Singleton & Singleton::instant(){
if (!instance_)
{
char * style = getenv("STYLE");
if (style){
if (strcmp(style,"dotted")==0)
{
instance_ = new Dotted();
return *instance_;
} else{
instance_ = new Singleton();
return *instance_;
}
}
else{
instance_ = new Singleton();
return *instance_;
}
}
return *instance_;
}
Dotted.h
#pragma once
class Dotted;
class Dotted:public Singleton{
public:
friend class Singleton;
void print(){cout<<"Dotted";}
private:
Dotted(){};
};
答案 6 :(得分:1)
我猜这不是他不想要的,但如果你想获得技术,你也可以提到Singleton是一种模式,而不是一种实现。使用类构造函数不是获得Singleton的唯一方法,您可以让工厂强制执行该模式,在这种情况下,您可以使用与其他类完全相同的方式继承。
答案 7 :(得分:-2)
您可以将构造函数包设为私有。这样,包外的任何类都不能实例化Singleton类,但派生类可以调用上层构造函数。
但是,正如其他人所说,这实际上是不可取的。
顺便说一句愚蠢的面试问题。