把一個類接口轉換成另外一個用戶須要的接口。html
鴨子(Duck)和火雞(Turkey)擁有不一樣的叫聲,Duck 的叫聲調用 quack() 方法,而 Turkey 調用 gobble() 方法。java
要求將 Turkey 的 gobble() 方法適配成 Duck 的 quack() 方法,從而讓火雞冒充鴨子!node
public interface Duck { void quack(); } public interface Turkey { void gobble(); } public class WildTurkey implements Turkey { @Override public void gobble() { System.out.println("gobble!"); } } public class TurkeyAdapter implements Duck { Turkey turkey; public TurkeyAdapter(Turkey turkey) { this.turkey = turkey; } @Override public void quack() { turkey.gobble(); } } public class Client { public static void main(String[] args) { Turkey turkey = new WildTurkey(); Duck duck = new TurkeyAdapter(turkey); duck.quack(); } }
將抽象與實現分離開來,使它們能夠獨立變化。git
RemoteControl 表示遙控器,指代 Abstraction。github
TV 表示電視,指代 Implementor。api
橋接模式將遙控器和電視分離開來,從而能夠獨立改變遙控器或者電視的實現。緩存
public abstract class TV { public abstract void on(); public abstract void off(); public abstract void tuneChannel(); } public class Sony extends TV { @Override public void on() { System.out.println("Sony.on()"); } @Override public void off() { System.out.println("Sony.off()"); } @Override public void tuneChannel() { System.out.println("Sony.tuneChannel()"); } } public class RCA extends TV { @Override public void on() { System.out.println("RCA.on()"); } @Override public void off() { System.out.println("RCA.off()"); } @Override public void tuneChannel() { System.out.println("RCA.tuneChannel()"); } } public abstract class RemoteControl { protected TV tv; public RemoteControl(TV tv) { this.tv = tv; } public abstract void on(); public abstract void off(); public abstract void tuneChannel(); } public class ConcreteRemoteControl1 extends RemoteControl { public ConcreteRemoteControl1(TV tv) { super(tv); } @Override public void on() { System.out.println("ConcreteRemoteControl1.on()"); tv.on(); } @Override public void off() { System.out.println("ConcreteRemoteControl1.off()"); tv.off(); } @Override public void tuneChannel() { System.out.println("ConcreteRemoteControl1.tuneChannel()"); tv.tuneChannel(); } } public class ConcreteRemoteControl2 extends RemoteControl { public ConcreteRemoteControl2(TV tv) { super(tv); } @Override public void on() { System.out.println("ConcreteRemoteControl2.on()"); tv.on(); } @Override public void off() { System.out.println("ConcreteRemoteControl2.off()"); tv.off(); } @Override public void tuneChannel() { System.out.println("ConcreteRemoteControl2.tuneChannel()"); tv.tuneChannel(); } } public class Client { public static void main(String[] args) { RemoteControl remoteControl1 = new ConcreteRemoteControl1(new RCA()); remoteControl1.on(); remoteControl1.off(); remoteControl1.tuneChannel(); RemoteControl remoteControl2 = new ConcreteRemoteControl2(new Sony()); remoteControl2.on(); remoteControl2.off(); remoteControl2.tuneChannel(); } }
將對象組合成樹形結構來表示「總體/部分」層次關係,容許用戶以相同的方式處理單獨對象和組合對象。併發
組件(Component)類是組合類(Composite)和葉子類(Leaf)的父類,能夠把組合類當作是樹的中間節點。oracle
組合對象擁有一個或者多個組件對象,所以組合對象的操做能夠委託給組件對象去處理,而組件對象能夠是另外一個組合對象或者葉子對象。分佈式
public abstract class Component { protected String name; public Component(String name) { this.name = name; } public void print() { print(0); } abstract void print(int level); abstract public void add(Component component); abstract public void remove(Component component); } public class Composite extends Component { private List<Component> child; public Composite(String name) { super(name); child = new ArrayList<>(); } @Override void print(int level) { for (int i = 0; i < level; i++) { System.out.print("--"); } System.out.println("Composite:" + name); for (Component component : child) { component.print(level + 1); } } @Override public void add(Component component) { child.add(component); } @Override public void remove(Component component) { child.remove(component); } } public class Leaf extends Component { public Leaf(String name) { super(name); } @Override void print(int level) { for (int i = 0; i < level; i++) { System.out.print("--"); } System.out.println("left:" + name); } @Override public void add(Component component) { throw new UnsupportedOperationException(); // 犧牲透明性換取單一職責原則,這樣就不用考慮是葉子節點仍是組合節點 } @Override public void remove(Component component) { throw new UnsupportedOperationException(); } } public class Client { public static void main(String[] args) { Composite root = new Composite("root"); Component node1 = new Leaf("1"); Component node2 = new Composite("2"); Component node3 = new Leaf("3"); root.add(node1); root.add(node2); root.add(node3); Component node21 = new Leaf("21"); Component node22 = new Composite("22"); node2.add(node21); node2.add(node22); Component node221 = new Leaf("221"); node22.add(node221); root.print(); } } Composite:root --left:1 --Composite:2 ----left:21 ----Composite:22 ------left:221 --left:3
爲對象動態添加功能。
裝飾者(Decorator)和具體組件(ConcreteComponent)都繼承自組件(Component),具體組件的方法實現不須要依賴於其它對象,而裝飾者組合了一個組件,這樣它能夠裝飾其它裝飾者或者具體組件。所謂裝飾,就是把這個裝飾者套在被裝飾者之上,從而動態擴展被裝飾者的功能。裝飾者的方法有一部分是本身的,這屬於它的功能,而後調用被裝飾者的方法實現,從而也保留了被裝飾者的功能。能夠看到,具體組件應當是裝飾層次的最低層,由於只有具體組件的方法實現不須要依賴於其它對象。
設計不一樣種類的飲料,飲料能夠添加配料,好比能夠添加牛奶,而且支持動態添加新配料。每增長一種配料,該飲料的價格就會增長,要求計算一種飲料的價格。
下圖表示在 DarkRoast 飲料上新增新添加 Mocha 配料,以後又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它們都繼承自相同父類,都有 cost() 方法,外層類的 cost() 方法調用了內層類的 cost() 方法。
public interface Beverage { double cost(); } public class DarkRoast implements Beverage { @Override public double cost() { return 1; } } public class HouseBlend implements Beverage { @Override public double cost() { return 1; } } public abstract class CondimentDecorator implements Beverage { protected Beverage beverage; } public class Milk extends CondimentDecorator { public Milk(Beverage beverage) { this.beverage = beverage; } @Override public double cost() { return 1 + beverage.cost(); } } public class Mocha extends CondimentDecorator { public Mocha(Beverage beverage) { this.beverage = beverage; } @Override public double cost() { return 1 + beverage.cost(); } } public class Client { public static void main(String[] args) { Beverage beverage = new HouseBlend(); beverage = new Mocha(beverage); beverage = new Milk(beverage); System.out.println(beverage.cost()); } } 3.0
類應該對擴展開放,對修改關閉:也就是添加新功能時不須要修改代碼。飲料能夠動態添加新的配料,而不須要去修改飲料的代碼。
不可能把全部的類設計成都知足這一原則,應當把該原則應用於最有可能發生改變的地方。
提供了一個統一的接口,用來訪問子系統中的一羣接口,從而讓子系統更容易使用。
觀看電影須要操做不少電器,使用外觀模式實現一鍵看電影功能。
public class SubSystem { public void turnOnTV() { System.out.println("turnOnTV()"); } public void setCD(String cd) { System.out.println("setCD( " + cd + " )"); } public void startWatching(){ System.out.println("startWatching()"); } } public class Facade { private SubSystem subSystem = new SubSystem(); public void watchMovie() { subSystem.turnOnTV(); subSystem.setCD("a movie"); subSystem.startWatching(); } } public class Client { public static void main(String[] args) { Facade facade = new Facade(); facade.watchMovie(); } }
最少知識原則:只和你的密友談話。也就是說客戶對象所須要交互的對象應當儘量少。
利用共享的方式來支持大量細粒度的對象,這些對象一部份內部狀態是相同的。
public interface Flyweight { void doOperation(String extrinsicState); } public class ConcreteFlyweight implements Flyweight { private String intrinsicState; public ConcreteFlyweight(String intrinsicState) { this.intrinsicState = intrinsicState; } @Override public void doOperation(String extrinsicState) { System.out.println("Object address: " + System.identityHashCode(this)); System.out.println("IntrinsicState: " + intrinsicState); System.out.println("ExtrinsicState: " + extrinsicState); } } public class FlyweightFactory { private HashMap<String, Flyweight> flyweights = new HashMap<>(); Flyweight getFlyweight(String intrinsicState) { if (!flyweights.containsKey(intrinsicState)) { Flyweight flyweight = new ConcreteFlyweight(intrinsicState); flyweights.put(intrinsicState, flyweight); } return flyweights.get(intrinsicState); } } public class Client { public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight flyweight1 = factory.getFlyweight("aa"); Flyweight flyweight2 = factory.getFlyweight("aa"); flyweight1.doOperation("x"); flyweight2.doOperation("y"); } } Object address: 1163157884 IntrinsicState: aa ExtrinsicState: x Object address: 1163157884 IntrinsicState: aa ExtrinsicState: y
Java 利用緩存來加速大量小對象的訪問時間。
控制對其它對象的訪問。
代理有如下四類:
如下是一個虛擬代理的實現,模擬了圖片延遲加載的狀況下使用與圖片大小相等的臨時內容去替換原始圖片,直到圖片加載完成纔將圖片顯示出來。
public interface Image { void showImage(); } public class HighResolutionImage implements Image { private URL imageURL; private long startTime; private int height; private int width; public int getHeight() { return height; } public int getWidth() { return width; } public HighResolutionImage(URL imageURL) { this.imageURL = imageURL; this.startTime = System.currentTimeMillis(); this.width = 600; this.height = 600; } public boolean isLoad() { // 模擬圖片加載,延遲 3s 加載完成 long endTime = System.currentTimeMillis(); return endTime - startTime > 3000; } @Override public void showImage() { System.out.println("Real Image: " + imageURL); } } public class ImageProxy implements Image { private HighResolutionImage highResolutionImage; public ImageProxy(HighResolutionImage highResolutionImage) { this.highResolutionImage = highResolutionImage; } @Override public void showImage() { while (!highResolutionImage.isLoad()) { try { System.out.println("Temp Image: " + highResolutionImage.getWidth() + " " + highResolutionImage.getHeight()); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } highResolutionImage.showImage(); } } public class ImageViewer { public static void main(String[] args) throws Exception { String image = "http://image.jpg"; URL url = new URL(image); HighResolutionImage highResolutionImage = new HighResolutionImage(url); ImageProxy imageProxy = new ImageProxy(highResolutionImage); imageProxy.showImage(); } }
本人免費整理了Java高級資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分佈式等教程,一共30G,須要本身領取。
傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q