關注公眾號獲取更多資料

@
目錄- 設計模式—結構型模式
- 代理模式
- 配接器模式
- 類配接器
- 物件配接器
- 擴展--雙向配接器
- 橋接模式
- 裝飾模式
- 外觀模式
- 擴展
- 享元模式
- 組合模式
- 擴展
設計模式—結構型模式
? 結構型模式描述如何將類或者物件按照某種布局組成更大的結構,組合關系或者聚合關系的耦合度比繼承低,滿足“合成復用原則”,結構型模式主要有以下幾種:
- 代理模式:為某物件提供一種代理以控制對該物件的訪問,用戶通過代理訪問該物件,
- 配接器模式:將一個類的介面轉換成用戶希望的另一種介面,使得原本介面不兼容的能夠一起作業起作用,
- 橋接模式:將抽象和實作分離,使他們可以獨立變化,用組合關系代替繼承關系,
- 裝飾模式:動態的給物件增加一些功能,
- 外觀模式:為多個復雜的子系統提供一個一致的介面,是之更加容易被訪問,
- 享元模式:運用共享技術支持大量重復物件中共享元素的復用,
- 組合模式:將物件組合成樹結構的模式,使用戶能夠對總體物件和子物件具有一直的訪問性,
代理模式
? 代理模式在框架中很常見,Spring AOP就是通過代理模式實作的 ,
? 代理模式主要有以下幾個角色:
- 抽象主題:通過介面或者抽象類宣告需要代理的類的方法,
- 真實主題:需要被代理的類,需要實作抽象主題,
- 代理類:實作了抽象主題,并在宣告的代理方法中實作被代理類的方法,在原有的方法上進行額外的操作,
? 代理模式的類結構如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lTjMpSLj-1604422625547)(結構型模式.assets/代理模式.png)]](https://img-blog.csdnimg.cn/20201104005741796.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:
- 創建抽象主題
interface ProxyInterface {
void say();
}
- 創建真實主題
class RealObject implements ProxyInterface {
@Override
public void say() {
System.out.println("hello");
}
}
- 創建代理類
class ProxyObject implements ProxyInterface {
RealObject obj;
@Override
public void say() {
if (obj == null) obj = new RealObject();
preSay();
obj.say();
afterSay();
}
private void preSay() {
System.out.println("proxy in...");
}
private void afterSay() {
System.out.println("proxy out...");
}
}
- 測驗
public class ProxyDemo {
public static void main(String[] args) {
ProxyObject proxy = new ProxyObject();
proxy.say();
}
}
//輸出
//proxy in...
//hello
//proxy out...
? 在代理類中使用了真實主題物件,并在呼叫方法前后執行代理方法,代理類主要作用是隱藏了真實主題,在一定程度上起到了保護作用,
配接器模式
? 配接器模式是將一個類的介面轉換為用戶希望的另一個介面,解決了因為介面不兼容而不能一起作業的問題,一般情況下可以分為類配接器和物件配接器兩種,
? 配接器主要包含以下幾個結構:
- 目標介面:用戶所希望的介面,可以是抽象類或者介面,
- 適配者:現存的組件,即需要被兼容的組件,
- 配接器:將適配者轉換成目標介面的樣式的類,
類配接器
? 類配接器通過繼承和實作介面的方式完成適配程序,類圖如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XUl0Qnii-1604422625550)(結構型模式.assets/類配接器.png)]](https://img-blog.csdnimg.cn/2020110400581795.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:
- 創建目標介面
interface Adapter {
void request();
}
- 創建適配者
class Adaptee {
public void say() {
System.out.println("hello from adapdee");
}
}
- 創建適配者
class ClassAdapter extends Adaptee implements Adapter {
@Override
public void request() {
say();
}
}
- 測驗
Adapter classAdapter = new ClassAdapter();
classAdapter.request();//hello from adapdee
物件配接器
? 物件配接器,只實作了目標介面,然后在配接器中依賴適配者,使用適配者呼叫原有方法實作適配的方式,類結構如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xUSCWZGb-1604422625551)(結構型模式.assets/物件配接器.png)]](https://img-blog.csdnimg.cn/2020110400583110.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
擴展--雙向配接器
? 雙向配接器可以將適配者轉換為目標,也可以將目標轉換為適配者,他的配接器類采用物件配接器實作,如下:
class TwoWayAdapter implements Adapter, IAdaptee {
private Adaptee adaptee;
private Adapter adapter;
public TwoWayAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public TwoWayAdapter(Adapter adapter) {
this.adapter = adapter;
}
@Override
public void request() {
System.out.println("配接器呼叫適配者...");
adaptee.say();
}
@Override
public void say() {
System.out.println("適配者呼叫配接器");
adapter.request();
}
}
? 測驗:
System.out.println("--------");
TwoWayAdapter twoWayAdapter = new TwoWayAdapter(new ObjectAdapter(new Adaptee()));
twoWayAdapter.say();//hello from adapdee
System.out.println("--------");
TwoWayAdapter twoWayAdapter1 = new TwoWayAdapter(new Adaptee());
twoWayAdapter1.request();//hello from adapdee
橋接模式
? 現實生活中很多物件都是由多種元素組成,這些元素又會有多種變化,如果采用繼承的方式將會產生很多種不同的類,使系統臃腫冗余,比如一個產品有兩種元素組成,這兩種元素分別有m種和n種種類,那么如果使用繼承方式,將會有m*n種可能性,
? 橋接模式將抽象和實作分離,使他們可以獨立變化,使用組合關系替代繼承,降低了多可變的情況,
? 橋接模式主要包含以下幾個結構:
- 抽象化角色:定義抽象類,包含一個對實作化物件的參考,
- 擴展抽象化:抽象化角色的子類,實作弗雷中的業務,并呼叫實作化物件的業務方法,
- 實作化角色:定義實作化角色的介面,
- 具體實作化:實作化角色的具體實作,
? 橋接模式的類圖:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vmEnnPp0-1604422625553)(結構型模式.assets/橋接模式.png)]](https://img-blog.csdnimg.cn/20201104005849690.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:女式背包有很多種種類,比如手提包,錢包等等,也有很多種顏色,使用橋接模式可以很方便的對這些屬性進行組合,
- 創建抽象化角色
abstract class Bag {
public Color color;
public Bag(Color color) {
this.color = color;
}
abstract String getName();
public void say() {
System.out.println("i am " + getName() + ";my color is " + color.getColor());
}
}
- 擴展抽象化角色
class HandBag extends Bag {
@Override
String getName() {
return "handBag";
}
public HandBag(Color color) {
super(color);
}
}
class Wallet extends Bag {
@Override
String getName() {
return "wallet";
}
public Wallet(Color color) {
super(color);
}
}
- 實作化角色介面
interface Color {
String getColor();
}
- 具體實作化角色
class Red implements Color {
@Override
public String getColor() {
return "red";
}
}
class Yellow implements Color {
@Override
public String getColor() {
return "yellow";
}
}
- 測驗
Bag handBag = new HandBag(new Red());
handBag.say();
Bag wallet = new Wallet(new Yellow());
wallet.say();
//i am handBag;my color is red
//i am wallet;my color is yellow
裝飾模式
? 裝飾者模式是指在不改變現有物件結構的情況下,動態的對其增加一些職責的模式,
? 裝飾者模式有以下幾個成員:
- 抽象構件:定義一個抽象介面準備接受附加責任的物件,
- 具體構件:實作抽象構件,通過裝飾角色增加一些職責,
- 抽象裝飾:繼承抽象構件,包含具體構件的實體,
- 具體裝飾:實作抽象裝飾的一些方法,
? 裝飾者模式的類圖:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WIiaeDuv-1604422625554)(結構型模式.assets/裝飾者模式.png)]](https://img-blog.csdnimg.cn/20201104005905975.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 裝飾者模式與代理模式都是在不改變原有類結構的基礎上新增一些職責,兩者功能一致,從類圖上看,結構也很相似,
? 裝飾者模式關注于在一個物件上動態的添加方法,然而代理模式關注于控制對物件的訪問,換句話 說,用代理模式,代理類可以對它的客戶隱藏一個物件的具體資訊,因此,當使用代理模式的時候,我們常常在一個代理類中創建一個物件的實體,并且,當我們使用裝飾器模 式的時候,我們通常的做法是將原始物件作為一個引數傳給裝飾者的構造器,
? 可以用另外一句話來總結這些差別:使用代理模式,代理和真實物件之間的的關系通常在編譯時就已經確定了,而裝飾者能夠在運行時遞回地被構造,http://www.cnblogs.com/jaredlam/archive/2011/11/08/2241089.html)
? 舉例說明:汽車的生產—汽車物件Car,在出廠的時候可以添加修飾,使之成為不同型別的車輛,
- 抽象構件
interface Car {
void create();
}
- 具體構件
class MyCar implements Car {
@Override
public void create() {
System.out.print("it's a car.");
}
}
- 抽象裝飾
abstract class DecoratorCar implements Car {
private Car car;
public DecoratorCar(Car car) {
this.car = car;
}
@Override
public void create() {
car.create();
}
abstract void change();
}
- 具體裝飾
class Truck extends DecoratorCar {
public Truck(Car car) {
super(car);
}
public void create() {
super.create();
change();
}
@Override
protected void change() {
System.out.println("it's a truck.");
}
}
class Bus extends DecoratorCar {
public Bus(Car car) {
super(car);
}
@Override
public void create() {
super.create();
change();
}
@Override
void change() {
System.out.println("it's a bus.");
}
}
- 測驗
Car truck = new Truck(new MyCar());
truck.create();
//it's a car.it's a truck.
Car bus = new Bus(new MyCar());
bus.create();
//it's a car.it's a truck.
? 裝飾模式在Java中最著名的應用就是I/O庫的設計了,例如InputStream的子類FileInputStream,OutputStream的子類FileOutputStream等,他們都是裝飾類,
外觀模式
? 外觀模式是一種通過為多個復雜的子系統提供一個一致的介面,使這些子系統更容易被訪問,
? 外觀模式通常有以下幾種角色:
- 外觀角色:為多個子系統對外提供一個共同介面,
- 子系統角色:實作系統的部分功能,
- 客戶角色:通過外觀角色訪問各個子系統的功能,
? 外觀模式類圖如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MaW0WERm-1604422625555)(結構型模式.assets/外觀模式1.png)]](https://img-blog.csdnimg.cn/20201104005922821.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:京東購買流程包含下單,付款,打包等子系統支持
- 客戶角色
class User {
private JDShopping jd = new JDShopping();
public void buy() {
jd.shooping();
}
}
- 外觀角色
class JDShopping {
private ChooseSystem chooseSystem = new ChooseSystem();
private PaySystem paySystem = new PaySystem();
private PackageSystem packageSystem = new PackageSystem();
public void shooping() {
chooseSystem.choose();
paySystem.pay();
packageSystem.packageGoods();
}
}
- 子系統角色
class ChooseSystem {
public void choose() {
System.out.println("下單中...");
}
}
class PaySystem {
public void pay() {
System.out.println("付款中...");
}
}
class PackageSystem {
public void packageGoods() {
System.out.println("打包中...");
}
}
- 測驗
public static void main(String[] args) {
new User().buy();
//下單中...
//付款中...
//打包中...
}
擴展
? 如果需要引入其他子系統,可以使用如下結構:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QkRlyvwr-1604422625557)(結構型模式.assets/外觀模式2.png)]](https://img-blog.csdnimg.cn/20201104005935936.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
享元模式
? 享元模式運用了共享技術最大限度的支持大量細粒度物件的復用,享元模式主要有以下幾個角色:
- 抽象享元角色:所有具體享元類的基類,為具體享元的公共介面,
- 具體享元角色:實作抽象享元角色中規定的介面,
- 非享元角色:不可共享的外部狀態,
- 享元工廠角色:負責創建和管理享元角色,
? 享元模式的類圖如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rqEEfJKI-1604422625558)(結構型模式.assets/享元模式.png)]](https://img-blog.csdnimg.cn/20201104005946909.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:以圍棋為例,黑白棋子除顏色以外都具備相同的屬性,非享元角色為顏色,剩余為享元角色,
- 非享元角色
class PiecesColor {
private String color;
public PiecesColor(String color) {
this.color = color;
}
public String getColor() {
return color;
}
@Override
public int hashCode() {
return this.color.hashCode();
}
@Override
public boolean equals(Object color) {
return this.color.equals(((PiecesColor) color).getColor());
}
}
- 抽象享元角色
abstract class Pieces {
protected String shareName = "share";
protected PiecesColor color;
public Pieces(PiecesColor color) {
this.color = color;
}
public String getShareName() {
return shareName;
}
public PiecesColor getColor() {
return color;
}
public void show() {
System.out.println(this + "--shareName:" + shareName + "--color:" + color.getColor());
}
}
- 具體享元角色
class WhitePieces extends Pieces {
public WhitePieces(PiecesColor color) {
super(color);
}
}
class BlackPieces extends Pieces {
public BlackPieces(PiecesColor color) {
super(color);
}
}
- 享元工廠角色
class PiecesFactory {
//可以用任何形式儲存
Map<PiecesColor, Pieces> pieces = new HashMap<>(2);
public Pieces get(PiecesColor color) {
if (!pieces.containsKey(color)) {
System.out.println("creating...");
pieces.put(color, color.getColor().equals("white") ? new WhitePieces(color) : new BlackPieces(color));
}
return pieces.get(color);
}
}
- 測驗
PiecesFactory factory = new PiecesFactory();
Pieces pieces = factory.get(new PiecesColor("white"));
pieces.show();
pieces = factory.get(new PiecesColor("black"));
pieces.show();
//是否不再創建享元角色,使用現有物件
pieces = factory.get(new PiecesColor("white"));
pieces.show();
pieces = factory.get(new PiecesColor("black"));
pieces.show();
- 結果
creating...
com.wupengchoy.mystudy.designpattern.structure.WhitePieces@255316f2--shareName:share--color:white
creating...
com.wupengchoy.mystudy.designpattern.structure.BlackPieces@41906a77--shareName:share--color:black
com.wupengchoy.mystudy.designpattern.structure.WhitePieces@255316f2--shareName:share--color:white
com.wupengchoy.mystudy.designpattern.structure.BlackPieces@41906a77--shareName:share--color:black
? 以上結果可以看出第二次獲取物件的時候享元角色并沒有重新創建,而是使用之前創建的物件,
組合模式
? 組合模式又叫部分-整體模式,將物件組合成樹狀的層次結構的模式,表示部分和整體的關系,通常有以下幾個角色:
- 抽象構件角色:為樹葉結構和樹枝結構宣告公共介面,并實作默認行為,
- 樹葉結構角色:組合中的葉子節點物件,沒有子節點,
- 樹枝結構物件:組合中的分支節點物件,有子節點,
? 組合模式的實作方式可分為透明式和安全式,類圖和區別如下:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-D2s2o57v-1604422625560)(結構型模式.assets/組合模式1.png)]](https://img-blog.csdnimg.cn/20201104010007565.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
? 舉例說明:超市購物袋子為例,大袋子里有小袋子,還有其他商品,小袋子里還有其他商品,
- 抽象構件
abstract class BagAndGoods {
abstract void show();
}
- 樹葉結構
class Milk extends BagAndGoods {
public void show() {
System.out.println("i am milk.");
}
}
class Apple extends BagAndGoods {
public void show() {
System.out.println("i am apple.");
}
}
- 樹枝結構
class Bags extends BagAndGoods {
private List<BagAndGoods> goods = new ArrayList<>();
public void add(BagAndGoods good) {
goods.add(good);
}
@Override
public void show() {
for (BagAndGoods good : goods) {
good.show();
}
}
}
- 測驗
Bags bigBag = new Bags();
bigBag.add(new Milk());
Bags milddleBag = new Bags();
milddleBag.add(new Apple());
milddleBag.add(new Apple());
bigBag.add(milddleBag);
//展示袋子中購買的物品
bigBag.show();
//i am milk.
//i am apple.
//i am apple.
擴展
? 如果有多個樹枝和樹葉,還可以對樹枝和樹葉再進行抽象,組成如下格式:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Sgkje2Ku-1604422625562)(結構型模式.assets/組合模式2.png)]](https://img-blog.csdnimg.cn/20201104010025579.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMyMjYxMjQ3,size_16,color_FFFFFF,t_70#pic_center)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/228920.html
標籤:設計模式
上一篇:C#設計模式-模板方法模式(Template Method)
下一篇:設計模式— 行為型模式
