日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

策略模式、观察者模式、代理模式、装饰模式 应用场景和实现

發布時間:2023/12/19 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 策略模式、观察者模式、代理模式、装饰模式 应用场景和实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有個大神寫的很好:

參考:設計模式學習筆記(四:策略模式)

參考:設計模式學習筆記(二:觀察者模式)

參考:設計模式學習筆記-代理模式

參考:設計模式--裝飾者模式與代理模式(重要)

參考:設計模式——代理模式與裝飾模式的異同?(重要)

參考:設計模式之裝飾模式

參考:java模式—裝飾者模式

參考:修飾者模式(裝飾者模式,Decoration)

一、策略模式:
?(1)解決場景:
某個功能有多個方案可以實現,要達到某個目的,需要根據具體的實際情況,選擇合適的方法,
?(2)如何實現:
分為兩個層次
 (a) 環境類
 環境類負責接收用戶的請求,并根據實際情況把相應的請求委托給一組策略類中的一個;

 (b) 一組策略類
  一組封裝了具體的實現類的算法,并負責具體的計算過程

(3)關鍵類圖:

?

?首先定義策略類的接口:?

public interface GameStrategy {public void goldCoin();}

其次 實現一組策略類:

public class normalStrategy implements GameStrategy { @Override public void goldCoin() { // System.out.println("普通玩家沒有折扣"); } } public class advancedStrategy implements GameStrategy {@Overridepublic void goldCoin() {// TODO Auto-generated method stubSystem.out.println("高級會員9折優惠");} }

環境類的實現:

public class Context { //持有一個Strategy的引用 private GameStrategy mGameStrategy; // 構造函數 public Context(GameStrategy strategy) { this.mGameStrategy = strategy; } public void setStrategy(GameStrategy strategy) { this.mGameStrategy = strategy; } public void goldCoin() { this.mGameStrategy.goldCoin(); } }

最后根據不同的情況進行調用:

public class main { public static void main(String[] args) { //普通玩家策略 Context context = new Context(new normalStrategy()); context.goldCoin(); //高級玩家策略 context.setStrategy(new advancedStrategy()); context.goldCoin(); } }

?二、觀察者模式

(1)解決場景:
  (a) 對一個對象狀態的更新,需要其他對象同步更新
  (b) 對象僅需要將自己的更新通知給其他對象而不需要知道其他對象的細節
觀察者模式,又稱為發布訂閱模式,它的特點:
  (a) subject 和 observer之間是松耦合的,各自獨立實現,
  (b) subject在發送廣播通知的時候,不需要指定具體的observer,observer可以自行決定是否要訂閱
  (c) 遵循常用設計原則:高內聚,低耦合
(2)如何實現:

關鍵類圖:

?定義觀察者接口:?

public interface Observer {void update(String message,String name);}

實現觀察者:

public class Bianyi1 implements Observer { //定義姓名 private String bname = "張昊天"; @Override public void update(String message,String name) { System.out.println(bname+":"+name+"那里有新情況:"+ message); } } public class Bianyi2 implements Observer { //定義姓名 private String bname = "石破天"; @Override public void update(String message,String name) { System.out.println(bname+":"+name+"那里有新情況:"+ message); } }

定義目標接口:

public interface Huairen { //添加便衣觀察者 void addObserver(Observer observer); //移除便衣觀察者 void removeObserver(Observer observer); //通知觀察者 void notice(String message); }

兩個實現目標的類:

import java.util.*; /** * 嫌犯大熊 */ public class XianFan1 implements Huairen { //別稱 private String name = "大熊"; //定義觀察者集合 private List<Observer> observerList = new ArrayList<Observer>(); //增加觀察者 @Override public void addObserver(Observer observer) { if(!observerList.contains(observer)){ observerList.add(observer); } } //移除觀察者 @Override public void removeObserver(Observer observer) { if(observerList.contains(observer)){ observerList.remove(observer); } } //通知觀察者 @Override public void notice(String message) { for(Observer observer:observerList){ observer.update(message,name); } } } import java.util.*; /** * 嫌犯黑狗 */ public class XianFan2 implements Huairen { //別稱 private String name = "黑狗"; //定義觀察者集合 private List<Observer> observerList = new ArrayList<Observer>(); //增加觀察者 @Override public void addObserver(Observer observer) { if(!observerList.contains(observer)){ observerList.add(observer); } } //移除觀察者 @Override public void removeObserver(Observer observer) { if(observerList.contains(observer)){ observerList.remove(observer); } } //通知觀察者 @Override public void notice(String message) { for(Observer observer:observerList){ observer.update(message,name); } } }

觀察者根據目標進行調用:

public class Clienter { public static void main(String[] args) { //定義兩個嫌犯 Huairen xf1 = new XianFan1(); Huairen xf2 = new XianFan2(); //定義三個觀察便衣警察 Observer o1 = new Bianyi1(); Observer o2 = new Bianyi2(); //為嫌犯增加觀察便衣 xf1.addObserver(o1); xf1.addObserver(o2); xf2.addObserver(o1); xf2.addObserver(o3); //定義嫌犯1的情況 String message1 = "又賣了一批貨"; String message2 = "老大要下來視察了"; xf1.notice(message1); xf2.notice(message2); } }

?

三、代理模式:


(1)解決場景:
? ? (a) 當我們想要隱藏某個類時,可以為其提供代理類

  (b) 當一個類需要對不同的調用者提供不同的調用權限時,可以使用代理類來實現

  (c) 當我們要擴展某個類的某個功能時,可以使用代理模式,在代理類中進行簡單擴展
(2) 如何實現:
  (a) 代理類與委托類實現同一接口
  (b) 在委托類中實現功能,在代理類的方法中中引用委托類的同名方法
  (c) 外部類調用委托類某個方法時,直接以接口指向代理類的實例,這正是代理的意義所在:屏蔽。

(3) 類圖:

?(a) 抽象的主題:

public interface Moveable {void move() throws Exception; }

(b)真實主題:

public class Car implements Moveable {public void move() throws Exception {Thread.sleep(new Random().nextInt(1000));System.out.println("汽車行駛中…");} }

(c) 事務處理器:

public class TimeHandler implements InvocationHandler {private Object target;public TimeHandler(Object target) {super();this.target = target;}/*** 參數:*proxy 被代理的對象*method 被代理對象的方法*args 方法的參數* 返回:*Object 方法返回值*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {long startTime = System.currentTimeMillis();System.out.println("汽車開始行駛…");method.invoke(target, args);long stopTime = System.currentTimeMillis();System.out.println("汽車結束行駛…汽車行駛時間:" + (stopTime - startTime) + "毫秒!");return null;}}

(d) 調用:

public class Test {public static void main(String[] args) throws Exception{Car car = new Car();InvocationHandler h = new TimeHandler(car);Class<?> cls = car.getClass();/***loader 類加載器*interfaces 實現接口*h InvocationHandler*/Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h);m.move();}

?四、裝飾模式:

裝飾者(decorator)模式:在不改變對象自身的基礎上,在程序運行期間給對像動態的添加職責。與繼承相比,裝飾者是一種更輕便靈活的做法。
裝飾者模式的特點
可以動態的給某個對象添加額外的職責,而不會影響從這個類中派生的其它對象;

(1)應用場景:

(a)在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。

? (b)? 需要動態地給一個對象增加功能,這些功能也可以動態地被撤銷。? 當不能采用繼承的方式對系統進行擴充或者采用繼承不利于系統擴展和維護時。

(2)實現的例子:

最常見的就是輸入輸出流:

BufferedReader in1 = new BufferedReader(new InputStreamReader(new FileInputStream(file)));//字符流DataInputStream in2 = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));//字節流// DataInputStream-從數據流讀取字節,并將它們裝換為正確的基本類型值或字符串// BufferedInputStream-可以通過減少讀寫次數來提高輸入和輸出的速度

?

從例子開始講解,比如今天你要出門約會,你肯定是要決定好你要穿什么樣的衣服出門,用衣服來裝飾下自己,讓自己擁有一個完美的約會。比如,你會穿一件襯衫,然后穿一件西服褲,最后穿皮鞋出門。這就是裝飾者模式的一個例子。為了實現這個功能,會有下面的代碼。 public class People {public void wearShirt(){System.out.println("******穿襯衫******");} public void wearTrouser(){System.out.println("******穿西服褲******");}public void wearShoes(){System.out.println("******穿皮鞋******");}}

?

? public class Client { public static void main(String[] args) {People people = new People();people.wearShirt();people.wearTrouser();people.wearShoes();} }

?

雖然上面的代碼實現了出門穿衣服的功能,但是這里會問題。如果我現在要增加一個功能,我要先穿襪子,再穿皮鞋。此時就要在People類中增加一個穿襪子的方法。這就違背了設計模式的開閉原則,所謂開閉原則就是類可以進行擴展,但是不可以進行修改。所以就有如下的設計: public interface People { public void wearClothing(); } public class Xiaoming implements People{ private String name; public Xiaoming(){name = "小明";} public void wearClothing(){System.out.println(name+"******開始穿衣服******");}public String getName() {return name;}} public abstract class Finery implements People { protected People people; public Finery(People people){this.people = people;}public abstract void wearClothing();} public class ShirtFinery extends Finery {public ShirtFinery(People people){super(people);}@Overridepublic void wearClothing() {people.wearClothing();System.out.println("******穿襯衫******");} } public class ShoesFinery extends Finery { public ShoesFinery(People people){super(people);}@Overridepublic void wearClothing() {people.wearClothing();System.out.println("******穿皮鞋*******");} }public class TrouserFinery extends Finery {public TrouserFinery(People people){super(people);}@Overridepublic void wearClothing() {people.wearClothing();System.out.println("******穿西服褲*******");} } public class Client { public static void main(String[] args) {People people = new Xiaoming();Finery shirtFinery = new ShirtFinery(people);Finery trouserFinery = new TrouserFinery(shirtFinery);Finery shoesFinery = new ShoesFinery(trouserFinery);shoesFinery.wearClothing();}}

? (3)類圖:

People是定義了一個接口,用來添加具體的職責,而Xiaoming是具體的People,也就是被裝飾的對象。對于Finery實現了People接口,進而對People進行擴展,而Finery的子類就是具體的裝飾類,Finery中依賴People類,裝飾的具體對象。 這就是所謂的裝飾者模式。如果我要添加穿襪子的步驟,則只需要再添加一個實現類,完全不需要修改其他代碼(Client是客戶端類,肯定是要修改的)。

?

裝飾者模式和代理模式的區別:

兩種模式的特點


裝飾模式:

  在不改變接口的前提下,動態擴展對象的訪問。
  動態繼承,讓類具有在運行期改變行為的能力。
  裝飾模式,突出的是運行期增加行為,這和繼承是不同的,繼承是在編譯期增加行為。
  強調:增強,新增行為

代理模式:

  在不改變接口的前提下,控制對象的訪問。
  1.從封裝的角度講,是為了解決類與類之間相互調用而由此導致的耦合關系,可以說是接口的另外一個層引用。
    比如:在a類->b代理->c類這個關系中,c類的一切行為都隱藏在b中。即調用者不知道要訪問的內容與代理了什么對象。
  2.從復用的角度講,可以解決不同類調用一個復雜類時,僅僅因較小的改變而導致整個復雜類新建一個類。
    比如:a類->c類1;b類->c類2。
    可以變為a類->ca代理類->c類;b類->cb代理類-c類。
  代理模式,是類之間的封裝和(某方面的)復用。
  強調:限制,控制訪問

?

總結:

  1. 裝飾模式可以讓使用者直觀的看到增強了哪些功能,而代理模式完全限制了使用者。

  2. 對裝飾模式來說,裝飾者(Decorator)和被裝飾者(Cafe)都實現同一個 接口。

  3. 對代理模式來說,代理類(Proxy Class)和真實處理的類(Real Class)都實現同一個接口。

  4.?此外,不論我們使用哪一個模式,都可以很容易地在真實對象的方法前面或者后面加上自定義的方法。

裝飾模式與繼承的比較


  明顯的,裝飾模式可以動態的擴展對象的行為。

  比如某對象有30項行為,但是在第一階段用到1-20行為,第二階段用到11-30項行為,所以這時候,就可以只定義11-20的行為。

  在第一階段運行時,可以將1-10的行為以“裝飾1”給加上

  到第二階段運行時,可以將“裝飾1”去掉,將21-30的能以“裝飾2”給加上。

  但是繼承是在編譯期增加行為。

裝飾模式的優缺點


優點:

  1. 裝飾模式可以提供比繼承更多地靈活性。
  2. 可以通過一種動態的方式來擴展一個對象的功能,在運行時選擇不同的裝飾器,從而實現不同的行為。
  3. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一對象,得到功能更為強大的對象。
  4. 具體構件類與具體裝飾類可以獨立變化,用戶可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有代碼無須改變,符合“開閉原則”。

缺點:

  1. 會產生很多的小對象(具體裝飾類),增加了系統的復雜性。
  2. 這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承易于出錯,排錯也很困難,對于多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為煩瑣。

總結

以上是生活随笔為你收集整理的策略模式、观察者模式、代理模式、装饰模式 应用场景和实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。