รูปแบบการออกแบบ Python - คู่มือฉบับย่อ
รูปแบบการออกแบบใช้เพื่อแสดงถึงรูปแบบที่นักพัฒนาใช้ในการสร้างซอฟต์แวร์หรือเว็บแอปพลิเคชัน รูปแบบเหล่านี้ถูกเลือกตามการวิเคราะห์ความต้องการ รูปแบบอธิบายวิธีการแก้ปัญหาเมื่อใดและที่ไหนที่จะใช้วิธีแก้ปัญหาและผลที่ตามมาของการนำไปใช้
โครงสร้างของรูปแบบการออกแบบ
เอกสารเกี่ยวกับรูปแบบการออกแบบจะถูกเก็บรักษาไว้ในลักษณะที่เน้นมากขึ้นเกี่ยวกับเทคโนโลยีที่ใช้และในลักษณะใด แผนภาพต่อไปนี้อธิบายโครงสร้างพื้นฐานของเอกสารเกี่ยวกับรูปแบบการออกแบบ
ชื่อรูปแบบ
อธิบายรูปแบบในลักษณะที่สั้นและมีประสิทธิภาพ
เจตนา / แรงจูงใจ
อธิบายถึงสิ่งที่รูปแบบทำ
การบังคับใช้
อธิบายถึงรายการสถานการณ์ที่สามารถใช้รูปแบบได้
ผู้เข้าร่วมและผลที่ตามมา
ผู้เข้าร่วมรวมถึงชั้นเรียนและวัตถุที่มีส่วนร่วมในรูปแบบการออกแบบพร้อมกับรายการผลที่ตามมาที่เกิดขึ้นกับรูปแบบ
ทำไมต้อง Python
Python เป็นภาษาสคริปต์โอเพ่นซอร์ส มีห้องสมุดที่รองรับรูปแบบการออกแบบที่หลากหลาย ไวยากรณ์ของ python นั้นเข้าใจง่ายและใช้คีย์เวิร์ดภาษาอังกฤษ
Python ให้การสนับสนุนรายการรูปแบบการออกแบบที่ระบุไว้ด้านล่าง รูปแบบการออกแบบเหล่านี้จะถูกนำไปใช้ตลอดบทช่วยสอนนี้ -
- รูปแบบตัวควบคุมมุมมองโมเดล
- รูปแบบ Singleton
- รูปแบบโรงงาน
- รูปแบบตัวสร้าง
- รูปแบบต้นแบบ
- รูปแบบซุ้ม
- รูปแบบคำสั่ง
- รูปแบบอะแดปเตอร์
- รูปแบบต้นแบบ
- รูปแบบมัณฑนากร
- รูปแบบพร็อกซี
- รูปแบบความรับผิดชอบของห่วงโซ่
- รูปแบบผู้สังเกตการณ์
- รูปแบบของรัฐ
- รูปแบบกลยุทธ์
- รูปแบบเทมเพลต
- รูปแบบฟลายเวท
- รูปแบบโรงงานนามธรรม
- รูปแบบเชิงวัตถุ
ประโยชน์ของการใช้รูปแบบการออกแบบ
ต่อไปนี้เป็นประโยชน์ที่แตกต่างกันของรูปแบบการออกแบบ -
รูปแบบช่วยให้นักพัฒนาสามารถเลือกโซลูชันที่ทดลองและทดสอบสำหรับปัญหาที่ระบุได้
รูปแบบการออกแบบทั้งหมดมีความเป็นกลางทางภาษา
รูปแบบช่วยในการสื่อสารและรักษาเอกสารอย่างดี
รวมถึงบันทึกความสำเร็จเพื่อลดความเสี่ยงทางเทคนิคใด ๆ ของโครงการ
รูปแบบการออกแบบมีความยืดหยุ่นสูงในการใช้งานและเข้าใจง่าย
Python เป็นภาษาสคริปต์โอเพ่นซอร์สซึ่งเป็นภาษาระดับสูงตีความโต้ตอบและเชิงวัตถุ ถูกออกแบบมาให้อ่านง่ายมาก ไวยากรณ์ของภาษา Python นั้นเข้าใจง่ายและใช้คีย์เวิร์ดภาษาอังกฤษบ่อยๆ
คุณสมบัติของภาษา Python
ในส่วนนี้เราจะเรียนรู้เกี่ยวกับคุณสมบัติต่างๆของภาษา Python
ตีความ
Python ถูกประมวลผลที่รันไทม์โดยใช้ล่าม ไม่จำเป็นต้องคอมไพล์โปรแกรมก่อนดำเนินการ มันคล้ายกับ PERL และ PHP
เชิงวัตถุ
Python เป็นไปตามสไตล์เชิงวัตถุและรูปแบบการออกแบบ รวมถึงการกำหนดคลาสที่มีคุณสมบัติต่างๆเช่นการห่อหุ้มความหลากหลายและอื่น ๆ อีกมากมาย
แบบพกพา
รหัส Python ที่เขียนในระบบปฏิบัติการ Windows และสามารถใช้ในระบบปฏิบัติการ Mac รหัสสามารถใช้ซ้ำและพกพาได้ตามข้อกำหนด
ง่ายต่อการเขียนโค้ด
ไวยากรณ์ Python นั้นเข้าใจง่ายและเขียนโค้ด นักพัฒนาทุกคนสามารถเข้าใจไวยากรณ์ของ Python ได้ภายในไม่กี่ชั่วโมง Python สามารถอธิบายได้ว่า“ เป็นมิตรกับโปรแกรมเมอร์”
ขยายได้
หากจำเป็นผู้ใช้สามารถเขียนโค้ด Python ในภาษา C ได้เช่นกัน นอกจากนี้ยังสามารถใส่รหัส python ในซอร์สโค้ดในภาษาต่างๆเช่น C ++ สิ่งนี้ทำให้ Python เป็นภาษาที่ขยายได้
จุดสำคัญ
พิจารณาประเด็นสำคัญต่อไปนี้ที่เกี่ยวข้องกับภาษาโปรแกรม Python -
ประกอบด้วยวิธีการเขียนโปรแกรมเชิงฟังก์ชันและโครงสร้างตลอดจนวิธีการเขียนโปรแกรมเชิงวัตถุ
สามารถใช้เป็นภาษาสคริปต์หรือเป็นภาษาโปรแกรม
รวมถึงการเก็บขยะอัตโนมัติ
ประกอบด้วยประเภทข้อมูลไดนามิกระดับสูงและรองรับการตรวจสอบประเภทไดนามิกต่างๆ
Python มีคุณลักษณะของการทำงานร่วมกับ C, C ++ และภาษาเช่น Java
จะดาวน์โหลดภาษา python ในระบบของคุณได้อย่างไร?
หากต้องการดาวน์โหลดภาษา Python ในระบบของคุณให้ไปที่ลิงค์นี้ -
https://www.python.org/downloads/ประกอบด้วยแพ็คเกจสำหรับระบบปฏิบัติการต่างๆเช่น Windows, MacOS และ Linux
เครื่องมือสำคัญใน Python
ในส่วนนี้เราจะเรียนรู้โดยย่อเกี่ยวกับเครื่องมือสำคัญบางอย่างใน Python
Python Strings
การประกาศสตริงพื้นฐานมีดังนี้ -
str = 'Hello World!'
รายการ Python
รายการของ python สามารถประกาศเป็นชนิดข้อมูลผสมโดยคั่นด้วยเครื่องหมายจุลภาคและอยู่ในวงเล็บเหลี่ยม ([])
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
Python Tuples
ทูเพิลเป็นชนิดข้อมูลไดนามิกของ Python ซึ่งประกอบด้วยจำนวนค่าที่คั่นด้วยเครื่องหมายจุลภาค ทูเปิลอยู่ในวงเล็บ
tinytuple = (123, 'john')
พจนานุกรม Python
พจนานุกรม Python คือตารางแฮชประเภทหนึ่ง คีย์พจนานุกรมสามารถเป็นข้อมูลได้เกือบทุกประเภทของ Python ประเภทข้อมูลมักเป็นตัวเลขหรือสตริง
tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}
รูปแบบการออกแบบใน Python เป็นอย่างไร
Python ช่วยในการสร้างรูปแบบการออกแบบโดยใช้พารามิเตอร์ต่อไปนี้ -
- ชื่อรูปแบบ
- Intent
- Aliases
- Motivation
- Problem
- Solution
- Structure
- Participants
- Constraints
- ตัวอย่างรหัส
Model View Controller เป็นรูปแบบการออกแบบที่ใช้กันมากที่สุด นักพัฒนาพบว่าง่ายต่อการนำรูปแบบการออกแบบนี้ไปใช้
ต่อไปนี้เป็นสถาปัตยกรรมพื้นฐานของ Model View Controller -
ตอนนี้ให้เราดูว่าโครงสร้างทำงานอย่างไร
รุ่น
ประกอบด้วยตรรกะของแอปพลิเคชันที่บริสุทธิ์ซึ่งโต้ตอบกับฐานข้อมูล รวมถึงข้อมูลทั้งหมดเพื่อแสดงข้อมูลให้กับผู้ใช้ปลายทาง
ดู
View แสดงถึงไฟล์ HTML ซึ่งโต้ตอบกับผู้ใช้ปลายทาง แสดงข้อมูลของโมเดลให้กับผู้ใช้
ตัวควบคุม
ทำหน้าที่เป็นตัวกลางระหว่างมุมมองและโมเดล จะรับฟังเหตุการณ์ที่เกิดขึ้นจากมุมมองและรูปแบบการสืบค้นสำหรับสิ่งเดียวกัน
รหัส Python
ให้เราพิจารณาวัตถุพื้นฐานที่เรียกว่า "บุคคล" และสร้างรูปแบบการออกแบบ MVC
Model.py
import json
class Person(object):
def __init__(self, first_name = None, last_name = None):
self.first_name = first_name
self.last_name = last_name
#returns Person name, ex: John Doe
def name(self):
return ("%s %s" % (self.first_name,self.last_name))
@classmethod
#returns all people inside db.txt as list of Person objects
def getAll(self):
database = open('db.txt', 'r')
result = []
json_list = json.loads(database.read())
for item in json_list:
item = json.loads(item)
person = Person(item['first_name'], item['last_name'])
result.append(person)
return result
เรียกใช้เมธอดซึ่งดึงข้อมูลทั้งหมดของตารางบุคคลในฐานข้อมูล บันทึกจะแสดงในรูปแบบ JSON
ดู
จะแสดงระเบียนทั้งหมดที่ดึงมาจากแบบจำลอง ดูไม่เคยโต้ตอบกับโมเดล ตัวควบคุมทำงานนี้ (สื่อสารกับโมเดลและมุมมอง)
from model import Person
def showAllView(list):
print 'In our db we have %i users. Here they are:' % len(list)
for item in list:
print item.name()
def startView():
print 'MVC - the simplest example'
print 'Do you want to see everyone in my db?[y/n]'
def endView():
print 'Goodbye!'
ตัวควบคุม
คอนโทรลเลอร์โต้ตอบกับโมเดลผ่านไฟล์ getAll() วิธีการที่ดึงข้อมูลทั้งหมดที่แสดงต่อผู้ใช้ปลายทาง
from model import Person
import view
def showAll():
#gets list of all Person objects
people_in_db = Person.getAll()
#calls view
return view.showAllView(people_in_db)
def start():
view.startView()
input = raw_input()
if input == 'y':
return showAll()
else:
return view.endView()
if __name__ == "__main__":
#running controller function
start()
รูปแบบนี้ จำกัด การสร้างอินสแตนซ์ของคลาสไว้ที่อ็อบเจ็กต์เดียว เป็นรูปแบบการสร้างสรรค์ประเภทหนึ่งและเกี่ยวข้องกับคลาสเดียวเท่านั้นในการสร้างเมธอดและอ็อบเจ็กต์ที่ระบุ
เป็นจุดเข้าถึงทั่วโลกสำหรับอินสแตนซ์ที่สร้างขึ้น
จะใช้คลาสซิงเกิลตันได้อย่างไร?
โปรแกรมต่อไปนี้แสดงให้เห็นถึงการนำคลาส singleton ไปใช้งานซึ่งจะพิมพ์อินสแตนซ์ที่สร้างขึ้นหลาย ๆ ครั้ง
class Singleton:
__instance = None
@staticmethod
def getInstance():
""" Static access method. """
if Singleton.__instance == None:
Singleton()
return Singleton.__instance
def __init__(self):
""" Virtually private constructor. """
if Singleton.__instance != None:
raise Exception("This class is a singleton!")
else:
Singleton.__instance = self
s = Singleton()
print s
s = Singleton.getInstance()
print s
s = Singleton.getInstance()
print s
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
จำนวนอินสแตนซ์ที่สร้างขึ้นเหมือนกันและไม่มีความแตกต่างในออบเจ็กต์ที่แสดงรายการในเอาต์พุต
รูปแบบโรงงานอยู่ภายใต้หมวดหมู่รายการรูปแบบการสร้างสรรค์ เป็นหนึ่งในวิธีที่ดีที่สุดในการสร้างวัตถุ ในรูปแบบโรงงานวัตถุจะถูกสร้างขึ้นโดยไม่เปิดเผยตรรกะกับไคลเอนต์และอ้างถึงวัตถุที่สร้างขึ้นใหม่โดยใช้อินเทอร์เฟซทั่วไป
รูปแบบโรงงานถูกนำไปใช้ใน Python โดยใช้วิธีโรงงาน เมื่อผู้ใช้เรียกใช้เมธอดที่เราส่งผ่านสตริงและค่าส่งคืนเป็นอ็อบเจ็กต์ใหม่ถูกนำไปใช้ผ่านวิธีการโรงงาน ประเภทของออบเจ็กต์ที่ใช้ในวิธีการโรงงานถูกกำหนดโดยสตริงที่ส่งผ่านเมธอด
ในตัวอย่างด้านล่างทุกวิธีรวมออบเจ็กต์เป็นพารามิเตอร์ซึ่งดำเนินการผ่านวิธีการโรงงาน
จะใช้รูปแบบโรงงานได้อย่างไร?
ตอนนี้ให้เราดูวิธีใช้รูปแบบโรงงาน
class Button(object):
html = ""
def get_html(self):
return self.html
class Image(Button):
html = "<img></img>"
class Input(Button):
html = "<input></input>"
class Flash(Button):
html = "<obj></obj>"
class ButtonFactory():
def create_button(self, typ):
targetclass = typ.capitalize()
return globals()[targetclass]()
button_obj = ButtonFactory()
button = ['image', 'input', 'flash']
for b in button:
print button_obj.create_button(b).get_html()
คลาสปุ่มช่วยในการสร้างแท็ก html และเพจ html ที่เกี่ยวข้อง ไคลเอนต์จะไม่สามารถเข้าถึงตรรกะของโค้ดและผลลัพธ์แสดงถึงการสร้างเพจ html
เอาต์พุต
คำอธิบาย
รหัส python มีตรรกะของแท็ก html ซึ่งระบุค่า ผู้ใช้สามารถดูไฟล์ HTML ที่สร้างโดยโค้ด Python
Builder Pattern เป็นรูปแบบการออกแบบที่ไม่เหมือนใครซึ่งช่วยในการสร้างวัตถุที่ซับซ้อนโดยใช้วัตถุธรรมดาและใช้วิธีการอัลกอริทึม รูปแบบการออกแบบนี้อยู่ภายใต้หมวดหมู่ของรูปแบบการสร้างสรรค์ ในรูปแบบการออกแบบนี้คลาส builder จะสร้างอ็อบเจ็กต์สุดท้ายในโพรซีเดอร์ทีละขั้นตอน ตัวสร้างนี้ไม่ขึ้นกับวัตถุอื่น ๆ
ข้อดีของ Builder Pattern
ให้การแยกที่ชัดเจนและชั้นที่ไม่ซ้ำกันระหว่างการสร้างและการแสดงวัตถุที่ระบุซึ่งสร้างโดยคลาส
ให้การควบคุมกระบวนการก่อสร้างของรูปแบบที่สร้างขึ้นได้ดีขึ้น
ทำให้สถานการณ์ที่สมบูรณ์แบบในการเปลี่ยนการแสดงวัตถุภายใน
จะใช้รูปแบบตัวสร้างได้อย่างไร?
ในส่วนนี้เราจะเรียนรู้วิธีใช้รูปแบบตัวสร้าง
class Director:
__builder = None
def setBuilder(self, builder):
self.__builder = builder
def getCar(self):
car = Car()
# First goes the body
body = self.__builder.getBody()
car.setBody(body)
# Then engine
engine = self.__builder.getEngine()
car.setEngine(engine)
# And four wheels
i = 0
while i < 4:
wheel = self.__builder.getWheel()
car.attachWheel(wheel)
i += 1
return car
# The whole product
class Car:
def __init__(self):
self.__wheels = list()
self.__engine = None
self.__body = None
def setBody(self, body):
self.__body = body
def attachWheel(self, wheel):
self.__wheels.append(wheel)
def setEngine(self, engine):
self.__engine = engine
def specification(self):
print "body: %s" % self.__body.shape
print "engine horsepower: %d" % self.__engine.horsepower
print "tire size: %d\'" % self.__wheels[0].size
class Builder:
def getWheel(self): pass
def getEngine(self): pass
def getBody(self): pass
class JeepBuilder(Builder):
def getWheel(self):
wheel = Wheel()
wheel.size = 22
return wheel
def getEngine(self):
engine = Engine()
engine.horsepower = 400
return engine
def getBody(self):
body = Body()
body.shape = "SUV"
return body
# Car parts
class Wheel:
size = None
class Engine:
horsepower = None
class Body:
shape = None
def main():
jeepBuilder = JeepBuilder() # initializing the class
director = Director()
# Build Jeep
print "Jeep"
director.setBuilder(jeepBuilder)
jeep = director.getCar()
jeep.specification()
print ""
if __name__ == "__main__":
main()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
รูปแบบการออกแบบต้นแบบช่วยซ่อนความซับซ้อนของอินสแตนซ์ที่สร้างขึ้นโดยคลาส แนวคิดของออบเจ็กต์ที่มีอยู่จะแตกต่างกับของออบเจ็กต์ใหม่ซึ่งสร้างขึ้นตั้งแต่ต้น
วัตถุที่คัดลอกใหม่อาจมีการเปลี่ยนแปลงคุณสมบัติบางอย่างหากจำเป็น วิธีนี้ช่วยประหยัดเวลาและทรัพยากรที่ต้องใช้ในการพัฒนาผลิตภัณฑ์
จะใช้รูปแบบต้นแบบได้อย่างไร?
ตอนนี้ให้เราดูวิธีใช้รูปแบบต้นแบบ
import copy
class Prototype:
_type = None
_value = None
def clone(self):
pass
def getType(self):
return self._type
def getValue(self):
return self._value
class Type1(Prototype):
def __init__(self, number):
self._type = "Type1"
self._value = number
def clone(self):
return copy.copy(self)
class Type2(Prototype):
""" Concrete prototype. """
def __init__(self, number):
self._type = "Type2"
self._value = number
def clone(self):
return copy.copy(self)
class ObjectFactory:
""" Manages prototypes.
Static factory, that encapsulates prototype
initialization and then allows instatiation
of the classes from these prototypes.
"""
__type1Value1 = None
__type1Value2 = None
__type2Value1 = None
__type2Value2 = None
@staticmethod
def initialize():
ObjectFactory.__type1Value1 = Type1(1)
ObjectFactory.__type1Value2 = Type1(2)
ObjectFactory.__type2Value1 = Type2(1)
ObjectFactory.__type2Value2 = Type2(2)
@staticmethod
def getType1Value1():
return ObjectFactory.__type1Value1.clone()
@staticmethod
def getType1Value2():
return ObjectFactory.__type1Value2.clone()
@staticmethod
def getType2Value1():
return ObjectFactory.__type2Value1.clone()
@staticmethod
def getType2Value2():
return ObjectFactory.__type2Value2.clone()
def main():
ObjectFactory.initialize()
instance = ObjectFactory.getType1Value1()
print "%s: %s" % (instance.getType(), instance.getValue())
instance = ObjectFactory.getType1Value2()
print "%s: %s" % (instance.getType(), instance.getValue())
instance = ObjectFactory.getType2Value1()
print "%s: %s" % (instance.getType(), instance.getValue())
instance = ObjectFactory.getType2Value2()
print "%s: %s" % (instance.getType(), instance.getValue())
if __name__ == "__main__":
main()
เอาต์พุต
โปรแกรมข้างต้นจะสร้างผลลัพธ์ต่อไปนี้ -
ผลลัพธ์จะช่วยในการสร้างวัตถุใหม่ด้วยวัตถุที่มีอยู่และสามารถมองเห็นได้ชัดเจนในผลลัพธ์ที่กล่าวถึงข้างต้น
รูปแบบการออกแบบ Facade จัดเตรียมอินเตอร์เฟสแบบรวมให้กับชุดของอินเทอร์เฟซในระบบย่อย เป็นการกำหนดอินเทอร์เฟซระดับสูงขึ้นที่ระบบย่อยสามารถใช้ได้
คลาสซุ้มรู้ว่าระบบย่อยใดรับผิดชอบการร้องขอ
ออกแบบรูปแบบซุ้มอย่างไร?
ตอนนี้ให้เราดูวิธีการออกแบบรูปแบบซุ้ม
class _IgnitionSystem(object):
@staticmethod
def produce_spark():
return True
class _Engine(object):
def __init__(self):
self.revs_per_minute = 0
def turnon(self):
self.revs_per_minute = 2000
def turnoff(self):
self.revs_per_minute = 0
class _FuelTank(object):
def __init__(self, level=30):
self._level = level
@property
def level(self):
return self._level
@level.setter
def level(self, level):
self._level = level
class _DashBoardLight(object):
def __init__(self, is_on=False):
self._is_on = is_on
def __str__(self):
return self.__class__.__name__
@property
def is_on(self):
return self._is_on
@is_on.setter
def is_on(self, status):
self._is_on = status
def status_check(self):
if self._is_on:
print("{}: ON".format(str(self)))
else:
print("{}: OFF".format(str(self)))
class _HandBrakeLight(_DashBoardLight):
pass
class _FogLampLight(_DashBoardLight):
pass
class _Dashboard(object):
def __init__(self):
self.lights = {"handbreak": _HandBrakeLight(), "fog": _FogLampLight()}
def show(self):
for light in self.lights.values():
light.status_check()
# Facade
class Car(object):
def __init__(self):
self.ignition_system = _IgnitionSystem()
self.engine = _Engine()
self.fuel_tank = _FuelTank()
self.dashboard = _Dashboard()
@property
def km_per_litre(self):
return 17.0
def consume_fuel(self, km):
litres = min(self.fuel_tank.level, km / self.km_per_litre)
self.fuel_tank.level -= litres
def start(self):
print("\nStarting...")
self.dashboard.show()
if self.ignition_system.produce_spark():
self.engine.turnon()
else:
print("Can't start. Faulty ignition system")
def has_enough_fuel(self, km, km_per_litre):
litres_needed = km / km_per_litre
if self.fuel_tank.level > litres_needed:
return True
else:
return False
def drive(self, km = 100):
print("\n")
if self.engine.revs_per_minute > 0:
while self.has_enough_fuel(km, self.km_per_litre):
self.consume_fuel(km)
print("Drove {}km".format(km))
print("{:.2f}l of fuel still left".format(self.fuel_tank.level))
else:
print("Can't drive. The Engine is turned off!")
def park(self):
print("\nParking...")
self.dashboard.lights["handbreak"].is_on = True
self.dashboard.show()
self.engine.turnoff()
def switch_fog_lights(self, status):
print("\nSwitching {} fog lights...".format(status))
boolean = True if status == "ON" else False
self.dashboard.lights["fog"].is_on = boolean
self.dashboard.show()
def fill_up_tank(self):
print("\nFuel tank filled up!")
self.fuel_tank.level = 100
# the main function is the Client
def main():
car = Car()
car.start()
car.drive()
car.switch_fog_lights("ON")
car.switch_fog_lights("OFF")
car.park()
car.fill_up_tank()
car.drive()
car.start()
car.drive()
if __name__ == "__main__":
main()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
โปรแกรมนี้ได้รับการออกแบบโดยใช้สถานการณ์จำลอง มันคือการสตาร์ทเครื่องยนต์ของรถยนต์หรือยานพาหนะขับเคลื่อนใด ๆ หากคุณสังเกตรหัสดังกล่าวจะรวมถึงฟังก์ชันที่เกี่ยวข้องในการขับขี่การจอดรถและการสิ้นเปลืองน้ำมันด้วย
รูปแบบคำสั่งเพิ่มระดับของนามธรรมระหว่างการกระทำและรวมถึงวัตถุซึ่งเรียกการกระทำเหล่านี้
ในรูปแบบการออกแบบนี้ไคลเอ็นต์จะสร้างอ็อบเจ็กต์คำสั่งที่มีรายการคำสั่งที่จะดำเนินการ อ็อบเจ็กต์คำสั่งที่สร้างขึ้นจะใช้อินเทอร์เฟซเฉพาะ
ต่อไปนี้เป็นสถาปัตยกรรมพื้นฐานของรูปแบบคำสั่ง -
จะใช้รูปแบบคำสั่งได้อย่างไร?
ตอนนี้เราจะดูวิธีใช้รูปแบบการออกแบบ
def demo(a,b,c):
print 'a:',a
print 'b:',b
print 'c:',c
class Command:
def __init__(self, cmd, *args):
self._cmd=cmd
self._args=args
def __call__(self, *args):
return apply(self._cmd, self._args+args)
cmd = Command(dir,__builtins__)
print cmd()
cmd = Command(demo,1,2)
cmd(3)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
ผลลัพธ์จะใช้คำสั่งและคำสำคัญทั้งหมดที่แสดงรายการในภาษา Python มันพิมพ์ค่าที่จำเป็นของตัวแปร
รูปแบบอะแดปเตอร์ทำงานเป็นสะพานเชื่อมระหว่างสองอินเทอร์เฟซที่เข้ากันไม่ได้ รูปแบบการออกแบบประเภทนี้อยู่ภายใต้รูปแบบโครงสร้างเนื่องจากรูปแบบนี้รวมความสามารถของสองอินเทอร์เฟซที่เป็นอิสระ
รูปแบบนี้เกี่ยวข้องกับคลาสเดียวซึ่งมีหน้าที่ในการรวมฟังก์ชันของอินเทอร์เฟซที่เป็นอิสระหรือเข้ากันไม่ได้ ตัวอย่างชีวิตจริงอาจเป็นกรณีของเครื่องอ่านการ์ดซึ่งทำหน้าที่เป็นอะแดปเตอร์ระหว่างการ์ดหน่วยความจำและแล็ปท็อป คุณเสียบการ์ดหน่วยความจำเข้ากับเครื่องอ่านการ์ดและเครื่องอ่านการ์ดเข้ากับแล็ปท็อปเพื่อให้สามารถอ่านการ์ดหน่วยความจำผ่านแล็ปท็อปได้
รูปแบบการออกแบบอะแดปเตอร์ช่วยในการทำงานร่วมกัน มันแปลงอินเทอร์เฟซของคลาสเป็นอินเทอร์เฟซอื่นตามความต้องการ รูปแบบรวมถึงการระบุความหลากหลายซึ่งตั้งชื่อหนึ่งชื่อและหลายรูปแบบ พูดสำหรับคลาสรูปร่างที่สามารถใช้ได้ตามข้อกำหนดที่รวบรวม
รูปแบบอะแดปเตอร์มีสองประเภท -
รูปแบบอแดปเตอร์วัตถุ
รูปแบบการออกแบบนี้อาศัยการใช้งานวัตถุ ดังนั้นจึงเรียกว่า Object Adapter Pattern
รูปแบบอะแดปเตอร์คลาส
นี่เป็นอีกทางเลือกหนึ่งในการใช้รูปแบบการออกแบบอะแดปเตอร์ รูปแบบสามารถนำไปใช้โดยใช้การสืบทอดหลายรายการ
วิธีใช้รูปแบบอะแดปเตอร์?
ตอนนี้ให้เราดูวิธีใช้รูปแบบอะแดปเตอร์
class EuropeanSocketInterface:
def voltage(self): pass
def live(self): pass
def neutral(self): pass
def earth(self): pass
# Adaptee
class Socket(EuropeanSocketInterface):
def voltage(self):
return 230
def live(self):
return 1
def neutral(self):
return -1
def earth(self):
return 0
# Target interface
class USASocketInterface:
def voltage(self): pass
def live(self): pass
def neutral(self): pass
# The Adapter
class Adapter(USASocketInterface):
__socket = None
def __init__(self, socket):
self.__socket = socket
def voltage(self):
return 110
def live(self):
return self.__socket.live()
def neutral(self):
return self.__socket.neutral()
# Client
class ElectricKettle:
__power = None
def __init__(self, power):
self.__power = power
def boil(self):
if self.__power.voltage() > 110:
print "Kettle on fire!"
else:
if self.__power.live() == 1 and \
self.__power.neutral() == -1:
print "Coffee time!"
else:
print "No power."
def main():
# Plug in
socket = Socket()
adapter = Adapter(socket)
kettle = ElectricKettle(adapter)
# Make coffee
kettle.boil()
return 0
if __name__ == "__main__":
main()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
โค้ดประกอบด้วยอินเทอร์เฟซของอะแด็ปเตอร์ที่มีพารามิเตอร์และแอตทริบิวต์ต่างๆ ประกอบด้วย Adaptee พร้อมกับอินเทอร์เฟซ Target ที่ใช้แอตทริบิวต์ทั้งหมดและแสดงผลลัพธ์ตามที่มองเห็นได้
รูปแบบ Decorator ช่วยให้ผู้ใช้สามารถเพิ่มฟังก์ชันการทำงานใหม่ให้กับวัตถุที่มีอยู่ได้โดยไม่ต้องเปลี่ยนแปลงโครงสร้าง รูปแบบการออกแบบประเภทนี้อยู่ภายใต้รูปแบบโครงสร้างเนื่องจากรูปแบบนี้ทำหน้าที่เป็นตัวห่อหุ้มคลาสที่มีอยู่
รูปแบบนี้สร้างคลาสมัณฑนากรซึ่งจะปิดคลาสเดิมและมีฟังก์ชันเพิ่มเติมที่ทำให้ลายเซ็นเมธอดคลาสเหมือนเดิม
แรงจูงใจของรูปแบบมัณฑนากรคือการแนบความรับผิดชอบเพิ่มเติมของวัตถุแบบไดนามิก
วิธีใช้รูปแบบการออกแบบมัณฑนากร
โค้ดที่กล่าวถึงด้านล่างเป็นการสาธิตวิธีใช้รูปแบบการออกแบบมัณฑนากรใน Python ภาพประกอบเกี่ยวข้องกับการสาธิตร้านกาแฟในรูปแบบของชั้นเรียน คลาสกาแฟที่สร้างขึ้นเป็นนามธรรมซึ่งหมายความว่าไม่สามารถสร้างอินสแตนซ์ได้
import six
from abc import ABCMeta
@six.add_metaclass(ABCMeta)
class Abstract_Coffee(object):
def get_cost(self):
pass
def get_ingredients(self):
pass
def get_tax(self):
return 0.1*self.get_cost()
class Concrete_Coffee(Abstract_Coffee):
def get_cost(self):
return 1.00
def get_ingredients(self):
return 'coffee'
@six.add_metaclass(ABCMeta)
class Abstract_Coffee_Decorator(Abstract_Coffee):
def __init__(self,decorated_coffee):
self.decorated_coffee = decorated_coffee
def get_cost(self):
return self.decorated_coffee.get_cost()
def get_ingredients(self):
return self.decorated_coffee.get_ingredients()
class Sugar(Abstract_Coffee_Decorator):
def __init__(self,decorated_coffee):
Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
def get_cost(self):
return self.decorated_coffee.get_cost()
def get_ingredients(self):
return self.decorated_coffee.get_ingredients() + ', sugar'
class Milk(Abstract_Coffee_Decorator):
def __init__(self,decorated_coffee):
Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
def get_cost(self):
return self.decorated_coffee.get_cost() + 0.25
def get_ingredients(self):
return self.decorated_coffee.get_ingredients() + ', milk'
class Vanilla(Abstract_Coffee_Decorator):
def __init__(self,decorated_coffee):
Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
def get_cost(self):
return self.decorated_coffee.get_cost() + 0.75
def get_ingredients(self):
return self.decorated_coffee.get_ingredients() + ', vanilla'
การใช้งานระดับนามธรรมของร้านกาแฟนั้นทำด้วยไฟล์แยกต่างหากตามที่กล่าวไว้ด้านล่าง -
import coffeeshop
myCoffee = coffeeshop.Concrete_Coffee()
print('Ingredients: '+myCoffee.get_ingredients()+
'; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
myCoffee = coffeeshop.Milk(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
'; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
myCoffee = coffeeshop.Vanilla(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
'; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
myCoffee = coffeeshop.Sugar(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
'; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
รูปแบบการออกแบบพร็อกซีมีวัตถุใหม่ซึ่งเรียกว่า "พร็อกซี" แทนที่วัตถุที่มีอยู่ซึ่งเรียกว่า "เรื่องจริง" วัตถุพร็อกซีที่สร้างขึ้นจากหัวเรื่องจริงจะต้องอยู่บนอินเทอร์เฟซเดียวกันในลักษณะที่ไคลเอนต์ไม่ควรเข้าใจว่าใช้พร็อกซีแทนวัตถุจริง คำขอที่สร้างโดยไคลเอ็นต์ไปยังพร็อกซีจะส่งผ่านเรื่องจริง
การแสดง UML ของรูปแบบพร็อกซีมีดังนี้ -
จะใช้รูปแบบพร็อกซีได้อย่างไร?
ตอนนี้ให้เราดูวิธีใช้รูปแบบพร็อกซี
class Image:
def __init__( self, filename ):
self._filename = filename
def load_image_from_disk( self ):
print("loading " + self._filename )
def display_image( self ):
print("display " + self._filename)
class Proxy:
def __init__( self, subject ):
self._subject = subject
self._proxystate = None
class ProxyImage( Proxy ):
def display_image( self ):
if self._proxystate == None:
self._subject.load_image_from_disk()
self._proxystate = 1
print("display " + self._subject._filename )
proxy_image1 = ProxyImage ( Image("HiRes_10Mb_Photo1") )
proxy_image2 = ProxyImage ( Image("HiRes_10Mb_Photo2") )
proxy_image1.display_image() # loading necessary
proxy_image1.display_image() # loading unnecessary
proxy_image2.display_image() # loading necessary
proxy_image2.display_image() # loading unnecessary
proxy_image1.display_image() # loading unnecessary
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
การออกแบบรูปแบบพร็อกซีช่วยในการจำลองภาพที่เราสร้างขึ้น ฟังก์ชัน display_image () ช่วยตรวจสอบว่ามีการพิมพ์ค่าในพรอมต์คำสั่งหรือไม่
รูปแบบความรับผิดชอบถูกนำมาใช้เพื่อให้เกิดการเชื่อมต่อแบบหลวม ๆ ในซอฟต์แวร์ที่มีการส่งคำขอที่ระบุจากไคลเอนต์ผ่านห่วงโซ่ของวัตถุที่รวมอยู่ในนั้น ช่วยในการสร้างห่วงโซ่ของวัตถุ คำขอเข้าจากปลายด้านหนึ่งและย้ายจากวัตถุหนึ่งไปยังอีกวัตถุหนึ่ง
รูปแบบนี้อนุญาตให้อ็อบเจ็กต์ส่งคำสั่งโดยไม่ทราบว่าอ็อบเจ็กต์ใดจะจัดการกับคำร้องขอ
จะดำเนินการตามรูปแบบความรับผิดชอบอย่างไร?
ตอนนี้เราจะดูวิธีการนำรูปแบบห่วงโซ่ความรับผิดชอบไปใช้
class ReportFormat(object):
PDF = 0
TEXT = 1
class Report(object):
def __init__(self, format_):
self.title = 'Monthly report'
self.text = ['Things are going', 'really, really well.']
self.format_ = format_
class Handler(object):
def __init__(self):
self.nextHandler = None
def handle(self, request):
self.nextHandler.handle(request)
class PDFHandler(Handler):
def handle(self, request):
if request.format_ == ReportFormat.PDF:
self.output_report(request.title, request.text)
else:
super(PDFHandler, self).handle(request)
def output_report(self, title, text):
print '<html>'
print ' <head>'
print ' <title>%s</title>' % title
print ' </head>'
print ' <body>'
for line in text:
print ' <p>%s' % line
print ' </body>'
print '</html>'
class TextHandler(Handler):
def handle(self, request):
if request.format_ == ReportFormat.TEXT:
self.output_report(request.title, request.text)
else:
super(TextHandler, self).handle(request)
def output_report(self, title, text):
print 5*'*' + title + 5*'*'
for line in text:
print line
class ErrorHandler(Handler):
def handle(self, request):
print "Invalid request"
if __name__ == '__main__':
report = Report(ReportFormat.TEXT)
pdf_handler = PDFHandler()
text_handler = TextHandler()
pdf_handler.nextHandler = text_handler
text_handler.nextHandler = ErrorHandler()
pdf_handler.handle(report)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
รหัสด้านบนสร้างรายงานสำหรับงานรายเดือนซึ่งจะส่งคำสั่งผ่านแต่ละฟังก์ชัน ต้องใช้ตัวจัดการสองตัว - สำหรับ PDF และสำหรับข้อความ พิมพ์ผลลัพธ์เมื่อวัตถุที่ต้องการเรียกใช้แต่ละฟังก์ชัน
ในรูปแบบนี้วัตถุจะแสดงเป็นผู้สังเกตการณ์ที่รอให้เหตุการณ์ทริกเกอร์ ผู้สังเกตการณ์จะยึดติดกับตัวแบบเมื่อเหตุการณ์ที่ระบุเกิดขึ้น เมื่อเกิดเหตุการณ์ขึ้นผู้ถูกทดลองจะบอกผู้สังเกตการณ์ว่าเกิดขึ้นแล้ว
แผนภาพ UML ต่อไปนี้แสดงถึงรูปแบบผู้สังเกตการณ์ -
จะใช้รูปแบบผู้สังเกตการณ์ได้อย่างไร?
ตอนนี้ให้เราดูวิธีใช้รูปแบบผู้สังเกตการณ์
import threading
import time
import pdb
class Downloader(threading.Thread):
def run(self):
print 'downloading'
for i in range(1,5):
self.i = i
time.sleep(2)
print 'unfunf'
return 'hello world'
class Worker(threading.Thread):
def run(self):
for i in range(1,5):
print 'worker running: %i (%i)' % (i, t.i)
time.sleep(1)
t.join()
print 'done'
t = Downloader()
t.start()
time.sleep(1)
t1 = Worker()
t1.start()
t2 = Worker()
t2.start()
t3 = Worker()
t3.start()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
โค้ดด้านบนอธิบายขั้นตอนการดาวน์โหลดผลลัพธ์เฉพาะ ตามตรรกะของรูปแบบผู้สังเกตการณ์วัตถุทุกชิ้นจะถือว่าเป็นผู้สังเกตการณ์ พิมพ์ผลลัพธ์เมื่อเหตุการณ์ถูกทริกเกอร์
จัดเตรียมโมดูลสำหรับเครื่องสถานะซึ่งนำไปใช้โดยใช้คลาสย่อยที่ได้มาจากคลาสเครื่องสถานะที่ระบุ วิธีการนี้ไม่ขึ้นกับสถานะและทำให้เกิดการเปลี่ยนแปลงที่ประกาศโดยใช้มัณฑนากร
จะใช้รูปแบบของรัฐอย่างไร?
การดำเนินการขั้นพื้นฐานของรูปแบบสถานะดังแสดงด้านล่าง -
class ComputerState(object):
name = "state"
allowed = []
def switch(self, state):
""" Switch to new state """
if state.name in self.allowed:
print 'Current:',self,' => switched to new state',state.name
self.__class__ = state
else:
print 'Current:',self,' => switching to',state.name,'not possible.'
def __str__(self):
return self.name
class Off(ComputerState):
name = "off"
allowed = ['on']
class On(ComputerState):
""" State of being powered on and working """
name = "on"
allowed = ['off','suspend','hibernate']
class Suspend(ComputerState):
""" State of being in suspended mode after switched on """
name = "suspend"
allowed = ['on']
class Hibernate(ComputerState):
""" State of being in hibernation after powered on """
name = "hibernate"
allowed = ['on']
class Computer(object):
""" A class representing a computer """
def __init__(self, model='HP'):
self.model = model
# State of the computer - default is off.
self.state = Off()
def change(self, state):
""" Change state """
self.state.switch(state)
if __name__ == "__main__":
comp = Computer()
comp.change(On)
comp.change(Off)
comp.change(On)
comp.change(Suspend)
comp.change(Hibernate)
comp.change(On)
comp.change(Off)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
รูปแบบกลยุทธ์เป็นรูปแบบพฤติกรรมประเภทหนึ่ง เป้าหมายหลักของรูปแบบกลยุทธ์คือเพื่อให้ลูกค้าสามารถเลือกอัลกอริทึมหรือขั้นตอนต่างๆเพื่อทำงานที่ระบุให้เสร็จสิ้น อัลกอริทึมที่แตกต่างกันสามารถสลับเข้าและออกได้โดยไม่มีความยุ่งยากใด ๆ สำหรับงานที่กล่าวถึง
รูปแบบนี้สามารถใช้เพื่อปรับปรุงความยืดหยุ่นเมื่อมีการเข้าถึงทรัพยากรภายนอก
จะดำเนินการตามรูปแบบกลยุทธ์อย่างไร?
โปรแกรมที่แสดงด้านล่างช่วยในการนำรูปแบบกลยุทธ์ไปใช้
import types
class StrategyExample:
def __init__(self, func = None):
self.name = 'Strategy Example 0'
if func is not None:
self.execute = types.MethodType(func, self)
def execute(self):
print(self.name)
def execute_replacement1(self):
print(self.name + 'from execute 1')
def execute_replacement2(self):
print(self.name + 'from execute 2')
if __name__ == '__main__':
strat0 = StrategyExample()
strat1 = StrategyExample(execute_replacement1)
strat1.name = 'Strategy Example 1'
strat2 = StrategyExample(execute_replacement2)
strat2.name = 'Strategy Example 2'
strat0.execute()
strat1.execute()
strat2.execute()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
มีรายการกลยุทธ์จากฟังก์ชันซึ่งดำเนินการผลลัพธ์ จุดเน้นหลักของรูปแบบพฤติกรรมนี้คือพฤติกรรม
รูปแบบเทมเพลตกำหนดอัลกอริทึมพื้นฐานในคลาสฐานโดยใช้การดำเนินการแบบนามธรรมโดยที่คลาสย่อยจะแทนที่พฤติกรรมที่เป็นรูปธรรม รูปแบบเทมเพลตจะเก็บโครงร่างของอัลกอริทึมไว้ในวิธีการแยกต่างหาก วิธีนี้เรียกว่าวิธีเทมเพลต
ต่อไปนี้เป็นคุณสมบัติต่างๆของรูปแบบเทมเพลต -
เป็นการกำหนดโครงกระดูกของอัลกอริทึมในการดำเนินการ
ประกอบด้วยคลาสย่อยซึ่งกำหนดขั้นตอนบางขั้นตอนของอัลกอริทึมใหม่
class MakeMeal:
def prepare(self): pass
def cook(self): pass
def eat(self): pass
def go(self):
self.prepare()
self.cook()
self.eat()
class MakePizza(MakeMeal):
def prepare(self):
print "Prepare Pizza"
def cook(self):
print "Cook Pizza"
def eat(self):
print "Eat Pizza"
class MakeTea(MakeMeal):
def prepare(self):
print "Prepare Tea"
def cook(self):
print "Cook Tea"
def eat(self):
print "Eat Tea"
makePizza = MakePizza()
makePizza.go()
print 25*"+"
makeTea = MakeTea()
makeTea.go()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
รหัสนี้สร้างเทมเพลตเพื่อเตรียมอาหาร ที่นี่แต่ละพารามิเตอร์แสดงถึงคุณลักษณะในการสร้างส่วนหนึ่งของอาหารเช่นชาพิซซ่า ฯลฯ
ผลลัพธ์แสดงถึงการแสดงภาพของแอตทริบิวต์
แพทเทอร์บรุ่นฟลายเวทอยู่ภายใต้หมวดรูปแบบการออกแบบโครงสร้าง มีวิธีลดจำนวนวัตถุ ประกอบด้วยคุณสมบัติต่างๆที่ช่วยในการปรับปรุงโครงสร้างแอปพลิเคชัน คุณสมบัติที่สำคัญที่สุดของวัตถุฟลายเวทคือไม่เปลี่ยนรูป ซึ่งหมายความว่าไม่สามารถแก้ไขได้เมื่อสร้างแล้ว รูปแบบใช้ HashMap เพื่อจัดเก็บวัตถุอ้างอิง
จะใช้รูปแบบฟลายเวทได้อย่างไร?
โปรแกรมต่อไปนี้ช่วยในการปรับใช้รูปแบบฟลายเวท -
class ComplexGenetics(object):
def __init__(self):
pass
def genes(self, gene_code):
return "ComplexPatter[%s]TooHugeinSize" % (gene_code)
class Families(object):
family = {}
def __new__(cls, name, family_id):
try:
id = cls.family[family_id]
except KeyError:
id = object.__new__(cls)
cls.family[family_id] = id
return id
def set_genetic_info(self, genetic_info):
cg = ComplexGenetics()
self.genetic_info = cg.genes(genetic_info)
def get_genetic_info(self):
return (self.genetic_info)
def test():
data = (('a', 1, 'ATAG'), ('a', 2, 'AAGT'), ('b', 1, 'ATAG'))
family_objects = []
for i in data:
obj = Families(i[0], i[1])
obj.set_genetic_info(i[2])
family_objects.append(obj)
for i in family_objects:
print "id = " + str(id(i))
print i.get_genetic_info()
print "similar id's says that they are same objects "
if __name__ == '__main__':
test()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
รูปแบบโรงงานนามธรรมเรียกอีกอย่างว่าโรงงานของโรงงาน รูปแบบการออกแบบนี้อยู่ภายใต้หมวดหมู่รูปแบบการออกแบบสร้างสรรค์ เป็นหนึ่งในวิธีที่ดีที่สุดในการสร้างวัตถุ
ประกอบด้วยอินเทอร์เฟซซึ่งรับผิดชอบในการสร้างวัตถุที่เกี่ยวข้องกับ Factory
วิธีการใช้รูปแบบโรงงานนามธรรม?
โปรแกรมต่อไปนี้ช่วยในการนำรูปแบบโรงงานนามธรรมไปใช้
class Window:
__toolkit = ""
__purpose = ""
def __init__(self, toolkit, purpose):
self.__toolkit = toolkit
self.__purpose = purpose
def getToolkit(self):
return self.__toolkit
def getType(self):
return self.__purpose
class GtkToolboxWindow(Window):
def __init__(self):
Window.__init__(self, "Gtk", "ToolboxWindow")
class GtkLayersWindow(Window):
def __init__(self):
Window.__init__(self, "Gtk", "LayersWindow")
class GtkMainWindow(Window):
def __init__(self):
Window.__init__(self, "Gtk", "MainWindow")
class QtToolboxWindow(Window):
def __init__(self):
Window.__init__(self, "Qt", "ToolboxWindow")
class QtLayersWindow(Window):
def __init__(self):
Window.__init__(self, "Qt", "LayersWindow")
class QtMainWindow(Window):
def __init__(self):
Window.__init__(self, "Qt", "MainWindow")
# Abstract factory class
class UIFactory:
def getToolboxWindow(self): pass
def getLayersWindow(self): pass
def getMainWindow(self): pass
class GtkUIFactory(UIFactory):
def getToolboxWindow(self):
return GtkToolboxWindow()
def getLayersWindow(self):
return GtkLayersWindow()
def getMainWindow(self):
return GtkMainWindow()
class QtUIFactory(UIFactory):
def getToolboxWindow(self):
return QtToolboxWindow()
def getLayersWindow(self):
return QtLayersWindow()
def getMainWindow(self):
return QtMainWindow()
if __name__ == "__main__":
gnome = True
kde = not gnome
if gnome:
ui = GtkUIFactory()
elif kde:
ui = QtUIFactory()
toolbox = ui.getToolboxWindow()
layers = ui.getLayersWindow()
main = ui.getMainWindow()
print "%s:%s" % (toolbox.getToolkit(), toolbox.getType())
print "%s:%s" % (layers.getToolkit(), layers.getType())
print "%s:%s" % (main.getToolkit(), main.getType())
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
ในโปรแกรมข้างต้นโรงงานนามธรรมจะสร้างวัตถุสำหรับแต่ละหน้าต่าง เรียกใช้แต่ละวิธีซึ่งดำเนินการผลลัพธ์ตามที่คาดไว้
รูปแบบเชิงวัตถุเป็นรูปแบบที่ใช้กันมากที่สุด รูปแบบนี้สามารถพบได้ในเกือบทุกภาษาโปรแกรม
จะใช้รูปแบบเชิงวัตถุได้อย่างไร?
ตอนนี้ให้เราดูวิธีใช้รูปแบบเชิงวัตถุ
class Parrot:
# class attribute
species = "bird"
# instance attribute
def __init__(self, name, age):
self.name = name
self.age = age
# instantiate the Parrot class
blu = Parrot("Blu", 10)
woo = Parrot("Woo", 15)
# access the class attributes
print("Blu is a {}".format(blu.__class__.species))
print("Woo is also a {}".format(woo.__class__.species))
# access the instance attributes
print("{} is {} years old".format( blu.name, blu.age))
print("{} is {} years old".format( woo.name, woo.age))
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้
คำอธิบาย
รหัสประกอบด้วยแอตทริบิวต์คลาสและแอตทริบิวต์อินสแตนซ์ซึ่งพิมพ์ตามความต้องการของเอาต์พุต มีคุณสมบัติต่างๆที่เป็นส่วนหนึ่งของรูปแบบเชิงวัตถุ คุณสมบัติจะอธิบายในบทถัดไป
ในบทนี้เราจะเน้นที่รูปแบบโดยใช้แนวคิดเชิงวัตถุและการนำไปใช้ใน Python เมื่อเราออกแบบโปรแกรมของเรารอบ ๆ บล็อคของคำสั่งซึ่งจัดการกับข้อมูลรอบ ๆ ฟังก์ชันจะเรียกว่าการเขียนโปรแกรมเชิงโพรซีเดอร์ ในการเขียนโปรแกรมเชิงวัตถุมีสองอินสแตนซ์หลักที่เรียกว่าคลาสและอ็อบเจ็กต์
วิธีการใช้คลาสและตัวแปรออบเจ็กต์?
การใช้คลาสและตัวแปรออบเจ็กต์มีดังนี้ -
class Robot:
population = 0
def __init__(self, name):
self.name = name
print("(Initializing {})".format(self.name))
Robot.population += 1
def die(self):
print("{} is being destroyed!".format(self.name))
Robot.population -= 1
if Robot.population == 0:
print("{} was the last one.".format(self.name))
else:
print("There are still {:d} robots working.".format(
Robot.population))
def say_hi(self):
print("Greetings, my masters call me {}.".format(self.name))
@classmethod
def how_many(cls):
print("We have {:d} robots.".format(cls.population))
droid1 = Robot("R2-D2")
droid1.say_hi()
Robot.how_many()
droid2 = Robot("C-3PO")
droid2.say_hi()
Robot.how_many()
print("\nRobots can do some work here.\n")
print("Robots have finished their work. So let's destroy them.")
droid1.die()
droid2.die()
Robot.how_many()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
ภาพประกอบนี้ช่วยแสดงให้เห็นถึงลักษณะของคลาสและตัวแปรออบเจ็กต์
"ประชากร" เป็นของคลาส "Robot" ดังนั้นจึงเรียกว่าตัวแปรคลาสหรือวัตถุ
ในที่นี้เราอ้างถึงตัวแปรระดับประชากรว่า Robot.population ไม่ใช่ self.population
รูปแบบการออกแบบตัววนซ้ำอยู่ภายใต้หมวดหมู่รูปแบบการออกแบบเชิงพฤติกรรม นักพัฒนาพบรูปแบบตัววนซ้ำในเกือบทุกภาษาโปรแกรม รูปแบบนี้ใช้ในลักษณะที่ช่วยในการเข้าถึงองค์ประกอบของคอลเลกชัน (คลาส) ตามลำดับโดยไม่เข้าใจการออกแบบเลเยอร์ที่อยู่เบื้องหลัง
จะใช้รูปแบบตัววนซ้ำได้อย่างไร?
ตอนนี้เราจะดูวิธีใช้รูปแบบตัววนซ้ำ
import time
def fib():
a, b = 0, 1
while True:
yield b
a, b = b, a + b
g = fib()
try:
for e in g:
print(e)
time.sleep(1)
except KeyboardInterrupt:
print("Calculation stopped")
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
หากคุณเน้นที่รูปแบบซีรีส์ฟีโบนักชีจะถูกพิมพ์ด้วยรูปแบบตัววนซ้ำ ในการยุติผู้ใช้อย่างมีผลบังคับใช้เอาต์พุตต่อไปนี้จะถูกพิมพ์ -
คำอธิบาย
รหัสหลามนี้เป็นไปตามรูปแบบตัววนซ้ำ ที่นี่ตัวดำเนินการส่วนเพิ่มจะใช้เพื่อเริ่มการนับ การนับจะสิ้นสุดลงเมื่อผู้ใช้ยุติลงอย่างมีผลบังคับ
พจนานุกรมคือโครงสร้างข้อมูลซึ่งรวมถึงการผสมค่าคีย์ สิ่งเหล่านี้ใช้กันอย่างแพร่หลายแทน JSON - JavaScript Object Notation พจนานุกรมใช้สำหรับการเขียนโปรแกรม API (Application Programming Interface) พจนานุกรมจะจับคู่ชุดของวัตถุกับชุดของวัตถุอื่น พจนานุกรมไม่แน่นอน ซึ่งหมายความว่าสามารถเปลี่ยนแปลงได้ตามและเมื่อจำเป็นตามข้อกำหนด
จะใช้พจนานุกรมใน Python ได้อย่างไร?
โปรแกรมต่อไปนี้แสดงการใช้งานพื้นฐานของพจนานุกรมใน Python ตั้งแต่การสร้างไปจนถึงการนำไปใช้งาน
# Create a new dictionary
d = dict() # or d = {}
# Add a key - value pairs to dictionary
d['xyz'] = 123
d['abc'] = 345
# print the whole dictionary
print(d)
# print only the keys
print(d.keys())
# print only values
print(d.values())
# iterate over dictionary
for i in d :
print("%s %d" %(i, d[i]))
# another method of iteration
for index, value in enumerate(d):
print (index, value , d[value])
# check if key exist 23. Python Data Structure –print('xyz' in d)
# delete the key-value pair
del d['xyz']
# check again
print("xyz" in d)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
Note −มีข้อบกพร่องที่เกี่ยวข้องกับการนำพจนานุกรมไปใช้ใน Python
ข้อเสียเปรียบ
พจนานุกรมไม่สนับสนุนการดำเนินการตามลำดับของชนิดข้อมูลลำดับเช่นสตริงสิ่งที่เพิ่มขึ้นและรายการ สิ่งเหล่านี้เป็นของประเภทการแมปในตัว
โครงสร้างข้อมูล Lists เป็นประเภทข้อมูลอเนกประสงค์ใน Python ซึ่งสามารถเขียนเป็นรายการของค่าที่คั่นด้วยเครื่องหมายจุลภาคระหว่างวงเล็บเหลี่ยม
ไวยากรณ์
นี่คือไวยากรณ์พื้นฐานสำหรับโครงสร้าง -
List_name = [ elements ];
หากคุณสังเกตไวยากรณ์จะถูกประกาศเหมือนอาร์เรย์โดยมีข้อแตกต่างเพียงประการเดียวที่รายการสามารถรวมองค์ประกอบที่มีประเภทข้อมูลต่างกันได้ อาร์เรย์ประกอบด้วยองค์ประกอบของประเภทข้อมูลเดียวกัน รายการสามารถประกอบด้วยสตริงจำนวนเต็มและอ็อบเจ็กต์รวมกัน รายการสามารถใช้สำหรับการใช้งานสแต็กและคิว
รายการไม่แน่นอน สิ่งเหล่านี้สามารถเปลี่ยนแปลงได้ตามต้องการ
วิธีการใช้งานรายการ?
โปรแกรมต่อไปนี้แสดงการใช้งานรายการ -
my_list = ['p','r','o','b','e']
# Output: p
print(my_list[0])
# Output: o
print(my_list[2])
# Output: e
print(my_list[4])
# Error! Only integer can be used for indexing
# my_list[4.0]
# Nested List
n_list = ["Happy", [2,0,1,5]]
# Nested indexing
# Output: a
print(n_list[0][1])
# Output: 5
print(n_list[1][3])
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
ฟังก์ชันในตัวของรายการ Python มีดังต่อไปนี้ -
Append()- เพิ่มองค์ประกอบที่ท้ายรายการ
Extend()- เพิ่มองค์ประกอบของรายการในรายการอื่น
Insert()- มันแทรกรายการลงในดัชนีที่กำหนด
Remove()- มันจะลบองค์ประกอบออกจากรายการที่ระบุ
Reverse()- มันย้อนกลับองค์ประกอบในรายการ
sort() - ช่วยจัดเรียงองค์ประกอบตามลำดับเวลา
ชุดสามารถกำหนดเป็นคอลเล็กชันที่ไม่เรียงลำดับซึ่งสามารถทำซ้ำได้เปลี่ยนแปลงได้และไม่มีการรวมองค์ประกอบที่ซ้ำกันไว้ในนั้น ใน Python set class คือสัญกรณ์ของเซตทางคณิตศาสตร์ ข้อได้เปรียบหลักของการใช้ชุดคือมีวิธีการที่เหมาะสมที่สุดสำหรับการตรวจสอบองค์ประกอบเฉพาะ
Python มีหมวดหมู่แยกต่างหากที่เรียกว่าชุดแช่แข็ง ชุดเหล่านี้เป็นวัตถุที่ไม่เปลี่ยนรูปซึ่งสนับสนุนเฉพาะเมธอดและตัวดำเนินการที่ให้ผลลัพธ์ที่ต้องการเท่านั้น
วิธีการใช้งานชุด?
โปรแกรมต่อไปนี้ช่วยในการใช้งานชุด -
# Set in Python
# Creating two sets
set1 = set()
set2 = set()
# Adding elements to set1
for i in range(1, 6):
set1.add(i)
# Adding elements to set2
for i in range(3, 8):
set2.add(i)
print("Set1 = ", set1)
print("Set2 = ", set2)
print("\n")
# Union of set1 and set2
set3 = set1 | set2# set1.union(set2)
print("Union of Set1 & Set2: Set3 = ", set3)
# Intersection of set1 and set2
set4 = set1 & set2# set1.intersection(set2)
print("Intersection of Set1 & Set2: Set4 = ", set4)
print("\n")
# Checking relation between set3 and set4
if set3 > set4: # set3.issuperset(set4)
print("Set3 is superset of Set4")
elif set3 < set4: # set3.issubset(set4)
print("Set3 is subset of Set4")
else : # set3 == set4
print("Set3 is same as Set4")
# displaying relation between set4 and set3
if set4 < set3: # set4.issubset(set3)
print("Set4 is subset of Set3")
print("\n")
# difference between set3 and set4
set5 = set3 - set4
print("Elements in Set3 and not in Set4: Set5 = ", set5)
print("\n")
# checkv if set4 and set5 are disjoint sets
if set4.isdisjoint(set5):
print("Set4 and Set5 have nothing in common\n")
# Removing all the values of set5
set5.clear()
print("After applying clear on sets Set5: ")
print("Set5 = ", set5)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
ชุดแช่แข็งสามารถแสดงได้โดยใช้โปรแกรมต่อไปนี้ -
normal_set = set(["a", "b","c"])
# Adding an element to normal set is fine
normal_set.add("d")
print("Normal Set")
print(normal_set)
# A frozen set
frozen_set = frozenset(["e", "f", "g"])
print("Frozen Set")
print(frozen_set)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
Queue คือชุดของออบเจ็กต์ซึ่งกำหนดโครงสร้างข้อมูลอย่างง่ายตามขั้นตอน FIFO (Fast In Fast Out) และ LIFO (Last In First Out) การดำเนินการแทรกและลบเรียกว่าenqueue และ dequeue การดำเนินงาน
คิวไม่อนุญาตให้เข้าถึงวัตถุที่มีโดยสุ่ม
จะใช้ขั้นตอน FIFO ได้อย่างไร?
โปรแกรมต่อไปนี้ช่วยในการใช้ FIFO -
import Queue
q = Queue.Queue()
#put items at the end of the queue
for x in range(4):
q.put("item-" + str(x))
#remove items from the head of the queue
while not q.empty():
print q.get()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
จะดำเนินการตามขั้นตอน LIFO ได้อย่างไร?
โปรแกรมต่อไปนี้ช่วยในการดำเนินการตามขั้นตอน LIFO -
import Queue
q = Queue.LifoQueue()
#add items at the head of the queue
for x in range(4):
q.put("item-" + str(x))
#remove items from the head of the queue
while not q.empty():
print q.get()
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
Priority Queue คืออะไร
ลำดับความสำคัญคิวเป็นโครงสร้างข้อมูลคอนเทนเนอร์ที่จัดการชุดของระเบียนด้วยคีย์ที่สั่งซื้อเพื่อให้สามารถเข้าถึงระเบียนได้อย่างรวดเร็วด้วยคีย์ที่เล็กที่สุดหรือใหญ่ที่สุดในโครงสร้างข้อมูลที่ระบุ
จะใช้ลำดับความสำคัญได้อย่างไร?
การดำเนินการตามลำดับความสำคัญมีดังนี้ -
import Queue
class Task(object):
def __init__(self, priority, name):
self.priority = priority
self.name = name
def __cmp__(self, other):
return cmp(self.priority, other.priority)
q = Queue.PriorityQueue()
q.put( Task(100, 'a not agent task') )
q.put( Task(5, 'a highly agent task') )
q.put( Task(10, 'an important task') )
while not q.empty():
cur_task = q.get()
print 'process task:', cur_task.name
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
การจัดลำดับสตริงเป็นกระบวนการเขียนสถานะของอ็อบเจ็กต์ลงในไบต์สตรีม ใน python ไลบรารี "pickle" ใช้สำหรับเปิดใช้งานการทำให้เป็นอนุกรม โมดูลนี้มีอัลกอริทึมที่มีประสิทธิภาพสำหรับการทำให้เป็นอนุกรมและการแยกอนุกรมโครงสร้างวัตถุ Python “ Pickling” คือกระบวนการแปลงลำดับชั้นของวัตถุ Python ให้เป็นไบต์สตรีมและ“ การไม่หยิบ” คือกระบวนการย้อนกลับ
การสาธิตโมดูลการดองมีดังนี้ -
import pickle
#Here's an example dict
grades = { 'Alice': 89, 'Bob': 72, 'Charles': 87 }
#Use dumps to convert the object to a serialized string
serial_grades = pickle.dumps( grades )
print(serial_grades)
#Use loads to de-serialize an object
received_grades = pickle.loads( serial_grades )
print(received_grades)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
ภาวะพร้อมกันมักถูกเข้าใจผิดว่าเป็นความเท่าเทียมกัน ภาวะพร้อมกันหมายถึงการตั้งเวลาให้โค้ดที่เป็นอิสระดำเนินการอย่างเป็นระบบ บทนี้มุ่งเน้นไปที่การดำเนินการพร้อมกันสำหรับระบบปฏิบัติการโดยใช้ Python
โปรแกรมต่อไปนี้ช่วยในการดำเนินการพร้อมกันสำหรับระบบปฏิบัติการ -
import os
import time
import threading
import multiprocessing
NUM_WORKERS = 4
def only_sleep():
print("PID: %s, Process Name: %s, Thread Name: %s" % (
os.getpid(),
multiprocessing.current_process().name,
threading.current_thread().name)
)
time.sleep(1)
def crunch_numbers():
print("PID: %s, Process Name: %s, Thread Name: %s" % (
os.getpid(),
multiprocessing.current_process().name,
threading.current_thread().name)
)
x = 0
while x < 10000000:
x += 1
for _ in range(NUM_WORKERS):
only_sleep()
end_time = time.time()
print("Serial time=", end_time - start_time)
# Run tasks using threads
start_time = time.time()
threads = [threading.Thread(target=only_sleep) for _ in range(NUM_WORKERS)]
[thread.start() for thread in threads]
[thread.join() for thread in threads]
end_time = time.time()
print("Threads time=", end_time - start_time)
# Run tasks using processes
start_time = time.time()
processes = [multiprocessing.Process(target=only_sleep()) for _ in range(NUM_WORKERS)]
[process.start() for process in processes]
[process.join() for process in processes]
end_time = time.time()
print("Parallel time=", end_time - start_time)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
คำอธิบาย
“ มัลติโพรเซสซิง” เป็นแพ็คเกจที่คล้ายกับโมดูลเธรด แพคเกจนี้รองรับการทำงานพร้อมกันภายในและระยะไกล เนื่องจากโมดูลนี้โปรแกรมเมอร์ได้รับประโยชน์ในการใช้กระบวนการหลายอย่างในระบบที่กำหนด
รูปแบบการต่อต้านเป็นไปตามกลยุทธ์ในการต่อต้านรูปแบบการออกแบบที่กำหนดไว้ล่วงหน้า กลยุทธ์นี้รวมถึงแนวทางทั่วไปในการแก้ไขปัญหาทั่วไปซึ่งสามารถทำให้เป็นทางการได้และโดยทั่วไปถือได้ว่าเป็นแนวทางปฏิบัติในการพัฒนาที่ดี โดยปกติรูปแบบการต่อต้านจะตรงกันข้ามและไม่เป็นที่ต้องการ รูปแบบการต่อต้านคือรูปแบบบางอย่างที่ใช้ในการพัฒนาซอฟต์แวร์ซึ่งถือเป็นการเขียนโปรแกรมที่ไม่ดี
คุณสมบัติที่สำคัญของการต่อต้านรูปแบบ
ตอนนี้ให้เราดูคุณสมบัติที่สำคัญบางประการของรูปแบบการต่อต้าน
ความถูกต้อง
รูปแบบเหล่านี้ทำลายรหัสของคุณอย่างแท้จริงและทำให้คุณทำสิ่งผิดพลาด ต่อไปนี้เป็นภาพประกอบง่ายๆของเรื่องนี้ -
class Rectangle(object):
def __init__(self, width, height):
self._width = width
self._height = height
r = Rectangle(5, 6)
# direct access of protected member
print("Width: {:d}".format(r._width))
การบำรุงรักษา
โปรแกรมกล่าวว่าสามารถบำรุงรักษาได้หากเข้าใจง่ายและปรับเปลี่ยนตามความต้องการ การนำเข้าโมดูลถือได้ว่าเป็นตัวอย่างของการบำรุงรักษา
import math
x = math.ceil(y)
# or
import multiprocessing as mp
pool = mp.pool(8)
ตัวอย่างการต่อต้านรูปแบบ
ตัวอย่างต่อไปนี้ช่วยในการสาธิตรูปแบบการต่อต้าน -
#Bad
def filter_for_foo(l):
r = [e for e in l if e.find("foo") != -1]
if not check_some_critical_condition(r):
return None
return r
res = filter_for_foo(["bar","foo","faz"])
if res is not None:
#continue processing
pass
#Good
def filter_for_foo(l):
r = [e for e in l if e.find("foo") != -1]
if not check_some_critical_condition(r):
raise SomeException("critical condition unmet!")
return r
try:
res = filter_for_foo(["bar","foo","faz"])
#continue processing
except SomeException:
i = 0
while i < 10:
do_something()
#we forget to increment i
คำอธิบาย
ตัวอย่างรวมถึงการสาธิตมาตรฐานที่ดีและไม่ดีสำหรับการสร้างฟังก์ชันใน Python
การจัดการข้อยกเว้นยังเป็นเกณฑ์หลักของรูปแบบการออกแบบ ข้อยกเว้นคือข้อผิดพลาดที่เกิดขึ้นระหว่างการทำงานของโปรแกรม เมื่อมีข้อผิดพลาดเกิดขึ้นสิ่งสำคัญคือต้องสร้างข้อยกเว้น สิ่งนี้ช่วยในการยับยั้งโปรแกรมขัดข้อง
เหตุใดจึงต้องใช้ข้อยกเว้น
ข้อยกเว้นเป็นวิธีที่สะดวกในการจัดการข้อผิดพลาดและเงื่อนไขพิเศษในโปรแกรม เมื่อผู้ใช้คิดว่ารหัสที่ระบุสามารถสร้างข้อผิดพลาดได้สิ่งสำคัญคือต้องใช้การจัดการข้อยกเว้น
ตัวอย่าง - หารด้วยศูนย์
import sys
randomList = ['a', 0, 2]
for entry in randomList:
try:
print("The entry is", entry)
r = 1/int(entry)
break
except:
print("Oops!",sys.exc_info()[0],"occured.")
print("Next entry.")
print()
print("The reciprocal of",entry,"is",r)
เอาต์พุต
โปรแกรมข้างต้นสร้างผลลัพธ์ต่อไปนี้ -
การเพิ่มข้อยกเว้น
ในการเขียนโปรแกรม Python โดยเฉพาะจะมีการเพิ่มข้อยกเว้นเมื่อเกิดข้อผิดพลาดของรหัสที่เกี่ยวข้องในขณะทำงาน สิ่งนี้สามารถเพิ่มขึ้นอย่างมีประสิทธิภาพโดยใช้“raise” คำสำคัญ.
ไวยากรณ์
raise KeyboardInterrupt
Traceback (most recent call last):
...
KeyboardInterrupt