為什么將這兩個(gè)模式一起說(shuō)呢默蚌,因?yàn)樗鼈兘?jīng)常是同時(shí)出現(xiàn)(框架中)或者使用(自己寫的代碼).
直接上代碼祝沸,然后再說(shuō)其中的區(qū)別。
工廠模式(這里主要以抽象工廠為例)
意圖:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口塔橡,而無(wú)需指定它們具體的類裆馒。
書內(nèi)完整:是一種為訪問(wèn)類提供一個(gè)創(chuàng)建一組相關(guān)或相互依賴對(duì)象的接口,且訪問(wèn)類無(wú)須指定所要產(chǎn)品的具體類就能得到同族的不同等級(jí)的產(chǎn)品的模式結(jié)構(gòu)凡桥。
主要解決:主要解決接口選擇的問(wèn)題蟀伸。何時(shí)使用:系統(tǒng)的產(chǎn)品有多于一個(gè)的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。
如何解決:在一個(gè)產(chǎn)品族里面啊掏,定義多個(gè)產(chǎn)品蠢络。
關(guān)鍵代碼:在一個(gè)工廠里聚合多個(gè)同類產(chǎn)品。
應(yīng)用實(shí)例:工作了迟蜜,為了參加一些聚會(huì)刹孔,肯定有兩套或多套衣服吧,比如說(shuō)有商務(wù)裝(成套娜睛,一系列具體產(chǎn)品)髓霞、時(shí)尚裝(成套,一系列具體產(chǎn)品)畦戒,甚至對(duì)于一個(gè)家庭來(lái)說(shuō)方库,可能有商務(wù)女裝、商務(wù)男裝障斋、時(shí)尚女裝纵潦、時(shí)尚男裝,這些也都是成套的垃环,即一系列具體產(chǎn)品邀层。假設(shè)一種情況(現(xiàn)實(shí)中是不存在的,要不然遂庄,沒(méi)法進(jìn)入共產(chǎn)主義了被济,但有利于說(shuō)明抽象工廠模式),在您的家中涧团,某一個(gè)衣柜(具體工廠)只能存放某一種這樣的衣服(成套,一系列具體產(chǎn)品)经磅,每次拿這種成套的衣服時(shí)也自然要從這個(gè)衣柜中取出了泌绣。用 OOP 的思想去理解,所有的衣柜(具體工廠)都是衣柜類的(抽象工廠)某一個(gè)预厌,而每一件成套的衣服又包括具體的上衣(某一具體產(chǎn)品)阿迈,褲子(某一具體產(chǎn)品),這些具體的上衣其實(shí)也都是上衣(抽象產(chǎn)品)轧叽,具體的褲子也都是褲子(另一個(gè)抽象產(chǎn)品)苗沧。
優(yōu)點(diǎn):
抽象工廠模式除了具有工廠方法模式的優(yōu)點(diǎn)外,其他主要優(yōu)點(diǎn)如下炭晒。
1.可以在類的內(nèi)部對(duì)產(chǎn)品族中相關(guān)聯(lián)的多等級(jí)產(chǎn)品共同管理待逞,而不必專門引入多個(gè)新的類來(lái)進(jìn)行管理。
2.當(dāng)需要產(chǎn)品族時(shí)网严,抽象工廠可以保證客戶端始終只使用同一個(gè)產(chǎn)品的產(chǎn)品組识樱。
3.抽象工廠增強(qiáng)了程序的可擴(kuò)展性,當(dāng)增加一個(gè)新的產(chǎn)品族時(shí),不需要修改原代碼怜庸,滿足開閉原則当犯。
4.當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí),它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象割疾。
缺點(diǎn):
1.產(chǎn)品族擴(kuò)展非常困難嚎卫,要增加一個(gè)系列的某一產(chǎn)品,既要在抽象的 Creator 里加代碼宏榕,又要在具體的里面加代碼拓诸。
2.當(dāng)產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品時(shí),所有的工廠類都需要進(jìn)行修改担扑。增加了系統(tǒng)的抽象性和理解難度恰响。
使用場(chǎng)景: 1、QQ 換皮膚涌献,一整套一起換胚宦。 2、生成不同操作系統(tǒng)的程序燕垃。注意事項(xiàng):產(chǎn)品族難擴(kuò)展枢劝,產(chǎn)品等級(jí)易擴(kuò)展。
先看基本目錄哈
1.先創(chuàng)建Shape和Color工廠
Color.java
public interface Color {
/**
* 填充
*/
void fill();
}
Shape.jaba
public interface Shape {
/**
* 繪畫
*/
void draw();
}
2.然后我們color和shape都拿其中一個(gè)來(lái)舉例卜壕,其他效仿哈
Red.java
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
3.再創(chuàng)建工廠創(chuàng)造器
FactoryProducer
public class FactoryProducer {
public static AbstractFactoryDemo getFactory(String choice) {
if (choice.equalsIgnoreCase("SHAPE")) return new ShapeFactory();
if (choice.equalsIgnoreCase("COLOR")) return new ColorFactory();
return null;
}
}
4.最后測(cè)試一下(自己創(chuàng)一個(gè)類)
public static void main(String[] args) {
//獲取圖形工廠
AbstractFactoryDemo shape = FactoryProducer.getFactory("SHAPE");
//通過(guò)圖形工廠 獲取圖形中的3個(gè)或多個(gè)圖形
Shape circle = shape.getShape("CIRCLE");
circle.draw();
Shape rectangle = shape.getShape("RECTANGLE");
rectangle.draw();
Shape square = shape.getShape("SQUARE");
square.draw();
//獲取顏色工廠
AbstractFactoryDemo color = FactoryProducer.getFactory("COLOR");
//通過(guò)顏色工廠 獲取顏色中的3個(gè)或多個(gè)顏色
Color red = color.getColor("RED");
red.fill();
Color yellow = color.getColor("YELLOW");
yellow.fill();
Color blue = color.getColor("BLUE");
blue.fill();
}
輸出結(jié)果:
策略模式
意圖:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái), 并且使它們可相互替換您旁。
書內(nèi)完整:該模式定義了一系列算法,并將每個(gè)算法封裝起來(lái)轴捎,使它們可以相互替換鹤盒,且算法的變化不會(huì)影響使用算法的客戶。策略模式屬于對(duì)象行為模式侦副,它通過(guò)對(duì)算法進(jìn)行封裝侦锯,把使用算法的責(zé)任和算法的實(shí)現(xiàn)分割開來(lái),并委派給不同的對(duì)象對(duì)這些算法進(jìn)行管理秦驯。
主要解決:在有多種算法相似的情況下尺碰,使用 if...else 所帶來(lái)的復(fù)雜和難以維護(hù)。何時(shí)使用:一個(gè)系統(tǒng)有許多許多類译隘,而區(qū)分它們的只是他們直接的行為亲桥。
如何解決:將這些算法封裝成一個(gè)一個(gè)的類,任意地替換固耘。
關(guān)鍵代碼:實(shí)現(xiàn)同一個(gè)接口题篷。
應(yīng)用實(shí)例: 1、JAVA AWT 中的 LayoutManager 2厅目、旅行的出游方式悼凑,選擇騎自行車偿枕、坐汽車,每一種旅行方式都是一個(gè)策略户辫。3渐夸、spring中使用。 4渔欢、jdk中使用墓塌。 5、電商的多促銷模式奥额。 6苫幢、多種不同的支付方式。
優(yōu)點(diǎn):
1.算法可以自由切換垫挨。 1.2韩肝、避免使用多重條件判斷。 1.3九榔、擴(kuò)展性良好哀峻。
2.多重條件語(yǔ)句不易維護(hù),而使用策略模式可以避免使用多重條件語(yǔ)句哲泊,如 if...else 語(yǔ)句剩蟀、switch...case 語(yǔ)句。
3.策略模式提供了一系列的可供重用的算法族切威,恰當(dāng)使用繼承可以把算法族的公共代碼轉(zhuǎn)移到父類里面育特,從而避免重復(fù)的代碼。
4.策略模式可以提供相同行為的不同實(shí)現(xiàn)先朦,客戶可以根據(jù)不同時(shí)間或空間要求選擇不同的缰冤。
5.策略模式提供了對(duì)開閉原則的完美支持,可以在不修改原代碼的情況下喳魏,靈活增加新算法棉浸。
6.策略模式把算法的使用放到環(huán)境類中,而算法的實(shí)現(xiàn)移到具體策略類中截酷,實(shí)現(xiàn)了二者的分離。
缺點(diǎn): 1.策略類會(huì)增多乾戏。 2.所有策略類都需要對(duì)外暴露迂苛。
3.客戶端必須理解所有策略算法的區(qū)別,以便適時(shí)選擇恰當(dāng)?shù)乃惴悺?br> 4.策略模式造成很多的策略類鼓择,增加維護(hù)難度三幻。使用場(chǎng)景: 1、如果在一個(gè)系統(tǒng)里面有許多類呐能,它們之間的區(qū)別僅在于它們的行為念搬,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為抑堡。 2、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種朗徊。 3首妖、如果一個(gè)對(duì)象有很多的行為,如果不用恰當(dāng)?shù)哪J揭遥@些行為就只好使用多重的條件選擇語(yǔ)句來(lái)實(shí)現(xiàn)有缆。
注意事項(xiàng):如果一個(gè)系統(tǒng)的策略多于四個(gè),就需要考慮使用混合模式温亲,解決策略類膨脹的問(wèn)題棚壁。
大致的目錄跟工廠模式一樣差不多創(chuàng)建即可
CrabCookingStrategy 、CrabCooking(抽象策略接口)栈虚、(具體策略)1.BraisedCrabs 2.SteamedCrabs袖外、Kitchen(環(huán)境)
為了方便看我直接放一個(gè)類了
public class CrabCookingStrategy {
private Kitchen kitchen; //廚房
private CrabCooking qzx, hsx; //大閘蟹加工者
CrabCookingStrategy() {
System.out.println("策略模式在大閘蟹做菜中的應(yīng)用");
List arrayList= new ArrayList<>();
//環(huán)境
kitchen = new Kitchen();
// 清蒸
qzx = new SteamedCrabs();
// 紅燒
hsx = new BraisedCrabs();
//修改策略
itemStateChanged(qzx);
System.out.println(kitchen.getStrategy());
itemStateChanged(hsx);
System.out.println(kitchen.getStrategy());
itemStateChanged(qzx);
System.out.println(kitchen.getStrategy());
}
public void itemStateChanged(Object action) {
if (action == qzx) {
kitchen.setStrategy(qzx);
kitchen.cookingMethod(); //清蒸
} else if (action == hsx) {
kitchen.setStrategy(hsx);
kitchen.cookingMethod(); //紅燒
}
}
public static void main(String[] args) {
new CrabCookingStrategy();
}
}
//抽象策略類:大閘蟹加工類
interface CrabCooking {
public void cookingMethod(); //做菜方法
}
//具體策略類:清蒸大閘蟹
class SteamedCrabs implements CrabCooking {
private static final long serialVersionUID = 1L;
public void cookingMethod() {
System.out.println("清蒸大閘蟹");
}
}
//具體策略類:紅燒大閘蟹
class BraisedCrabs implements CrabCooking {
private static final long serialVersionUID = 1L;
public void cookingMethod() {
System.out.println("紅燒大閘蟹");
}
}
//環(huán)境類:廚房
class Kitchen {
//抽象策略
private CrabCooking strategy;
public void setStrategy(CrabCooking strategy) {
this.strategy = strategy;
}
public CrabCooking getStrategy() {
return strategy;
}
public void cookingMethod() {
System.out.println("做菜");
strategy.cookingMethod(); //做菜
}
}