關注公衆號獲取更多資料
html
@java
結構型模式描述如何將類或者對象按照某種佈局組成更大的結構。組合關係或者聚合關係的耦合度比繼承低,知足「合成複用原則」。結構型模式主要有如下幾種:設計模式
代理模式在框架中很常見,Spring AOP就是經過代理模式實現的 。安全
代理模式主要有如下幾個角色:app
代理模式的類結構以下:框架
舉例說明:ide
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...
在代理類中使用了真實主題對象,並在調用方法先後執行代理方法。代理類主要做用是隱藏了真實主題,在必定程度上起到了保護做用。oop
適配器模式是將一個類的接口轉換爲用戶但願的另外一個接口,解決了由於接口不兼容而不能一塊兒工做的問題。通常狀況下能夠分爲類適配器和對象適配器兩種。佈局
適配器主要包含如下幾個結構:測試
類適配器經過繼承和實現接口的方式完成適配過程,類圖以下:
舉例說明:
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
對象適配器,只實現了目標接口,而後在適配器中依賴適配者,使用適配者調用原有方法實現適配的方式,類結構以下:
雙向適配器能夠將適配者轉換爲目標,也能夠將目標轉換爲適配者。他的適配器類採用對象適配器實現,以下:
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種可能性。
橋接模式將抽象和實現分離,使他們能夠獨立變化,使用組合關係替代繼承,下降了多可變的狀況。
橋接模式主要包含如下幾個結構:
橋接模式的類圖:
舉例說明:女式揹包有不少種種類,好比手提包,錢包等等,也有不少種顏色,使用橋接模式能夠很方便的對這些屬性進行組合。
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
裝飾者模式是指在不改變現有對象結構的狀況下,動態的對其增長一些職責的模式。
裝飾者模式有如下幾個成員:
裝飾者模式的類圖:
裝飾者模式與代理模式都是在不改變原有類結構的基礎上新增一些職責,二者功能一致,從類圖上看,結構也很類似。
裝飾者模式關注於在一個對象上動態的添加方法,然而代理模式關注於控制對對象的訪問。換句話 說,用代理模式,代理類能夠對它的客戶隱藏一個對象的具體信息。所以,當使用代理模式的時候,咱們經常在一個代理類中建立一個對象的實例。而且,當咱們使用裝飾器模 式的時候,咱們一般的作法是將原始對象做爲一個參數傳給裝飾者的構造器。
能夠用另一句話來總結這些差異:使用代理模式,代理和真實對象之間的的關係一般在編譯時就已經肯定了,而裝飾者可以在運行時遞歸地被構造。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等,他們都是裝飾類。
外觀模式是一種經過爲多個複雜的子系統提供一個一致的接口,使這些子系統更容易被訪問。
外觀模式一般有如下幾種角色:
外觀模式類圖以下:
舉例說明:京東購買流程包含下單,付款,打包等子系統支持
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(); //下單中... //付款中... //打包中... }
若是須要引入其餘子系統,可使用以下結構:
享元模式運用了共享技術最大限度的支持大量細粒度對象的複用。享元模式主要有如下幾個角色:
享元模式的類圖以下:
舉例說明:以圍棋爲例,黑白棋子除顏色之外都具有相同的屬性,非享元角色爲顏色,剩餘爲享元角色。
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
以上結果能夠看出第二次獲取對象的時候享元角色並無從新建立,而是使用以前建立的對象。
組合模式又叫部分-總體模式,將對象組合成樹狀的層次結構的模式,表示部分和總體的關係。一般有如下幾個角色:
組合模式的實現方式可分爲透明式和安全式,類圖和區別以下:
舉例說明:超市購物袋子爲例,大袋子裏有小袋子,還有其餘商品,小袋子裏還有其餘商品。
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.
若是有多個樹枝和樹葉,還能夠對樹枝和樹葉再進行抽象,組成以下格式: