一、什麼是設計模式
每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的解決方案的核心。這樣你就能一次又一次地使用該方案而不必做重複勞動。” 每一個設計模式系統地命名、解釋和評價了物件導向系統中一個重要的和重複出現的設計。 GoF(Gang of Four) 設計模式四個基本要素:模式名稱、問題、解決方案、效果
二、設計模式七大原則
1、開放封閉原則:一個軟體實體如類,模組和函式應該對擴充套件是開放的,對修改是關閉的。即軟體實體應儘量在不修改原有程式碼的情況下進行擴充套件(裝飾器)
2、里氏替換原則:重寫父類裡面的方法,邏輯可能不一樣,但是返回的結果引數啥的要一樣(所有引用基類的地方必須能透明的使用其子類的物件)
3、依賴倒置原則:高層模組不應該依賴低層模組,二者都應該依賴其抽象,要針對介面程式設計,而不是針對實現程式設計。(介面類)
4、介面隔離原則:使用多個專門的介面,而不使用單一的總介面,即客戶端不應該依賴那些它不需要實現的介面
5、迪米特法則:一個軟體實體應當儘可能少的與其他實體發生相互作用
6、單一職責原則:一個類只負責一項職責(不要存在多於一個導致類變更的原因,即一個類只負責一項職責)
7、合同複用原則:多用組合少用繼承
一個類重用另一個類的程式碼有兩種方式
複製程式碼
繼承
組合
a、下面來說一下介面隔離原則
介面隔離原則
#假如說現在有這樣的動物類
from abc import abstractmethod,ABCMeta #藉助abc模組來實現介面
#介面類就是為了提供標準,約束後面的子類
# class Animal(metaclass=ABCMeta):
# @abstractmethod
# def walk(self):
# pass
#
# @abstractmethod
# def fly(self):
# pass
#
# @abstractmethod
# def swim(self):
# pass
#
# class Frog(Animal):
# '''像是這樣定義一個青蛙類,由於介面類的方法都要被實現,而青蛙只會走,沒不要要實現其他的方法
# 動物不同會的功能也會不同,所以這時候我們就可以選擇用介面隔離原則
# '''
# def walk(self):
# print('青蛙會走')
#
# obj = Frog()
# obj.walk() #會報錯
# =====================改進-=================
class AnimalOnLand(metaclass=ABCMeta):
'''在陸地上的動物'''
@abstractmethod
def walk(self):
pass
class AnimalInSky(metaclass=ABCMeta):
'''飛行動物'''
@abstractmethod
def fly(self):
pass
class AnimalInWater(metaclass=ABCMeta):
'''在水裡的動物'''
@abstractmethod
def swim(self):
pass
class Tiger(AnimalOnLand):
def walk(self):
print('老虎在地上')
class Frog(AnimalOnLand,AnimalInWater):
def swim(self):
print('青蛙會遊')
def walk(self):
print('會跳')
obj = Tiger()
obj.walk()
obj = Frog()
obj.walk()
obj.swim()
複製程式碼
b、繼承和組合
# 合同複用原則:多用組合少用繼承
class A:
def test(self):
return '你好啊'
class B(A): #繼承
def test(self):
return 123
class C:
def __init__(self):
self.a = A() #組合
self.a.test()
def test(self):
return 789
print(B().test())
print(C().a)
print(C().a.test())
print(C().test())
複製程式碼
三、設計模式分類
建立型模式:
簡單工廠模式
工廠方法模式
抽象工廠模式
建立者模式
原型模式
單例模式
總結建立型模式:
依賴於繼承的建立型模式:工廠方法模式
依賴於組合的建立型模式:抽象工廠模式,建立者模式
行為型模式:
直譯器模式
責任鏈模式
命令模式
迭代器模式
中介者模式
備忘錄模式
觀察者模式
狀態模式
策略模式
訪問者模式
模板方法模式
結構性模式:
介面卡模式
橋模式
組合模式
裝飾模式
外觀模式
享元模式
代理模式
四、簡單工廠模式
1、內容
不直接向客戶端暴露物件建立的實現細節,而是通過一個工廠類來負責建立產品類的例項。
2、角色
工廠角色(Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)
3、優點
隱藏了物件建立的實現細節
客戶端不需要修改程式碼
4、缺點
違反了單一職責原則,將建立邏輯集中到一個工廠類中
當新增新產品時,需要修改工廠類程式碼,違反了開放封閉原則
5、使用場景
系統要獨立於產品的建立與組合時
強調一系列相關的產品物件的設計以便進行聯合使用時
提供一個產品類庫,想隱藏產品的具體實現時
6、程式碼示例
原始的
from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self):
pass
class Alipay(Payment):
def __init__(self,money):
self.money = money
def pay(self):
print('支付寶支付了%s元'%self.money)
class Whatpay(Payment):
def __init__(self, money):
self.money = money
def pay(self):
print('微信支付了%s元' % self.money)
obj = Alipay(100)
obj.pay()
obj2 = Whatpay(200)
obj2.pay()
複製程式碼
簡單工廠
from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class Alipay(Payment):
def pay(self, money):
print('支付寶支付了%s元'%money)
class Applepay(Payment):
def pay(self, money):
print('微信支付了%s元' %money)
class Yuebao(Payment):
def pay(self,money):
print('餘額寶支付了%s元' %money)
class PaymentFactory:
'''工廠類:封裝了物件建立的細節'''
def create_payment(self,method):
if method =='alipay':
return Alipay()
elif method =='applepay':
return Applepay()
elif method =='yuebao':
return Yuebao()
else:
return NameError(method)
factory = PaymentFactory()
alipay=factory.create_payment('yuebao')
alipay.pay(100)
複製程式碼
五、工廠方法模式
1、內容
定義一個用於建立物件的介面(工廠介面),讓子類決定例項化哪一個產品類
2、角色
抽象工廠角色(Creator)
具體工廠角色(Concrere Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)
工廠方法模式相比簡單工廠模式將每個具體產品都對應一個具體工廠
3、優點
每個具體產品都對應一個具體工廠類,不需要修改工廠類程式碼
隱藏了物件建立的實現細節
4、缺點
每增加一個具體產品類,就必須增加一個相應的具體工廠類
5、使用場景
需要生產多種、大量複雜物件的時候
需要降低耦合度的時候
當系統的產品種類需要經常擴充套件的時候
6、程式碼示例
from abc import ABCMeta,abstractmethod
class PaymentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class Alipay(Payment):
def pay(self, money):
print('支付寶支付了%s元'%money)
class Applepay(Payment):
def pay(self, money):
print('微信支付了%s元' %money)
class AlipayFactory(PaymentFactory):
def create_payment(self):
return Alipay()
class AppleFactory(PaymentFactory):
def create_payment(self):
return Applepay()
apple = AppleFactory()
apple.create_payment().pay(100)
alipay = AlipayFactory()
alipay.create_payment().pay(300)
#輸出
# 微信支付了100元
# 支付寶支付了300元
複製程式碼
六、抽象工廠模式
1、內容
定義一個工廠類介面,讓工廠子類來建立一系列相關或相互依賴的物件
例:生產一部手機,需要手機殼、CPU、作業系統三類物件進行組裝,其中每類物件都有不同的種類。對每個具體工廠,分別生產一部手機所需要的三個物件。
2、角色
抽象工廠角色(Creator)
具體工廠角色(Concrete Creator)
抽象產品角色(Product)
具體產品角色(Concrete Product)
客戶端(Client)
相比工廠方法模式,抽象工廠模式中的每個具體工廠都產生一套產品
3、優點
將客戶端與類的具體實現相分離
每個工廠建立了一個完整的產品系列,使得易於交換產品系列
有利於產品的一致性(即產品之間的約束關係)
4、缺點
難以支援新種類的(抽象)產品
5、使用場景
系統要獨立於產品的建立與組合時
強調一系列相關的產品物件的設計以便進行聯合使用時
提供一個產品類庫,想隱藏產品的具體實現時
6、程式碼示例
from abc import abstractmethod,ABCMeta
#==============抽象產品============
class PhoneShell(metaclass=ABCMeta):
'''手機殼'''
@abstractmethod
def show_shell(self):
pass
class CPU(metaclass=ABCMeta):
'''CPU'''
@abstractmethod
def show_cpu(self):
pass
class OS(metaclass=ABCMeta):
'''作業系統'''
@abstractmethod
def show_os(self):
pass
# ===============抽象工廠==============
class PhoneFactory(metaclass=ABCMeta):
@abstractmethod
def make_shell(self):
'''製作手機殼'''
pass
@abstractmethod
def make_cpu(self):
'''製作cpu'''
pass
@abstractmethod
def make_os(self):
'''製作手機殼'''
pass
# =================具體產品==============
class SmallShell(PhoneShell):
def show_shell(self):
print('普通手機小手機殼')
class BigShell(PhoneShell):
def show_shell(self):
print('普通手機大手機殼')
class AppleShell(PhoneShell):
def show_shell(self):
print('蘋果手機殼')
class YingTeerCPU(CPU):
def show_cpu(self):
print('英特爾cpu')
class MediaCPU(CPU):
def show_cpu(self):
print('聯發科cpu')
class AppleCPU(CPU):
def show_cpu(self):
print('蘋果cpu')
class Android(OS):
def show_os(self):
print('Android系統')
class IOS(OS):
def show_os(self):
print('ios系統')
# ==============具體工廠================
class MiFactory(PhoneFactory):
def make_shell(self):
return SmallShell()
def make_cpu(self):
return AppleCPU()
def make_os(self):
return Android()
class HuaWeiactory(PhoneFactory):
def make_shell(self):
return BigShell()
def make_cpu(self):
return YingTeerCPU()
def make_os(self):
return Android()
# ===============使用===============
class Phone:
def __init__(self,cpu,os,shell):
self.cpu = cpu
self.os = os
self.shell = shell
def show_info(self):
print('手機資訊')
self.cpu.show_cpu()
self.os.show_os()
self.shell.show_shell()
def make_phone(factory):
cpu = factory.make_cpu()
os = factory.make_os()
shell = factory.make_shell()
return Phone(cpu,os,shell)
p1 = make_phone(HuaWeiactory())
p1.show_info()
p2 = make_phone(MiFactory())
p2.show_info()
複製程式碼