Skip to content

Commit c05911b

Browse files
Singleton Patterns
1 parent 3bf38c5 commit c05911b

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# all members are static :)
2+
3+
class CEO:
4+
__shared_state = {
5+
'name': 'Steve',
6+
'age': 55
7+
}
8+
9+
def __init__(self):
10+
self.__dict__ = self.__shared_state
11+
12+
def __str__(self):
13+
return f'{self.name} is {self.age} years old'
14+
15+
16+
class Monostate:
17+
_shared_state = {}
18+
19+
def __new__(cls, *args, **kwargs):
20+
obj = super(Monostate, cls).__new__(cls, *args, **kwargs)
21+
obj.__dict__ = cls._shared_state
22+
return obj
23+
24+
25+
class CFO(Monostate):
26+
def __init__(self):
27+
self.name = ''
28+
self.money_managed = 0
29+
30+
def __str__(self):
31+
return f'{self.name} manages ${self.money_managed}bn'
32+
33+
if __name__ == '__main__':
34+
ceo1 = CEO()
35+
print(ceo1)
36+
37+
ceo1.age = 66
38+
39+
ceo2 = CEO()
40+
ceo2.age = 77
41+
print(ceo1)
42+
print(ceo2)
43+
44+
ceo2.name = 'Tim'
45+
46+
ceo3 = CEO()
47+
print(ceo1, ceo2, ceo3)
48+
49+
cfo1 = CFO()
50+
cfo1.name = 'Sheryl'
51+
cfo1.money_managed = 1
52+
53+
print(cfo1)
54+
55+
cfo2 = CFO()
56+
cfo2.name = 'Ruth'
57+
cfo2.money_managed = 10
58+
print(cfo1, cfo2, sep='\n')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import unittest
2+
3+
4+
class Singleton(type):
5+
_instances = {}
6+
7+
def __call__(cls, *args, **kwargs):
8+
if cls not in cls._instances:
9+
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
10+
return cls._instances[cls]
11+
12+
13+
class Database(metaclass=Singleton):
14+
def __init__(self):
15+
self.population = {}
16+
f = open('capitals.txt', 'r')
17+
lines = f.readlines()
18+
for i in range(0, len(lines), 2):
19+
self.population[lines[i].strip()] = int(lines[i + 1].strip())
20+
f.close()
21+
22+
23+
class SingletonRecordFinder:
24+
def total_population(self, cities):
25+
result = 0
26+
for c in cities:
27+
result += Database().population[c]
28+
return result
29+
30+
31+
class ConfigurableRecordFinder:
32+
def __init__(self, db):
33+
self.db = db
34+
35+
def total_population(self, cities):
36+
result = 0
37+
for c in cities:
38+
result += self.db.population[c]
39+
return result
40+
41+
42+
class DummyDatabase:
43+
population = {
44+
'alpha': 1,
45+
'beta': 2,
46+
'gamma': 3
47+
}
48+
49+
def get_population(self, name):
50+
return self.population[name]
51+
52+
class SingletonTests(unittest.TestCase):
53+
def test_is_singleton(self):
54+
db = Database()
55+
db2 = Database()
56+
self.assertEqual(db, db2)
57+
58+
def test_singleton_total_population(self):
59+
""" This tests on a live database :( """
60+
rf = SingletonRecordFinder()
61+
names = ['Seoul', 'Mexico City']
62+
tp = rf.total_population(names)
63+
self.assertEqual(tp, 17500000 + 17400000) # what if these change?
64+
65+
ddb = DummyDatabase()
66+
67+
def test_dependent_total_population(self):
68+
crf = ConfigurableRecordFinder(self.ddb)
69+
self.assertEqual(
70+
crf.total_population(['alpha', 'beta']),
71+
3
72+
)
73+
74+
if __name__ == '__main__':
75+
unittest.main()

0 commit comments

Comments
 (0)