Singletonパターン
インスタンスが1つしか存在しないことを保証する
あるクラスのインスタンスが一つしかないことを保証したい場合があります。注意深く設計すれば、唯一のインスタンスを使いまわすことは可能でしょうが、このインスタンスが唯一であることを保障するものとはなりません。このような場合に、威力を発揮するのが Singleton パターンです。
先に、「インスタンスが一つしかないことを保証」と言いましたが、実はインスタンスが一つしか生成できないわけではありません。任意の数のインスタンスに制限できます。
Singleton パターンの適用方法として以下の2つが考えられます。
1. インスタンスの生成を制限する

例えば、データベースへのコネクションの数を制限したい場合、データベースアクセスインスタンスの生成数を制限する必要があります。また、シーケンス番号などを生成するような場合、複数のインスタンスが生成されてしまっては、その整合性に苦労することになります。
2. 無駄なインスタンスの生成を抑制する
例えば、ファイルへのアクセス処理です。ファイルへのアクセス処理は非常に負荷がかかり、処理速度に影響を及ぼします。ファイルの内容の更新頻度が高い場合はともかく、更新は行われないが、参照は頻繁に行われるようなファイルを毎回読み込むのは、効率が良いとは言えません。そんなときは、読み込んだファイルの内容を保持するキャッシュ機構を設けることで、問題を改善できます。
このキャッシュ機構はシステム内で1つあれば十分ですので、キャッシュ機構を Singleton 化します。Singleton 化することにより、ファイルアクセスのたびに実際にファイルを読み込むのではなく、システム内で共通のキャッシュを参照させることができます。
Singleton パターンの特徴は、Singleton クラスのインスタンス生成を、Singleton クラス自身が提供するオブジェクト生成用メソッドで行うことです。
まず、Singleton にしたいクラスをstaticなクラスフィールドとして用意します。これによって生成されたインスタンスはグローバル領域で管理され、どこからでも参照できます。
次に、コンストラクタを privateに指定して、Singleton クラス以外からコンストラクタの呼出し(newが使えなくなる)ができないようにします。そして、(外部よりnewが使えないため)インスタンスを取得するメソッドを用意してあげる必要があります。このメソッドは、どこからでも参照できるように、public でなおかつ static として宣言しておきます。
例題
1からのシリアルナンバーを生成するクラス SerialNumber を作りなさい。
0:1
1:2
2:3
3:4
4:5
5:6
End.
Start.
0:7
1:8
2:9
3:10
End.
|
Singletonパターンを使用しない例 SerialNumber.java public class SerialNumber {
private static int sn = 1;
public synchronized int getNextSerialNumber() {
return sn++;
}
}
Main.java public class Main {
public static void main(String[] args) {
exec(new SerialNumber(), 6);
exec(new SerialNumber(), 4);
}
private static void exec(SerialNumber sn, int n) {
System.out.println("Start.");
for (int i = 0; i < n; i++) {
System.out.println(i + ":" + sn.getNextSerialNumber());
}
System.out.println("End.");
}
}
|
Singletonパターンを使用した例 SerialNumber.java public class SerialNumber {
private int sn = 1;
private static SerialNumber singleton = new SerialNumber();
private SerialNumber() {}
public static SerialNumber getInstance() {
return singleton;
}
public synchronized int getNextSerialNumber() {
return sn++;
}
}
Main.java public class Main {
public static void main(String[] args) {
exec(SerialNumber.getInstance(), 6);
exec(SerialNumber.getInstance(), 4);
}
private static void exec(SerialNumber sn, int n) {
System.out.println("Start.");
for (int i = 0; i < n; i++) {
System.out.println(i + ":" + sn.getNextSerialNumber());
}
System.out.println("End.");
}
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 synchronized に注意してください。これは、宣言されたメソッドが同時に複数のインスタンスから呼ばれないようにするためのものです。これによって、シリアルナンバーを参照して1加算する前に、別のインスタンスから呼ばれて、同じ数値を参照してしまうというトラブルを避けています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 serialNumber.h class SerialNumber
{
private:
static int sn;
public:
SerialNumber(void);
virtual ~SerialNumber(void);
int getNextSerialNumber(void);
}; serialNumber.cpp #include "serialNumber.h"
int SerialNumber::sn = 1;
SerialNumber::SerialNumber(void) {}
SerialNumber::~SerialNumber(void) {}
int SerialNumber::getNextSerialNumber(void) {
return sn++;
}
Main.java #include <iostream>
using namespace std;
#include "serialnumber.h"
void exec(SerialNumber*, int);
int main() {
SerialNumber* sn1 = new SerialNumber();
exec(sn1, 6);
delete sn1;
SerialNumber* sn2 = new SerialNumber();
exec(sn2, 4);
delete sn2;
return 0;
}
void exec(SerialNumber* sn, int n) {
cout << "Start." << endl;
for (int i = 0; i < n; i++) {
cout << i << ":" << sn->getNextSerialNumber() << endl;
}
cout << "End." << endl;
}
|
Singletonパターンを使用した例 serialNumber.h class SerialNumber
{
private:
int sn;
static SerialNumber* singleton;
SerialNumber(void);
virtual ~SerialNumber(void);
public:
static SerialNumber* getInstance(void);
int getNextSerialNumber(void);
}; serialNumber.cpp #include "serialNumber.h"
SerialNumber* SerialNumber::singleton = new SerialNumber();
SerialNumber::SerialNumber(void) : sn(1) {}
SerialNumber::~SerialNumber(void) {}
serialNumber* SerialNumber::getInstance(void) {
return singleton;
}
int SerialNumber::getNextSerialNumber(void) {
return sn++;
}
main.cpp #include <iostream>
using namespace std;
#include "serialNumber.h"
void exec(SerialNumber*, int);
int main() {
exec(SerialNumber::getInstance(), 6);
exec(SerialNumber::getInstance(), 4);
return 0;
}
void exec(SerialNumber* sn, int n) {
cout << "Start." << endl;
for (int i = 0; i < n; i++) {
cout << i << ":" << sn->getNextSerialNumber() << endl;
}
cout << "End." << endl;
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
実は、C++では、Singletonパターンにはいくつかの問題があります。
- コピーコンストラクタ、コピー代入演算子によってインスタンスの唯一性の保証が崩れる
- インスタンスをdeleteされてしまうと、削除されたインスタンスを参照することになる
- マルチスレッドに対する安全性がない(snをインクリメントする前に他のスレッドが参照する)
- いつ誰が、newしたSingletonをdeleteするのか(最後までdeleteされない)
|
Singletonパターンを使用しない例 SerialNumber.cs class SerialNumber
{
private static int sn = 1;
public int GetNextSerialNumber()
{
return sn++;
}
} Program.cs class Program
{
static void Main(string[] args)
{
Exec(new SerialNumber(), 6);
Exec(new SerialNumber(), 4);
}
static void Exec(SerialNumber sn, int n)
{
Console.WriteLine("Start.");
for (int i = 0; i < n; i++)
{
Console.WriteLine(i + "." + sn.GetNextSerialNumber());
}
Console.WriteLine("End.");
}
}
|
Singletonパターンを使用した例 SerialNumber.cs class SerialNumber
{
private int sn = 1;
private static SerialNumber singleton = new SerialNumber();
private SerialNumber() {}
public static SerialNumber GetInstance()
{
return singleton;
}
public int GetNextSerialNumber()
{
return sn++;
}
} Program.cs class Program
{
static void Main(string[] args)
{
Exec(SerialNumber.GetInstance(), 6);
Exec(SerialNumber.GetInstance(), 4);
}
static void Exec(SerialNumber sn, int n)
{
Console.WriteLine("Start.");
for (int i = 0; i < n; i++)
{
Console.WriteLine(i + "." + sn.GetNextSerialNumber());
}
Console.WriteLine("End.");
}
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(GetInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(GetInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.vb Public Class SerialNumber
Private Shared sn As Integer = 1
Public Function GetNextSerialNumber() As Integer
Dim temp As Integer = sn
sn += 1
Return temp
End Function
End Class
Program.vb Module Main
Sub Main()
Exec(New SerialNumber(), 6)
Exec(New SerialNumber(), 4)
End Sub
Sub Exec(sn As SerialNumber, n As Integer)
Console.WriteLine("Start.")
For i As Integer = 0 To n - 1
Console.WriteLine(i & ":" & sn.GetNextSerialNumber())
Next
Console.WriteLine("End.")
End Sub
End Module
|
Singletonパターンを使用した例 SerialNumber.vb Public Class SerialNumber
Private sn As Integer = 1
Private Shared singleton As SerialNumber = New SerialNumber()
Private Sub New()
End Sub
Public Shared Function GetInstance() As SerialNumber
Return singleton
End Function
Public Function GetNextSerialNumber() As Integer
Dim temp As Integer = sn
sn += 1
Return temp
End Function
End Class
Program.vb Module Main
Sub Main()
Exec(SerialNumber.GetInstance(), 6)
Exec(SerialNumber.GetInstance(), 4)
End Sub
Sub Exec(sn As SerialNumber, n As Integer)
Console.WriteLine("Start.")
For i As Integer = 0 To n - 1
Console.WriteLine(i & ":" & sn.GetNextSerialNumber())
Next
Console.WriteLine("End.")
End Sub
End Module
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(GetInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(GetInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.js module.exports = class SerialNumber {
static sn = 1;
getNextSerialNumber() {
return SerialNumber.sn++;
}
}
Main.js const SerialNumber = require("./SerialNumber.js");
exec(new SerialNumber(), 6);
exec(new SerialNumber(), 4);
function exec(sn, n) {
process.stdout.write("Start.\n");
for (let i = 0; i < n; i++) {
process.stdout.write(i + ":" + sn.getNextSerialNumber() + "\n");
}
process.stdout.write("End.\n");
}
|
Singletonパターンを使用した例 SerialNumber.js module.exports = class SerialNumber {
static sn = 1;
static singleton = new SerialNumber();
static getInstance() {
return SerialNumber.singleton;
}
getNextSerialNumber() {
return SerialNumber.sn++;
}
}
Main.js const SerialNumber = require("./SerialNumber.js");
exec(SerialNumber.getInstance(), 6);
exec(SerialNumber.getInstance(), 4);
function exec(sn, n) {
process.stdout.write("Start.\n");
for (let i = 0; i < n; i++) {
process.stdout.write(i + ":" + sn.getNextSerialNumber() + "\n");
}
process.stdout.write("End.\n");
}
|
|
static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタの代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.pm package SerialNumber {
use feature 'state';
state $sn = 1;
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub getNextSerialNumber {
return $sn++;
}
}
Main.pl use lib qw(./);
use SerialNumber;
&exec(new SerialNumber(), 6);
&exec(new SerialNumber(), 4);
sub exec {
my ($sn, $n) = @_;
print "Start.";
foreach my $i ( 0 .. $n - 1 ) {
print $i . ":" . $sn->getNextSerialNumber() . "\n";
}
print "End.";
}
|
Singletonパターンを使用した例 SerialNumber.pm package SerialNumber {
use feature 'state';
state $singleton = undef;
sub _new {
my $this = { sn => 1 };
return bless $this;
}
sub getInstance {
return $singleton ||= _new();
}
sub getNextSerialNumber {
my ($this) = @_;
return $this->{sn}++;
}
}
Main.pl use lib qw(./);
use SerialNumber;
&exec(SerialNumber::getInstance(), 6);
&exec(SerialNumber::getInstance(), 4);
sub exec {
my ($sn, $n) = @_;
print "Start.";
foreach my $i ( 0 .. $n - 1 ) {
print $i . ":" . $sn->getNextSerialNumber() . "\n";
}
print "End.";
}
|
|
static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 なお、state は Perl 5.10 で導入されました。 |
コンストラクタは、誤ってnewされないように _new と別名で宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.rb class SerialNumber
@@sn = 1
def getNextSerialNumber()
m = Mutex.new()
m.synchronize do
sn = @@sn
@@sn += 1
return sn
end
end
end
Main.rb require './SerialNumber.rb'
def exec(sn, n)
puts "Start."
for i in (0..n - 1) do
puts "#{i}:#{sn.getNextSerialNumber()}"
end
puts "End."
end
exec(SerialNumber.new, 6)
exec(SerialNumber.new, 4)
|
Singletonパターンを使用した例 SerialNumber.rb class SerialNumber
@@sn = 1
@@singleton = SerialNumber.new()
def self.getInstance()
return @@singleton
end
def getNextSerialNumber()
m = Mutex.new()
m.synchronize do
sn = @@sn
@@sn += 1
return sn
end
end
end
Main.rb require './SerialNumber.rb'
def exec(sn, n)
puts "Start."
for i in (0..n - 1) do
puts "#{i}:#{sn.getNextSerialNumber()}"
end
puts "End."
end
exec(SerialNumber::getInstance(), 6)
exec(SerialNumber::getInstance(), 4)
|
|
static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタの代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.py class SerialNumber:
sn = 1
def getNextSerialNumber(self):
n = SerialNumber.sn
SerialNumber.sn += 1
return n
Main.py from SerialNumber import SerialNumber
def exec(sn, n):
print("Start.")
for i in range(n):
print(f"{i}:{sn.getNextSerialNumber()}")
print("End.")
exec(SerialNumber(), 6)
exec(SerialNumber(), 4)
|
Singletonパターンを使用した例 SerialNumber.py class SerialNumber:
sn = 1
__instance = None
@classmethod
def getInstance(cls):
if not cls.__instance:
cls.__instance = cls()
return cls.__instance
def getNextSerialNumber(self):
n = SerialNumber.sn
SerialNumber.sn += 1
return n
Main.js from SerialNumber import SerialNumber
def exec(sn, n):
print("Start.")
for i in range(n):
print(f"{i}:{sn.getNextSerialNumber()}")
print("End.")
exec(SerialNumber.getInstance(), 6)
exec(SerialNumber.getInstance(), 4)
|
|
static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタの代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.php <?php
class SerialNumber {
private static $sn = 1;
public function getNextSerialNumber() {
return self::$sn++;
}
}
?>
Main.java <?php
require_once('SerialNumber.php');
function _exec($sn, $n) {
print "Start.\n";
for ($i = 0; $i < $n; $i++) {
print $i . ":" . $sn->getNextSerialNumber() . "\n";
}
print "End.\n";
}
_exec(new SerialNumber(), 6);
_exec(new SerialNumber(), 4);
?>
|
Singletonパターンを使用した例 SerialNumber.php <?php
class SerialNumber {
private static $sn = 1;
private static $singleton;
private function __construct() {}
public static function getInstance() {
if (!isset(self::$singleton)) {
self::$singleton = new SerialNumber();
}
return self::$singleton;
}
public function getNextSerialNumber() {
return self::$sn++;
}
}
?>
Main.java <?php
require_once('SerialNumber.php');
function _exec($sn, $n) {
print "Start.\n";
for ($i = 0; $i < $n; $i++) {
print $i . ":" . $sn->getNextSerialNumber() . "\n";
}
print "End.\n";
}
_exec(SerialNumber::getInstance(), 6);
_exec(SerialNumber::getInstance(), 4);
?>
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.ts export
class SerialNumber {
private static sn:number = 1;
public getNextSerialNumber():number {
return SerialNumber.sn++;
}
}
Main.ts import {SerialNumber} from "./SerialNumber";
exec(new SerialNumber(), 6);
exec(new SerialNumber(), 4);
function exec(sn:SerialNumber, n:number) {
process.stdout.write("Start.\n");
for (let i:number = 0; i < n; i++) {
process.stdout.write(i + ":" + sn.getNextSerialNumber() + "\n");
}
process.stdout.write("End.\n");
}
|
Singletonパターンを使用した例 SerialNumber.ts export
class SerialNumber {
private static sn:number = 1;
private static singleton:SerialNumber = new SerialNumber();
private constructor() {}
public static getInstance():SerialNumber {
return SerialNumber.singleton;
}
public getNextSerialNumber():number {
return SerialNumber.sn++;
}
}
Main.ts import {SerialNumber} from "./SerialNumber";
exec(SerialNumber.getInstance(), 6);
exec(SerialNumber.getInstance(), 4);
function exec(sn:SerialNumber, n:number) {
process.stdout.write("Start.\n");
for (let i:number = 0; i < n; i++) {
process.stdout.write(i + ":" + sn.getNextSerialNumber() + "\n");
}
process.stdout.write("End.\n");
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.swift public class SerialNumber {
private static var sn:Int = 1
public func getNextSerialNumber() -> Int {
let n:Int = SerialNumber.sn
SerialNumber.sn += 1
return n
}
}
Main.swift exec(SerialNumber(), 6)
exec(SerialNumber(), 4)
func exec(_ sn:SerialNumber, _ n:Int) {
print("Start.")
for i in 0..<n {
print("\(i):\(sn.getNextSerialNumber())")
}
print("End.")
}
|
Singletonパターンを使用した例 SerialNumber.swift public class SerialNumber {
private static var sn:Int = 1
private static var singleton:SerialNumber = SerialNumber();
private init() {}
public static func getInstance() -> SerialNumber {
return SerialNumber.singleton
}
public func getNextSerialNumber() -> Int {
let n:Int = SerialNumber.sn
SerialNumber.sn += 1
return n
}
}
Main.swift exec(SerialNumber.getInstance(), 6)
exec(SerialNumber.getInstance(), 4)
func exec(_ sn:SerialNumber, _ n:Int) {
print("Start.")
for i in 0..<n {
print("\(i):\(sn.getNextSerialNumber())")
}
print("End.")
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.kt private var sn: Int = 1
class SerialNumber {
@Synchronized
fun getNextSerialNumber(): Int = sn++
}
Main.kt fun main() {
fun exec(sn:SerialNumber, n:Int) {
println("Start.")
for (i in 0 until n) {
println("$i:${sn.getNextSerialNumber()}")
}
println("End.")
}
exec(SerialNumber(), 6)
exec(SerialNumber(), 4)
}
|
Singletonパターンを使用した例 SerialNumber.kt object SerialNumber {
private var sn: Int = 1
fun getInstance(): SerialNumber = this
@Synchronized
fun getNextSerialNumber(): Int = sn++
}
Main.kt fun main() {
fun exec(sn:SerialNumber, n:Int) {
println("Start.")
for (i in 0 until n) {
println("$i:${sn.getNextSerialNumber()}")
}
println("End.")
}
exec(SerialNumber.getInstance(), 6)
exec(SerialNumber.getInstance(), 4)
}
|
|
パッケージレベルの変数(クラス外で定義した変数)を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 @synchronized に注意してください。これは、宣言されたメソッドが同時に複数のインスタンスから呼ばれないようにするためのものです。これによって、シリアルナンバーを参照して1加算する前に、別のインスタンスから呼ばれて、同じ数値を参照してしまうというトラブルを避けています。 |
誤ってインスタンスが生成されないように class ではなく object 宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、パッケージレベルの変数か companion object を使用すれば値を一元的に管理することができます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.scala object SerialNumber {
private var sn: Int = 1
private def get(): Int = {
this.synchronized {
sn += 1
sn - 1
}
}
}
class SerialNumber {
def getNextSerialNumber(): Int = SerialNumber.get()
}
Main.scala object Main {
def main(args: Array[String]) {
exec(new SerialNumber(), 6)
exec(new SerialNumber(), 4)
}
private def exec(sn: SerialNumber, n: Int) {
System.out.println("Start.")
for (i <- 0 until n) {
System.out.println(i + ":" + sn.getNextSerialNumber())
}
System.out.println("End.")
}
}
|
Singletonパターンを使用した例 SerialNumber.scala object SerialNumber {
private var sn: Int = 1
private val singleton = new SerialNumber()
def getInstance(): SerialNumber = singleton
}
class SerialNumber private() {
def getNextSerialNumber(): Int = {
SerialNumber.sn += 1
SerialNumber.sn - 1
}
}
Main.scala object Main {
def main(args: Array[String]) {
exec(SerialNumber.getInstance(), 6)
exec(SerialNumber.getInstance(), 4)
}
private def exec(sn: SerialNumber, n: Int) {
System.out.println("Start.")
for (i <- 0 until n) {
System.out.println(i + ":" + sn.getNextSerialNumber())
}
System.out.println("End.")
}
}
|
|
パッケージレベルの変数(クラス外で定義した変数)を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 this.synchronized に注意してください。これは、宣言されたメソッドが同時に複数のインスタンスから呼ばれないようにするためのものです。これによって、シリアルナンバーを参照して1加算する前に、別のインスタンスから呼ばれて、同じ数値を参照してしまうというトラブルを避けています。 |
誤ってインスタンスが生成されないように class ではなく object 宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、パッケージレベルの変数か companion object を使用すれば値を一元的に管理することができます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.groovy class SerialNumber {
private static int sn = 1
synchronized int getNextSerialNumber() {
return sn++
}
} Main.groovy class Main {
static void main(String[] args) {
exec(new SerialNumber(), 6)
exec(new SerialNumber(), 4)
}
private static void exec(SerialNumber sn, int n) {
System.out.println("Start.")
for (int i in 0..<n) {
System.out.println(i + ":" + sn.getNextSerialNumber())
}
System.out.println("End.")
}
}
|
Singletonパターンを使用した例 SerialNumber.groovy class SerialNumber {
private int sn = 1
private static SerialNumber singleton = new SerialNumber()
private SerialNumber() {}
static SerialNumber getInstance() {
return singleton
}
synchronized int getNextSerialNumber() {
return sn++
}
}
Main.groovy class Main {
static void main(String[] args) {
exec(SerialNumber.getInstance(), 6)
exec(SerialNumber.getInstance(), 4)
}
private static void exec(SerialNumber sn, int n) {
System.out.println("Start.")
for (int i in 0..<n) {
System.out.println(i + ":" + sn.getNextSerialNumber())
}
System.out.println("End.")
}
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 synchronized に注意してください。これは、宣言されたメソッドが同時に複数のインスタンスから呼ばれないようにするためのものです。これによって、シリアルナンバーを参照して1加算する前に、別のインスタンスから呼ばれて、同じ数値を参照してしまうというトラブルを避けています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.go type SerialNumber struct {}
var sn = 1
func (*SerialNumber) GetNextSerialNumber() int {
sn++
return sn - 1
} Main.go import "fmt"
func main() {
exec(new(SerialNumber), 6)
exec(new(SerialNumber), 4)
}
func exec(sn *SerialNumber, n int) {
fmt.Println("Start.")
for i:=0; i<n;i++ {
fmt.Println("%d. %d\n", i, sn.GetNumber())
}
fmt.Println("End.")
}
|
Singletonパターンを使用した例 SerialNumber.go type SerialNumber {
sn int
}
var instance = NewSerialNumber()
func GetInstance() *SerialNumber {
return instance
}
func (self *SerialNumber) GetNumber() int {
self.sn++
return self.sn - 1
}
func newSerialNumber() *SerialNumber {
var ins = new(SerialNumber)
ins.sn = 1
return ins
}
Main.go import "fmt"
func Main() {
exec(GetInstance(), 6)
exec(GetInstance(), 4)
}
func exec(sn *SerialNumber, n int) {
fmt.Println("Start.")
for i:=0; i<n; i++ {
fmt.Println(i + ":" + sn.GetNumber())
}
fmt.Println("End.")
}
|
|
private なパッケージ変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 パッケージ変数はローカル変数とは違い、プログラム全体で一つの値が共有されます。 |
コンストラクタは、インスタンスを誤って生成されないように、小文字から始まる名前で宣言されています。ただし、その代わりに、インスタンスを返すメソッド(GetInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private なパッケージ変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(GetInstance() の中で数を数えて、new(SerialNumber) をする)。パッケージ変数を使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 serialnumber.d static import core.atomic;
public class SerialNumber {
private static int sn = 1;
public int getNextSerialNumber() {
synchronized {
return sn++;
}
}
} main.d import std.stdio;
import serialnumber;
public int main() {
exec(new SerialNumber(), 6);
exec(new SerialNumber(), 4);
return 0;
}
private static void exec(SerialNumber sn, in int n) {
writeln("Start.");
foreach (int i; 0..n) {
writefln("%d:%d",i, sn.getNextSerialNumber());
}
writeln("End.");
}
|
Singletonパターンを使用した例 serialnumber.java import core.atomic;
public class SerialNumber {
private int sn = 1;
private static SerialNumber singleton;
public static this() {
singleton = new SerialNumber();
}
public static SerialNumber getInstance() {
return singleton;
}
public int getNextSerialNumber() {
synchronized {
return sn++;
}
}
} main.d import std.stdio;
import serialnumber;
public int main() {
exec(SerialNumber.getInstance(), 6);
exec(SerialNumber.getInstance(), 4);
return 0;
}
private static void exec(SerialNumber sn, in int n) {
writeln("Start.");
foreach (int i; 0..n) {
writefln("%d:%d",i, sn.getNextSerialNumber());
}
writeln("End.");
}
|
|
private で static なクラス変数を宣言し、同じ番号のシリアルナンバーが返らないようにしています。 synchronized に注意してください。これは、宣言されたメソッドが同時に複数のインスタンスから呼ばれないようにするためのものです。これによって、シリアルナンバーを参照して1加算する前に、別のインスタンスから呼ばれて、同じ数値を参照してしまうというトラブルを避けています。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singletonパターンを使わなくても、private で static なクラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singletonパターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、new SerialNumber() をする)。staticを使った場合は、1つに制限することしかできません。
|
Singletonパターンを使用しない例 SerialNumber.pas unit UnitSerialNumber;
interface
type
SerialNumber = class
private
class var sn:integer;
class constructor Create();
public
function getNextSerialNumber():integer;
end;
implementation
class constructor SerialNumber.Create();
begin
sn := 1;
end;
function SerialNumber.getNextSerialNumber():integer;
begin
Result := sn;
inc(sn);
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitSerialNumber;
procedure exec(sn:SerialNumber; n:integer);
var i:integer;
begin
Writeln('Start.');
for i := 0 to n-1 do
begin
Writeln(Format('%d:%d', [i, sn.getNextSerialNumber()]));
end;
Writeln('End.');
end;
var sn:SerialNumber;
begin
sn := SerialNumber.Create();
exec(sn, 6);
sn.Free;
sn := SerialNumber.Create();
exec(sn, 4);
sn.Free;
end.
|
Singletonパターンを使用した例 SerialNumber.pas unit UnitSerialNumber;
interface
type
SerialNumber = class
private
class var singleton:SerialNumber;
var sn:integer;
class constructor Create();
constructor Create();
public
class function getInstance():SerialNumber;
function getNextSerialNumber():integer;
end;
implementation
class constructor SerialNumber.Create();
begin
singleton := SerialNumber.Create();
end;
class function SerialNumber.getInstance():SerialNumber;
begin
Result := singleton;
end;
constructor SerialNumber.Create();
begin
sn := 1;
end;
function SerialNumber.getNextSerialNumber():integer;
begin
Result := sn;
inc(sn);
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitSerialNumber;
procedure exec(sn:SerialNumber; n:integer);
var i:integer;
begin
Writeln('Start.');
for i := 0 to n-1 do
begin
Writeln(Format('%d:%d', [i, sn.getNextSerialNumber()]));
end;
Writeln('End.');
end;
begin
exec(SerialNumber.getInstance(), 6);
exec(SerialNumber.getInstance(), 4);
end.
|
|
private なクラス変数を class var で宣言し、同じ番号のシリアルナンバーが返らないようにしています。 クラス変数はローカル変数とは違い、プログラム全体で一つの値が共有されます。 |
コンストラクタは、誤ってnewされないようにprivate宣言されています。ただし、その代わりに、インスタンスを返すメソッド(getInstance)が用意されています。シリアルナンバーが欲しいインスタンスは、このメソッドを呼びインスタンスを受け取ります。何回呼ぼうが同じインスタンスが得られます。よって、得られるシリアルナンバーもこのインスタンスが管理しているシリアルナンバーということになります。 |
この例から分かるように、別に Singleton パターンを使わなくても、クラス変数で構成されたクラスを使えば1つであることが保証されます。
それでは、Singleton パターンを使わなければできないことは何でしょう? それは、インスタンスの数を1つではなく、2つや3つのように特定の数に制限することです(getInstance() の中で数を数えて、SerialNumber.Create() をする)。クラス変数を使った場合は、1つに制限することしかできません。