<読書ノート>Thinking in python(Pythonデザインモード)1.Singltonのc++とpythonの実現
83207 ワード
1.pythonの天然の汎用的な特徴のため、pythonにはインタフェースの継承がなく、すべての継承は継承を実現し、サブクラスは親の実現を継承する.
2.Singlton単品モード singlton in c++
次に、最も簡単なC++実装を見てみましょう.
クラスstatic変数、およびデフォルトのコンストラクション関数をプライベート化します.
GlobalClassのエンティティは1つしか存在しません
1 #include
2
using
namespace
std;
3
4
class
GlobalClass {
5
public
:
6
static
GlobalClass
*
instance();
7
static
void
create();
8
static
void
destroy();
9
void
print() {
10
cout
<<
"
haha
"
<<
endl;
11
}
12
private
:
13
static
GlobalClass
*
s_instance;
14
GlobalClass();
15
~
GlobalClass(){
16
//
destroy();
17
cout
<<
"
destruct
"
<<
endl;
18
19
}
20
};
21
22
GlobalClass
*
GlobalClass::s_instance
=
NULL;
23
24
GlobalClass::GlobalClass() {
25
cout
<<
"
construct global class
"
<<
endl;
26
}
27
//
GloblaClass::~GlobalClass() {
28
//
destroy();
29
//
cout << "destruct" << endl;
30
//
}
31
GlobalClass
*
GlobalClass::instance() {
32
return
s_instance;
33
}
34
35
void
GlobalClass::create() {
36
if
(
!
s_instance)
37
s_instance
=
new
GlobalClass();
38
}
39
40
void
GlobalClass::destroy() {
41
delete s_instance;
42
s_instance
=
NULL;
43
cout
<<
"
delete ok
"
<<
endl;
44
}
45
46
int
main(
int
argc,
char
*
argv[])
47
{
48
//
GlobalClass my_global_class; //can't create by this
49
GlobalClass::create();
50
GlobalClass
*
p_global_class
=
GlobalClass::instance();
51
p_global_class
->
print();
52
GlobalClass::destroy();
53
return
0
;
54
}
//result
construct global class
haha
destruct
delete ok singlton in python
pythonでは著者らが述べたsingltonの概念が緩和され,
Alex Martelli makes the observation that what we really want with a Singleton is to have a single set of state data for all objects. That is, you could create as many objects as you want and as long as they all refer to the same state information then you achieve the effect of Singleton.
任意に多くのオブジェクトを持つことができますが、同じステータス情報、すなわちsingltonを指します.Borg利用_dict__属性が巧みに一つ実現した
singltonモード.
このスキームは,簡潔で明確であり,継承によって多重化しやすい.もちろん著者らは,以下の方法と比較して,多くの他の実装方法についても言及した.
1 class OnlyOne:
2
3
class
__OnlyOne
:
4
def
__init__
(self, arg):
5
self.val
=
arg
6
def
__str__
(self):
7
return
'
self
'
+
self.val
8
#
return `self` + self.val
9
instance
=
None
10
def
__init__
(self, arg):
11
if
not
OnlyOne.instance:
12
OnlyOne.instance
=
OnlyOne.
__OnlyOne
(arg)
13
else
:
14
OnlyOne.instance.val
=
arg
15
def
__getattr__
(self, name):
16
return
getattr(self.instance, name)
17
18
19
x
=
OnlyOne(
'
sausage
'
)
20
print
(x)
21
y
=
OnlyOne(
'
eggs
'
)
22
print
(y)
23
z
=
OnlyOne(
'
spam
'
)
24
print
(z)
25
26
print
(x)
27
print
(y)
28
print
(z)
29
print
(
'
x
'
)
30
print
(
'
y
'
)
31
print
(
'
z
'
)
32
33
print
(x.instance)
34
output
=
'''
35
selfsausage
36
selfeggs
37
selfspam
38
selfspam
39
selfspam
40
selfspam
41
x
42
y
43
z
44
selfspam
45
'''
2.Singlton単品モード
次に、最も簡単なC++実装を見てみましょう.
クラスstatic変数、およびデフォルトのコンストラクション関数をプライベート化します.
GlobalClassのエンティティは1つしか存在しません
1 #include
2
using
namespace
std;
3
4
class
GlobalClass {
5
public
:
6
static
GlobalClass
*
instance();
7
static
void
create();
8
static
void
destroy();
9
void
print() {
10
cout
<<
"
haha
"
<<
endl;
11
}
12
private
:
13
static
GlobalClass
*
s_instance;
14
GlobalClass();
15
~
GlobalClass(){
16
//
destroy();
17
cout
<<
"
destruct
"
<<
endl;
18
19
}
20
};
21
22
GlobalClass
*
GlobalClass::s_instance
=
NULL;
23
24
GlobalClass::GlobalClass() {
25
cout
<<
"
construct global class
"
<<
endl;
26
}
27
//
GloblaClass::~GlobalClass() {
28
//
destroy();
29
//
cout << "destruct" << endl;
30
//
}
31
GlobalClass
*
GlobalClass::instance() {
32
return
s_instance;
33
}
34
35
void
GlobalClass::create() {
36
if
(
!
s_instance)
37
s_instance
=
new
GlobalClass();
38
}
39
40
void
GlobalClass::destroy() {
41
delete s_instance;
42
s_instance
=
NULL;
43
cout
<<
"
delete ok
"
<<
endl;
44
}
45
46
int
main(
int
argc,
char
*
argv[])
47
{
48
//
GlobalClass my_global_class; //can't create by this
49
GlobalClass::create();
50
GlobalClass
*
p_global_class
=
GlobalClass::instance();
51
p_global_class
->
print();
52
GlobalClass::destroy();
53
return
0
;
54
}
//result
construct global class
haha
destruct
delete ok
effective c++ , local static 。 Siglton
1
//
file singlton.h
2
3
#ifndef _SINGLTON_H_
4
#define
_SINGLTON_H_
5
#include
<
iostream
>
6
using
namespace
std;
7
8
class
GlobalClass {
9
public
:
10
static
GlobalClass
&
instance(
int
weight
=
3
){
11
static
GlobalClass global_object(weight);
12
return
global_object;
13
}
14
void
print() {
15
cout
<<
"
haha
"
<<
this
<<
endl;
16
cout
<<
m_weight
<<
endl
<<
endl;
17
}
18
~
GlobalClass(){
19
cout
<<
"
destruct
"
<<
this
<<
endl;
20
21
}
22
void
addOne() {
23
m_weight
+=
1
;
24
}
25
26
private
:
27
GlobalClass() {
28
cout
<<
"
construct global class
"
<<
this
<<
endl;
29
30
}
31
GlobalClass(
int
weight):m_weight(weight){ cout
<<
"
construct global class with weight
"
<<
this
<<
endl;}
32
GlobalClass
&
operator
=
(
const
GlobalClass
&
);
33
GlobalClass(
const
GlobalClass
&
);
34
int
m_weight;
35
};
36
#endif
37
38
39
//
file use_singlton.h
40
#ifndef USE_SIGLTON_H
41
#define
USE_SIGLTON_H
42
43
#include
"
singlton.h
"
44
void
useSinglton();
45
46
#endif
47
48
//
file use_singlton.cc
49
#include
<
iostream
>
50
#include
"
use_singlton.h
"
51
using
namespace
std;
52
void
useSinglton() {
53
GlobalClass
&
p_global_class
=
GlobalClass::instance(
16
);
54
p_global_class.print();
55
p_global_class.addOne();
56
p_global_class.print();
57
58
GlobalClass
&
p_global_class2
=
GlobalClass::instance(
46
);
59
p_global_class2.print();
60
p_global_class2.addOne();
61
p_global_class2.print();
62
}
63
64
//
file test_singlton.cc
65
#include
<
iostream
>
66
#include
"
singlton.h
"
67
#include
"
use_singlton.h
"
68
using
namespace
std;
69
70
int
main(
int
argc,
char
*
argv[])
71
{
72
cout
<<
"
use singlton
"
<<
endl;
73
useSinglton();
74
75
cout
<<
"
wa ha ha
"
<<
endl;
76
GlobalClass
&
p_global_class
=
GlobalClass::instance(
4
);
77
p_global_class.print();
78
p_global_class.addOne();
79
p_global_class.print();
80
81
GlobalClass
&
p_global_class2
=
GlobalClass::instance(
8
);
82
p_global_class2.print();
83
p_global_class2.addOne();
84
p_global_class2.print();
85
86
cout
<<
"
ha ha wa
"
<<
endl;
87
useSinglton();
88
89
return
0
;
90
}
91
92
//
allen:~/study/design_pattern/singlton_test$ g++ -g -o test_singlton test_singlton.cc use_singlton.cc
93
allen:
~/
study
/
design_pattern
/
singlton_test$ .
/
test_singlton
94
use singlton
95
construct
global
class
with weight0x804a5c0
96
haha0x804a5c0
97
16
98
99
haha0x804a5c0
100
17
101
102
haha0x804a5c0
103
17
104
105
haha0x804a5c0
106
18
107
108
wa ha ha
109
haha0x804a5c0
110
18
111
112
haha0x804a5c0
113
19
114
115
haha0x804a5c0
116
19
117
118
haha0x804a5c0
119
20
120
121
ha ha wa
122
haha0x804a5c0
123
20
124
125
haha0x804a5c0
126
21
127
128
haha0x804a5c0
129
21
130
131
haha0x804a5c0
132
22
133
134
destruct0x804a5c0
135
local static , , , static ,
main , 。
Singlton , C++ , , 。
singlton , , shared_ptr, 。
OPEMESH singlton , static ( )。
main siglton , shared_ptr new , OPEMESH static ( ).
// shared_ptr singlton
1
#include
<
iostream
>
2
#include
<
tr1
/
memory
>
3
using
namespace
std;
4
using
namespace
std::tr1;
5
template
<
typename T
>
6
class
Singlton {
7
public
:
8
static
T
*
instance();
9
static
void
create();
10
void
print() {
11
cout
<<
"
haha
"
<<
endl;
12
}
13
~
Singlton() {
14
cout
<<
"
destruct singlton
"
<<
endl;
15
}
16
protected
:
17
Singlton();
18
//
private:
19
protected
:
20
static
shared_ptr
<
T
>
s_instance;
21
//
Singlton();
22
};
23
template
<
typename T
>
24
shared_ptr
<
T
>
Singlton
<
T
>
::s_instance;
25
26
template
<
typename T
>
27
Singlton
<
T
>
::Singlton() {
28
cout
<<
"
construct singlton
"
<<
endl;
29
}
30
31
template
<
typename T
>
32
T
*
Singlton
<
T
>
::instance() {
33
return
s_instance.
get
();
34
}
35
36
template
<
typename T
>
37
void
Singlton
<
T
>
::create() {
38
if
(
!
s_instance.
get
())
39
s_instance.reset(
new
T);
40
41
}
42
43
//
well , Singlton<T>::create() MySinglton ,
44
//
Singlton<MySinglton>::create()
45
//
class MySinglton : public Singlton<MySinglton> {
46
//
//
private:
47
//
public:
48
//
MySinglton(){
49
//
cout << "construct my singlton" << endl;
50
//
}
51
//
52
//
};
53
class
MySinglton :
public
Singlton
<
MySinglton
>
{
54
friend
class
Singlton
<
MySinglton
>
;
55
private
:
56
MySinglton(){
57
cout
<<
"
construct my singlton
"
<<
endl;
58
}
59
MySinglton
*
MyInstance() {
60
return
s_instance.
get
();
61
}
62
};
63
64
//
or can directyly define one class like MyClass1, and to not consider siglton part,
65
//
than use Singlton<MyClass1> is OK. May be typedef Singlton<MyClass1> MyClass1Singlton
66
//
and use MyClass1Siglton
67
int
main(
int
argc,
char
*
argv[])
68
{
69
70
MySinglton::create();
71
MySinglton
*
p_my_singlton
=
MySinglton::instance();
72
p_my_singlton
->
print();
73
return
0
;
74
}
75
/*
result
76
construct singlton
77
construct my singlton
78
haha
79
destruct singlton
80
*/
OPMESH singlton , :)
1
//
SingltonT.hh
2
//
=============================================================================
3
//
4
//
Implements a simple singleton template
5
//
6
//
=============================================================================
7
8
9
#ifndef __SINGLETON_HH__
10
#define
__SINGLETON_HH__
11
12
13
//
=== INCLUDES ================================================================
14
15
//
OpenMesh
16
#include
<
OpenMesh
/
Core
/
System
/
config.h
>
17
18
//
STL
19
#include
<
stdexcept
>
20
#include
<
iostream
>
21
22
23
//
== NAMESPACES ===============================================================
24
25
26
namespace
OpenMesh {
27
28
29
//
=== IMPLEMENTATION ==========================================================
30
31
32
/*
* A simple singleton template.
33
Encapsulates an arbitrary class and enforces its uniqueness.
34
*/
35
36
template
<
typename T
>
37
class
SingletonT
38
{
39
public
:
40
41
/*
* Singleton access function.
42
Use this function to obtain a reference to the instance of the
43
encapsulated class. Note that this instance is unique and created
44
on the first call to Instance().
45
*/
46
47
static
T
&
Instance()
48
{
49
if
(
!
pInstance__)
50
{
51
//
check if singleton alive
52
if
(destroyed__)
53
{
54
OnDeadReference();
55
}
56
//
first time request -> initialize
57
else
58
{
59
Create();
60
}
61
}
62
return
*
pInstance__;
63
}
64
65
66
private
:
67
68
//
Disable constructors/assignment to enforce uniqueness
69
SingletonT();
70
SingletonT(
const
SingletonT
&
);
71
SingletonT
&
operator
=
(
const
SingletonT
&
);
72
73
//
Create a new singleton and store its pointer
74
static
void
Create()
75
{
76
static
T theInstance;
77
pInstance__
=
&
theInstance;
78
}
79
80
//
Will be called if instance is accessed after its lifetime has expired
81
static
void
OnDeadReference()
82
{
83
throw
std::runtime_error(
"
[Singelton error] - Dead reference detected!
"
);
84
}
85
86
virtual
~
SingletonT()
87
{
88
pInstance__
=
0
;
89
destroyed__
=
true
;
90
}
91
92
static
T
*
pInstance__;
93
static
bool
destroyed__;
94
};
95
96
97
98
//
=============================================================================
99
}
//
namespace OpenMesh
100
//
=============================================================================
101
#if
defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SINGLETON_C)
102
# define OPENMESH_SINGLETON_TEMPLATES
103
# include
"
SingletonT.cc
"
104
#endif
105
//
=============================================================================
106
#endif
//
__SINGLETON_HH__
107
//
=============================================================================
108
109
110
//
SingltonT.cc
111
//
=============================================================================
112
//
113
//
Implements a simple singleton template
114
//
115
//
=============================================================================
116
117
118
#define
OPENMESH_SINGLETON_C
119
120
121
//
== INCLUDES =================================================================
122
123
124
//
header
125
#include
<
OpenMesh
/
Core
/
Utils
/
SingletonT.hh
>
126
127
128
//
== NAMESPACES ===============================================================
129
130
131
namespace
OpenMesh {
132
133
134
//
== SINGLETON'S DATA =========================================================
135
136
137
template
<
class
T
>
138
T
*
SingletonT
<
T
>
::pInstance__
=
0
;
139
140
template
<
class
T
>
141
bool
SingletonT
<
T
>
::destroyed__
=
false
;
142
143
144
//
=============================================================================
145
}
//
namespace OpenMesh
146
//
=============================================================================
147
typedef SingletonT<LoopSchemeMaskDouble> LoopSchemeMaskDoubleSingleton;
pythonでは著者らが述べたsingltonの概念が緩和され,
Alex Martelli makes the observation that what we really want with a Singleton is to have a single set of state data for all objects. That is, you could create as many objects as you want and as long as they all refer to the same state information then you achieve the effect of Singleton.
任意に多くのオブジェクトを持つことができますが、同じステータス情報、すなわちsingltonを指します.Borg利用_dict__属性が巧みに一つ実現した
singltonモード.
1
class
Borg():
2
shared_dict
=
{}
3
def
__init__
(self):
4
self.
__dict__
=
self.shared_dict
5
6
class
Singleton(Borg):
7
def
__init__
(self, arg):
8
Borg.
__init__
(self)
9
self.val
=
arg
10
def
__str__
(self):
11
print
(self.
__dict__
)
12
return
self.val
13
14
15
if
__name__
==
'
__main__
'
:
16
x
=
Singleton(
'
abc
'
)
17
y
=
Singleton(
'
def
'
)
18
print
(x)
19
print
(y)
20
21
output
=
'''
22
{'val': 'def'}
23
def
24
{'val': 'def'}
25
def
26
'''
このスキームは,簡潔で明確であり,継承によって多重化しやすい.もちろん著者らは,以下の方法と比較して,多くの他の実装方法についても言及した.
1 class OnlyOne:
2
3
class
__OnlyOne
:
4
def
__init__
(self, arg):
5
self.val
=
arg
6
def
__str__
(self):
7
return
'
self
'
+
self.val
8
#
return `self` + self.val
9
instance
=
None
10
def
__init__
(self, arg):
11
if
not
OnlyOne.instance:
12
OnlyOne.instance
=
OnlyOne.
__OnlyOne
(arg)
13
else
:
14
OnlyOne.instance.val
=
arg
15
def
__getattr__
(self, name):
16
return
getattr(self.instance, name)
17
18
19
x
=
OnlyOne(
'
sausage
'
)
20
(x)
21
y
=
OnlyOne(
'
eggs
'
)
22
(y)
23
z
=
OnlyOne(
'
spam
'
)
24
(z)
25
26
(x)
27
(y)
28
(z)
29
(
'
x
'
)
30
(
'
y
'
)
31
(
'
z
'
)
32
33
(x.instance)
34
output
=
'''
35
selfsausage
36
selfeggs
37
selfspam
38
selfspam
39
selfspam
40
selfspam
41
x
42
y
43
z
44
selfspam
45
'''