一、Python策略模式介紹
Python策略模式(Strategy Pattern)是一種軟件設(shè)計模式,用于通過將算法封裝為獨立的對象,而使得它們可以在運行時動態(tài)地相互替換。該模式使得算法的變化獨立于使用它們的客戶端,從而達到代碼的可擴展性、靈活性和可維護性。
功能:
1.將不同算法進行抽象和封裝,使得它們可以互相替換,從而增強程序的可擴展性。
2.將算法的變化獨立于客戶端,使得客戶端代碼不需要修改即可使用不同的算法。
3.提高程序的可讀性和可維護性。
優(yōu)點:
1.代碼可擴展性和靈活性好,能夠適應(yīng)不同的需求。
2.降低模塊之間的耦合度,提高代碼的可維護性和可讀性。
3.具有良好的可擴展性,可以動態(tài)地增加、刪除或替換算法。
缺點:
1.會增加一定的復(fù)雜度,需要額外的類定義。
2.可能會導(dǎo)致系統(tǒng)中出現(xiàn)較多的類,增加系統(tǒng)的復(fù)雜度。
3.需要客戶端了解不同策略的差異,才能選擇合適的策略。
應(yīng)用場景:
1.需要在運行時根據(jù)不同情況選擇不同算法的場景。
2.需要封裝業(yè)務(wù)邏輯的場景。
3.需要對同一種算法進行多次修改的場景。
使用方式:
1.抽象出一個策略接口,定義策略的方法。
2.將不同的算法分別封裝為具體的策略類,并實現(xiàn)策略接口的方法。
3.創(chuàng)建一個策略上下文類,負責(zé)調(diào)用不同的策略,根據(jù)不同的需求選擇合適的策略。
在應(yīng)用程序開發(fā)中的應(yīng)用:
1.實現(xiàn)排序算法,將排序邏輯抽象出來,將不同的排序算法封裝為不同的策略,然后在實現(xiàn)排序的過程中,動態(tài)地選擇不同的排序算法。
2.實現(xiàn)搜索算法,將搜索算法封裝為不同的策略,然后在實現(xiàn)搜索的過程中,動態(tài)地選擇不同的搜索算法。
二、策略模式使用
工作原理:
1.抽象策略類:定義了一個公共接口,用于所有策略類的實現(xiàn)。
2.具體策略類:具體實現(xiàn)了策略接口的方法。
3.策略上下文類:負責(zé)調(diào)用具體策略類的實例,根據(jù)用戶的需求選擇相應(yīng)的策略進行調(diào)用。
示例一:實現(xiàn)不同促銷活動
假設(shè)有一個電商平臺,需要實現(xiàn)多種促銷活動來吸引用戶購買商品。不同的促銷活動有不同的算法,例如:滿減、折扣、贈品等。這種情況下,可以使用Python策略模式來實現(xiàn)。
首先,定義一個促銷策略接口PromotionStrategy
,定義促銷活動的方法do_promotion
:
然后,定義具體的促銷策略類,例如:滿減、折扣、贈品等。這里以滿減和折扣為例:
接下來,定義促銷上下文類PromotionContext
,負責(zé)調(diào)用不同的策略:
最后,可以在客戶端代碼中動態(tài)地選擇不同的促銷策略:
# 定義促銷策略接口
class PromotionStrategy():
# 定義促銷活動
def do_promotion(self, price):
pass
# 定義具體促銷策略
class ReductionPromotion(PromotionStrategy):# 滿減
def do_promotion(self, price):
if price >= 200:
return price -50
return price
class DiscountPromotion(PromotionStrategy): # 折扣
def do_promotion(self, price):
return price * 0.8
# 定義上下文類,負責(zé)調(diào)用不同的促銷策略
class PromotionContext():
def __init__(self, promotion_strategy:PromotionStrategy):
self._promotion_strategy = promotion_strategy
def execute_promotion_strategy(self, price):
return self._promotion_strategy.do_promotion(price)
# 動態(tài)選擇不同促銷策略
promotion_type = "Reduction"
promotion_type = "Discount"
if promotion_type == "Reduction":
promotion_strategy = ReductionPromotion()
elif promotion_type == "Discount":
promotion_strategy = DiscountPromotion()
promotion_context = PromotionContext(promotion_strategy)
final_price = promotion_context.execute_promotion_strategy(100)
print(final_price)
promotion_type = "Reduction"
# promotion_type = "Discount"
if promotion_type == "Reduction":
promotion_strategy = ReductionPromotion()
elif promotion_type == "Discount":
promotion_strategy = DiscountPromotion()
promotion_context = PromotionContext(promotion_strategy)
final_price = promotion_context.execute_promotion_strategy(200)
print(final_price)
運行結(jié)果:
?80.0
150
上述代碼中,客戶端代碼通過promotion_type
參數(shù)來選擇不同的促銷策略。然后將選擇的策略傳遞給PromotionContext
類,由它來負責(zé)調(diào)用相應(yīng)的促銷策略。最終獲得商品的最終價格final_price
。如果需要增加或刪除促銷活動,只需增加或刪除相應(yīng)的促銷策略類即可,不需要修改客戶端代碼。
示例二:實現(xiàn)不同搜索算法
假設(shè)我們要實現(xiàn)一個搜索引擎,支持多種搜索算法,例如二分查找、線性查找、哈希查找等。為了實現(xiàn)這個功能,我們可以使用策略模式,將不同的搜索算法實現(xiàn)抽象成不同的類,然后在運行時動態(tài)地將它們傳遞到搜索引擎中。具體的實現(xiàn)如下:
# 定義算法類的抽象基類
class SearchAlgorithm():
def search(self, array, target):
pass
# 定義算法:二分法
class BinarySearch(SearchAlgorithm):
def search(self, array, target):
left, right = 0,len(array) - 1 # 初始化二分法查找的左右邊界,此處0, 9。 相當(dāng)于:left=0, right=len(array)-1
while left <= right:
mid = (left + right) // 2
if array[mid] == target:
return mid # 返回查找結(jié)果
elif array[mid] < target:
left = mid + 1
else:
right = mid -1
return -1
# 定義算法:線性查找
class LineSearch(SearchAlgorithm):
def search(self, array, target):
for i in range(len(array)):
if array[i] == target:
return i
return -1
# 定義搜索引擎
class SearchEngine():
def __init__(self, search_algorithm):
self.search_algorithm = search_algorithm
def set_search_algorithm(self,search_algorithm):
self.search_algorithm = search_algorithm
def search(self,array, target):
index = self.search_algorithm.search(array, target) # 調(diào)用具體的搜索方法
if index != -1:
print(f"Found {target} at index {index}")
else:
print(f"{target} not found in the array.")
# 測試代碼
array = [1,2,3,4,5,6,7,8,9,10]
target = 5
binary_search = BinarySearch()
line_search = LineSearch()
search_engine = SearchEngine(binary_search)
search_engine.search(array, target)
search_engine = SearchEngine(line_search)
search_engine.search(array, target)
運行結(jié)果:
Found 5 at index 4
Found 5 at index 4
在上面的例子中,我們定義了一個SearchAlgorithm
類,它是所有搜索算法類的抽象基類。然后,我們定義了兩個具體的搜索算法類BinarySearch
和LinearSearch
,它們分別實現(xiàn)了二分查找和線性查找算法。最后,我們定義了一個SearchEngine
類,它接收一個具體的搜索算法類,并將其存儲在search_algorithm
屬性中。SearchEngine
類還提供了search
方法,用于執(zhí)行搜索操作。
在測試代碼中,我們首先創(chuàng)建了一個BinarySearch
對象,并用它來創(chuàng)建一個SearchEngine
對象。然后,我們調(diào)用search
方法執(zhí)行搜索操作,結(jié)果顯示目標(biāo)值5被找到了。接著,我們將search_algorithm
屬性設(shè)置為LinearSearch
對象,并再次調(diào)用search
方法,這次結(jié)果顯示目標(biāo)值5同樣被找到了。
通過使用策略模式,我們可以在運行時根據(jù)需要切換搜索算法,而不需要修改搜索引擎的實現(xiàn)代碼。這樣就使得程序更加靈活和易于維護。
left, right = 0, len(array) - 1
這行代碼用于初始化二分查找的左右邊界。在列表中查找某個元素時,我們通常要在列表中的一段區(qū)間內(nèi)進行查找。一開始,這個區(qū)間通常是整個列表。那么,左右邊界要怎么確定呢?
對于有序列表,我們很容易想到的是將整個列表均勻地劃分成兩半,然后查看中間位置的元素與目標(biāo)元素的大小關(guān)系。如果中間位置的元素等于目標(biāo)元素,就返回對應(yīng)的索引;如果中間位置的元素小于目標(biāo)元素,就在右半邊繼續(xù)查找;如果中間位置的元素大于目標(biāo)元素,就在左半邊繼續(xù)查找。這個過程就是二分查找。
而對于二分查找算法,我們需要用left
和right
兩個變量來表示當(dāng)前查找區(qū)間的左右邊界。一開始,整個列表就是我們要查找的區(qū)間,所以left
的初始值為0,right
的初始值為列表長度減1。這樣,在每次查找時,我們就可以根據(jù)left
和right
的值來確定當(dāng)前查找區(qū)間的范圍。
定義類時帶括號和不帶括號區(qū)別
在Python中,定義類時可以帶括號,也可以不帶括號。
語法格式為:
class className:
# some code here
# 或者
class className():
# some code here
帶括號和不帶括號的區(qū)別在于繼承的方式不同。在Python 2.x版本中,帶括號和不帶括號的定義方式有區(qū)別,帶括號的類定義方式是舊式類,不帶括號的類定義方式是新式類。而在Python 3.x版本中,帶括號和不帶括號定義方式?jīng)]有區(qū)別。
新式類和舊式類的主要區(qū)別在于繼承方式不同。在舊式類中,如果沒有顯式地指定一個特定的父類,那么Python會默認繼承由內(nèi)置類型object
派生出的類;而在新式類中,如果沒有顯式地指定一個特定的父類,那么Python會默認繼承內(nèi)置類型object
。
因此,如果需要在Python 2.x版本中使用新式類,建議在定義類時使用帶括號的方式。在Python 3.x版本中,則可以使用帶括號或不帶括號的方式定義類,兩種方式等效。
默認繼承內(nèi)置類型object
在Python中,如果沒有顯式地指定一個特定的父類,那么Python會默認繼承內(nèi)置類型object
。下面是一個例子:
class MyClass:
pass
print(type(MyClass)) # <class 'type'>
print(type(MyClass())) # <class '__main__.MyClass'>
在上面的例子中,我們定義了一個空的類MyClass
,并沒有指定父類。我們可以通過調(diào)用type()
函數(shù)來查看MyClass
的類型以及用MyClass()
創(chuàng)建的實例的類型,都是type
和__main__.MyClass
,這說明Python默認繼承了內(nèi)置類型object
。
如果我們明確指定了一個父類,那么Python就會直接繼承這個父類,例如:文章來源:http://www.zghlxwxcb.cn/news/detail-608784.html
class MyBaseClass:
pass
class MyClass(MyBaseClass):
pass
print(type(MyClass)) # <class 'type'>
print(type(MyClass())) # <class '__main__.MyClass'>
在上面的例子中,我們定義了一個空的父類MyBaseClass
,并讓MyClass
類繼承自MyBaseClass
。此時,MyClass
的類型仍然是type
,但是MyClass()
創(chuàng)建的實例的類型變?yōu)榱?code>__main__.MyClass,這說明MyClass
類已經(jīng)從MyBaseClass
類繼承了一些屬性和方法。文章來源地址http://www.zghlxwxcb.cn/news/detail-608784.html
到了這里,關(guān)于Python策略模式介紹、使用方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!