碼了好幾年代碼的打字機器我,對于設計模式這個詞,肯定是一點也不陌生,但是對于設計模式的理解,因為日常開發(fā)中,增刪改查較多,使用設計模式思想來優(yōu)化代碼的機會就很少。也不乏在翻閱源碼的時候,嘆服于別人優(yōu)秀高效的設計。所有今天抽出點時間,對設計模式做個歸納、記錄,以便日后讀到優(yōu)秀的源碼,可以自信的說,這**不就是那啥嗎,我也會寫~~~
設計模式
設計模式(Design Pattern)是前輩們對代碼開發(fā)經(jīng)驗的總結,是解決特定問題的一系列套路。它不是語法規(guī)定,而是一套用來提高代碼可復用性、可維護性、可讀性、穩(wěn)健性以及安全性的解決方案
代理模式
一個類代表另一個類的功能,在代理模式中,我們創(chuàng)建具有現(xiàn)有對象的對象,以便向外界提供功能接口。
代理模式在我們的生活中也很常見,例如程序員的女友想買一個法國產(chǎn)的某包包,她不需要親自去法國某個賣驢的專賣店去買,而是可以在代購手中購買,并獲得一些小禮物,折扣優(yōu)惠等等。
靜態(tài)代理
在代碼中,代理就是在使用者和服務提供者中間的服務,提供一些在提供的服務前后處理一些事物的功能。
賣東西人的認證(共同實現(xiàn)的接口)
public interface Seller {
void sell();
}
法國某經(jīng)銷商:
public class LvFactory implements Seller{
@Override
public void sell() {
System.out.println("LV廠家賣包包");
}
}
你女朋友朋友圈某個不知名好友:
class Purchase implements Seller{
private Seller seller;
public Purchase(Seller factory) {
this.seller = factory;
}
@Override
public void sell() {
System.out.println("坐飛機去法國");
seller.sell();
System.out.println("坐飛機回國");
}
}
你女朋友:
public static void main(String[] args) {
Seller lv = new LvFactory();
new Purchase(lv).sell();
}
你:
信用卡 boom~~~~~~~~~~~~~~~~~
坐飛機去法國
LV廠家賣包包
坐飛機回國
動態(tài)代理
動態(tài)代理有別于靜態(tài)代理,是根據(jù)代理的對象,動態(tài)創(chuàng)建代理類。這樣,就可以避免靜態(tài)代理中代理類接口過多的問題。動態(tài)代理是實現(xiàn)方式,是通過反射來實現(xiàn)的,借助Java自帶的java.lang.reflect.Proxy,通過固定的規(guī)則生成。
舉個??,女朋友朋友圈這個代購,代購包,也代購手表,那我找他一起買一塊手表呢?
手表接口和天梭類:
public interface Watch {
void sellWatch();
}
public class TissotWatch implements Watch {
@Override
public void sellWatch() {
System.out.println("賣天梭手表");
}
}
使用 InvocationHandler 定義代理類:
public class PurchaseProxy implements InvocationHandler {
private Object object;
public PurchaseProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("坐飛機出國");
Object result = method.invoke(object, args);
System.out.println("坐飛機回國");
return result;
}
}
在朋友圈買包買表:
public static void main(String[] args) {
//賣包
Seller lvseller = new LvFactory();
PurchaseProxy lvproxy = new PurchaseProxy(lvseller);
((Seller) Proxy.newProxyInstance(lvseller.getClass().getClassLoader(), new Class[] { Seller.class }, lvproxy)).sell();
//賣表
Watch tissot = new TissotWatch();
PurchaseProxy tissotproxy = new PurchaseProxy(tissot);
((Watch) Proxy.newProxyInstance(tissot.getClass().getClassLoader(), new Class[] { Watch.class }, tissotproxy)).sellWatch();
}
坐飛機出國
LV廠家賣包包
坐飛機回國
坐飛機出國
賣天梭手表
坐飛機回國
動態(tài)代理詳解
InvocationHandler
InvocationHandler 是一個接口,當代理方法被調(diào)用時,會調(diào)用起相對應的實現(xiàn)類的 invoke 方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
三個參數(shù):
- proxy 代理對象
- method 代理對象調(diào)用的方法
- args 調(diào)用的方法中的參數(shù)
Proxy
Java自帶的java.lang.reflect.Proxy
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
- loader 類加載器
- interfaces 代碼要用來代理的接口
- h 一個 InvocationHandler 對象
適配器模式
我們?nèi)粘J褂玫倪m配器是一個接口轉換器,它可以是一個獨立的硬件接口設備,允許硬件或電子接口與其它硬件或電子接口相連,也可以是信息接口
在代碼中,我想實現(xiàn)一個接口中的部分功能,或者想用一個類來冒充另一個類來實現(xiàn)它的功能,就需要適配器模式了。
適配器模式使接口不兼容的那些類可以一起工作,其別名為包裝器
類適配器模式
在類適配器模式中,適配器與適配者之間是繼承,適配著實現(xiàn)通用接口
舉個??,我國標準電壓是220v,手機充電器也是220v,日本標準電壓是110v,女朋友去日本玩,想給220v的手機用110v電壓充電,就需要一個適配器了。
日本插座:
public class JapanAC {
private final static int v = 110;
public void jcharge() {
System.out.printf("使用%dv電壓充電\n", v);
}
}
充電通用接口:
public interface Charger {
void charge();
}
買一個 110v升220變壓器:
public class Adaptee extends JapanAC implements Charger {
@Override
public void charge() {
System.out.println("使用適配器110v轉220v");
super.jcharge();
System.out.println("充電完成");
}
}
女朋友使用適配器充電:
public static void main(String[] args) {
Charger charger = new Adaptee();
charger.charge();
}
使用適配器110v轉220v
使用110v電壓充電
充電完成
對象適配器模式
把一只猴子偽裝成人:
有那么一種猴子:
public interface Monkey {
//吃香蕉
void eatBanana();
//騎獨輪車
void rideABike();
}
public class Shuang implements Monkey {
@Override
public void eatBanana() {
System.out.println("猴子吃香蕉");
}
@Override
public void rideABike() {
System.out.println("猴子獨輪車"); //猴子不懂人性,只會騎獨輪車
}
}
有那么個人:
public interface Human {
//吃香蕉
void eatBanana();
//開車
void drive();
}
public class Da implements Human{
@Override
public void eatBanana() {
System.out.println("人吃香蕉");
}
@Override
public void drive() {
System.out.println("人開車");
}
}
猴子偽裝成人的大型真猴修表演:
public class MonkeyMan implements Human{
private Monkey monkey;
public MonkeyMan(Monkey monkey) {
this.monkey = monkey;
}
@Override
public void eatBanana() {
monkey.eatBanana();
}
@Override
public void drive() {
monkey.rideABike();
}
}
猴子偽裝成人:
public static void main(String[] args) {
Monkey shuang = new Shuang();
Human human = new MonkeyMan(shuang); //猴子成人
human.drive();
}
猴子獨輪車
觀察者模式
當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
又被稱為發(fā)布-訂閱(Publish/Subscribe)模式
例如微博關注,多個用戶關注同一博主,博主更新,會通知到所有用戶。
羅老師微博:
public interface Bloger {
void add(Fan fan);
void del(Fan fan);
void notifySms(String sms);
}
public class Luo implements Bloger {
private List<Fan> fans;
{
fans = new ArrayList<>();
}
@Override
public void add(Fan fan) {
fans.add(fan);
}
@Override
public void del(Fan fan) {
fans.remove(fan);
}
@Override
public void notifySms(String sms) {
fans.forEach(fan -> fan.notifySms(sms));
}
}
粉絲:
public interface Fan {
void notifySms(String sms);
}
public class Xigua implements Fan {
private String name;
public Xigua(String name) {
this.name = name;
}
@Override
public void notifySms(String sms) {
System.out.println(name + " | " + sms);
}
}
羅老師直播買手機 :
public static void main(String[] args) {
Fan leijun = new Xigua("雷軍");
Fan dongmingzhu = new Xigua("董明珠");
Fan renzhengfei = new Xigua("任正非");
Bloger luo = new Luo();
luo.add(leijun);
luo.add(dongmingzhu);
luo.add(renzhengfei);
luo.notifySms("買錘子,送錘子啦?。?!");
}
雷軍 | 買錘子,送錘子啦?。?!
董明珠 | 買錘子,送錘子啦?。?!
任正非 | 買錘子,送錘子啦?。?!
實際生產(chǎn)過程中,觀察者模式往往用消息中間件來實現(xiàn)
收工
更多好玩好看的內(nèi)容,歡迎到我的博客交流,共同進步????????WaterMin