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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

设计模式(待更新)

發(fā)布時(shí)間:2024/1/8 asp.net 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式(待更新) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

OOP七大原則

開(kāi)閉原則:對(duì)擴(kuò)展開(kāi)發(fā),對(duì)修改關(guān)閉。
里氏替換原則: 繼承必須確保超類(lèi)所擁有的性質(zhì)在子類(lèi)中仍然成立
依賴(lài)倒置原則: 要面向接口編程,不要面向?qū)崿F(xiàn)編程。
單一職責(zé)原則: 控制類(lèi)的粒度大小、將對(duì)象解耦、提高其內(nèi)聚性。
接口隔離原則: 要為各個(gè)類(lèi)建立它們需要的專(zhuān)用接口
迪米特法則: 只與你的直接朋友交談,不跟"陌生人”說(shuō)話。
合成復(fù)用原則: 盡量先使用組合或者聚合等關(guān)聯(lián)關(guān)系來(lái)實(shí)現(xiàn),其次才考慮使用繼承關(guān)系來(lái)實(shí)現(xiàn)。

單例模式

餓漢式

package com.sanjin.single;//餓漢式單例//餓漢,一上來(lái)就把實(shí)例加載了 public class Hungry {//可能會(huì)浪費(fèi)空間private byte[] data1=new byte[1024*1024];private byte[] data2=new byte[1024*1024];private byte[] data3=new byte[1024*1024];private byte[] data4=new byte[1024*1024];//構(gòu)造器私有private Hungry(){}//保證唯一private final static Hungry HUBGRY= new Hungry();public static Hungry getInstance(){return HUBGRY;} }

DCL懶漢式

package com.sanjin.single;import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException;//懶漢式單例 public class LazyMan {private static boolean sanjin =false;private LazyMan(){synchronized (LazyMan.class){if (sanjin==false){sanjin=true;}else {throw new RuntimeException("不要試圖使用反射破壞異常");}}System.out.println(Thread.currentThread().getName());}private volatile static LazyMan lazyMan;//雙重檢測(cè)鎖模式的 懶漢式單例 DCL 懶漢式public static LazyMan getInstance(){//加鎖if (lazyMan==null){synchronized (LazyMan.class){if (lazyMan==null){lazyMan=new LazyMan();//不是原子性操作/*1. 分配內(nèi)存空間2. 執(zhí)行構(gòu)造方法初始化對(duì)象3. 把這個(gè)對(duì)象指向這個(gè)空間123132*/}}}if (lazyMan==null){lazyMan=new LazyMan();}return lazyMan;}//單線程下ok//多線程并發(fā)//反射!public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {//LazyMan instance = LazyMan.getInstance();Field sanjin = LazyMan.class.getDeclaredField("sanjin");sanjin.setAccessible(true);Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor();declaredConstructor.setAccessible(true);LazyMan lazyMan = declaredConstructor.newInstance();sanjin.set(lazyMan,false);LazyMan lazyMan1 = declaredConstructor.newInstance();System.out.println(lazyMan==lazyMan1);} }

靜態(tài)內(nèi)部類(lèi)

package com.sanjin.single;//靜態(tài)內(nèi)部類(lèi) public class Holder {private Holder(){}public static Holder getInstance(){return innerClass.HOLDER;}public static class innerClass{private static final Holder HOLDER=new Holder();} }

單例不安全,反射

枚舉

package com.sanjin.single;import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;//enum 是一個(gè)什么? 本身也是一個(gè)class類(lèi) public enum EnumSingle {INSTANCE;public EnumSingle getInstance(){return INSTANCE;} } class Test{public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {EnumSingle instance = EnumSingle.INSTANCE;Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);declaredConstructor.setAccessible(true);EnumSingle enumSingle = declaredConstructor.newInstance();System.out.println(instance==enumSingle);} }

枚舉類(lèi)型的最終反編譯

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://www.kpdus.com/jad.html // Decompiler options: packimports(3) // Source File Name: EnumSingle.javapackage com.sanjin.single;public final class EnumSingle extends Enum {public static EnumSingle[] values(){return (EnumSingle[])$VALUES.clone();}public static EnumSingle valueOf(String name){return (EnumSingle)Enum.valueOf(com/sanjin/single/EnumSingle, name);}private EnumSingle(String s, int i){super(s, i);}public EnumSingle getInstance(){return INSTANCE;}public static final EnumSingle INSTANCE;private static final EnumSingle $VALUES[];static {INSTANCE = new EnumSingle("INSTANCE", 0);$VALUES = (new EnumSingle[] {INSTANCE});} }

簡(jiǎn)單(靜態(tài))工廠模式

滿(mǎn)足 :開(kāi)閉原則,依賴(lài)倒置原則,迪米特法則。

核心本質(zhì)
實(shí)例化對(duì)象不使用new,用工廠方法代替。
將選擇實(shí)現(xiàn)類(lèi),創(chuàng)建對(duì)象統(tǒng)一管理和控制。從而將調(diào)用者跟我們的實(shí)現(xiàn)類(lèi)解耦。

簡(jiǎn)單工廠模式:
創(chuàng)建接口:

package model.factory.simple;public interface Car {void name(); }

兩個(gè)實(shí)現(xiàn)類(lèi)

package model.factory.simple;public class Tesla implements Car{@Overridepublic void name() {System.out.println("Tesla");} } package model.factory.simple;public class WuLing implements Car{@Overridepublic void name() {System.out.println("五菱神車(chē)");} }

創(chuàng)建工廠

package model.factory.simple;// 靜態(tài)工廠模式 // 增加新的產(chǎn)品,必須修改代碼,這是弊端,這違背了開(kāi)閉原則public class CarFactory {public static Car getCar(String car){if (car==null||car.length()<=0){return null;}if (car.equals("五菱")){return new WuLing();}else if (car.equals("Tesla")){return new Tesla();}return null;} }

調(diào)用實(shí)現(xiàn)

package model.factory.simple;public class Consumer {public static void main(String[] args) {// 1. 了解這個(gè)接口和實(shí)現(xiàn)類(lèi)才能new出來(lái) // Car car1=new WuLing(); // Car car2=new Tesla(); // car1.name(); // car2.name();//2. 使用工廠創(chuàng)建Car car = CarFactory.getCar("五菱");Car tesla = CarFactory.getCar("Tesla");car.name();tesla.name();} }

簡(jiǎn)單工廠模式簡(jiǎn)單易懂,但是如果要增加產(chǎn)品,就要修改源代碼,破壞開(kāi)閉規(guī)則。

工廠方法模式

在簡(jiǎn)單工廠模式的前提下,我們?cè)黾右韵骂?lèi)
工廠方法模式類(lèi)

package model.factory.method;//工廠方法模式 public interface CarFactory {Car getCar(); }

實(shí)現(xiàn)工廠方法

package model.factory.method;public class TeslaFactory implements CarFactory{@Overridepublic Car getCar() {return new Tesla();} } package model.factory.method;public class WuLingFactory implements CarFactory{@Overridepublic Car getCar() {return new WuLing();} }

測(cè)試

package model.factory.method;public class Consumer {public static void main(String[] args) {Car car = new WuLingFactory().getCar();Car car1 = new TeslaFactory().getCar();car.name();car1.name();} }

此時(shí)如果想再新增一個(gè)產(chǎn)品,只需實(shí)現(xiàn)工廠方法

package model.factory.method;public class Mobai implements Car{@Overridepublic void name() {System.out.println("摩拜單車(chē)");} } package model.factory.method;public class MobaiFactory implements CarFactory{@Overridepublic Car getCar() {return new Mobai();} }

由此發(fā)現(xiàn),這樣可以不破壞最初代碼,但是繁瑣了很多。

抽象工廠模式

抽象工廠模式簡(jiǎn)單來(lái)說(shuō)就是工廠的工廠,具體的話,我們先看個(gè)例子

首先我們先寫(xiě)一個(gè)手機(jī)的接口

package model.factory.abstract1;//手機(jī)產(chǎn)品接口 public interface PhoneProduct {void start();void shutdown();void callup();void sendSMS(); }

我們?cè)趤?lái)寫(xiě)一個(gè)路由器的接口

package model.factory.abstract1;//路由器產(chǎn)品接口 public interface RouterProduct {void start();void shutdown();void openWifi();void setting(); }

現(xiàn)在有華為和小米兩個(gè)產(chǎn)品

package model.factory.abstract1;public class HuaWeiPhone implements PhoneProduct{@Overridepublic void start() {System.out.println("開(kāi)啟華為手機(jī)");}@Overridepublic void shutdown() {System.out.println("關(guān)閉華為手機(jī)");}@Overridepublic void callup() {System.out.println("華為打電話");}@Overridepublic void sendSMS() {System.out.println("華為發(fā)短信");} } package model.factory.abstract1;public class HuaWeiRouter implements RouterProduct{@Overridepublic void start() {System.out.println("啟動(dòng)華為路由器");}@Overridepublic void shutdown() {System.out.println("關(guān)閉華為路由器");}@Overridepublic void openWifi() {System.out.println("啟動(dòng)華為路由器wifi");}@Overridepublic void setting() {System.out.println("華為路由器設(shè)置");} } package model.factory.abstract1;public class XiaomiPhone implements PhoneProduct{@Overridepublic void start() {System.out.println("開(kāi)啟小米手機(jī)");}@Overridepublic void shutdown() {System.out.println("關(guān)閉小米手機(jī)");}@Overridepublic void callup() {System.out.println("小米打電話");}@Overridepublic void sendSMS() {System.out.println("小米發(fā)短信");} } package model.factory.abstract1;//小米路由器 public class XiaomiRouter implements RouterProduct{@Overridepublic void start() {System.out.println("啟動(dòng)小米路由器");}@Overridepublic void shutdown() {System.out.println("關(guān)閉小米路由器");}@Overridepublic void openWifi() {System.out.println("啟動(dòng)小米路由器wifi");}@Overridepublic void setting() {System.out.println("小米路由器設(shè)置");} }

這樣我們有了兩個(gè)接口和對(duì)應(yīng)各自的實(shí)現(xiàn)類(lèi)
但是這樣還沒(méi)有體現(xiàn)本節(jié)內(nèi)容

所以我們加入抽象工廠

package model.factory.abstract1;//抽象產(chǎn)品工廠 public interface ProductFactory {//生產(chǎn)手機(jī)PhoneProduct phoneProduct();//生產(chǎn)路由器RouterProduct routerProduct();}

有了抽象工廠,我們還不能指定到底是生產(chǎn)華為的手機(jī)還是小米的路由器,所以

package model.factory.abstract1;public class HuaWeiFactory implements ProductFactory{@Overridepublic PhoneProduct phoneProduct() {return new HuaWeiPhone();}@Overridepublic RouterProduct routerProduct() {return new HuaWeiRouter();} } package model.factory.abstract1;public class XIaomiFactory implements ProductFactory{@Overridepublic PhoneProduct phoneProduct() {return new XiaomiPhone();}@Overridepublic RouterProduct routerProduct() {return new XiaomiRouter();} }

增加測(cè)試類(lèi):

package model.factory.abstract1;public class Client{public static void main(String[] args) {System.out.println("===========小米");//小米工廠XIaomiFactory xIaomiFactory = new XIaomiFactory();PhoneProduct phoneProduct = xIaomiFactory.phoneProduct();phoneProduct.callup();phoneProduct.sendSMS();RouterProduct routerProduct = xIaomiFactory.routerProduct();routerProduct.openWifi();System.out.println("============華為");HuaWeiFactory huaWeiFactory = new HuaWeiFactory();PhoneProduct phoneProduct1 = huaWeiFactory.phoneProduct();phoneProduct1.callup();RouterProduct routerProduct1 = huaWeiFactory.routerProduct();routerProduct1.openWifi();}}

最后的關(guān)系如下:

調(diào)理一遍:
用戶(hù)選擇工廠,工廠實(shí)現(xiàn)了抽象工廠的內(nèi)容,然后用戶(hù)根據(jù)需求調(diào)用所需要的產(chǎn)品。

建造者模式

由上面的工廠模式,我們可以理解為創(chuàng)建了一個(gè)族的產(chǎn)品,然建造者就是把這些東西組裝起來(lái)變成一個(gè)類(lèi)。
比如,造房子的過(guò)程。
我們先要有地基,然后鋼筋工廠,然后鋪電線,粉刷。最后形成一個(gè)房子。
建造者,模式,就是抽象成一個(gè)指揮者,你去控制工人們?cè)趺醋觥K{(lán)圖在你這里,你只管決定然后做出最后的產(chǎn)品。
如下:

package model.builder.demo1;//抽象的建造者 : 定義 方法 public abstract class Builder {abstract void buildA();//地基abstract void buildB();//鋼筋工廠abstract void buildC();//電線abstract void buildD();//粉刷//得到產(chǎn)品abstract Product getProduct();} package model.builder.demo1;//具體的建造者: 工人 public class Worker extends Builder{private Product product;public Worker() {this.product = new Product();}@Overridevoid buildA() {product.setBulidA("地基");System.out.println("地基");}@Overridevoid buildB() {product.setBulidB("鋼筋工程");System.out.println("鋼筋");}@Overridevoid buildC() {product.setBulidC("電線");System.out.println("電線");}@Overridevoid buildD() {product.setBulidD("粉刷");System.out.println("粉刷");}@OverrideProduct getProduct() {return product;} } package model.builder.demo1;//產(chǎn)品 : 房子 public class Product {private String bulidA;private String bulidB;private String bulidC;private String bulidD;public String getBulidA() {return bulidA;}public void setBulidA(String bulidA) {this.bulidA = bulidA;}public String getBulidB() {return bulidB;}public void setBulidB(String bulidB) {this.bulidB = bulidB;}public String getBulidC() {return bulidC;}public void setBulidC(String bulidC) {this.bulidC = bulidC;}public String getBulidD() {return bulidD;}public void setBulidD(String bulidD) {this.bulidD = bulidD;}@Overridepublic String toString() {return "Product{" +"bulidA='" + bulidA + '\'' +", bulidB='" + bulidB + '\'' +", bulidC='" + bulidC + '\'' +", bulidD='" + bulidD + '\'' +'}';} } package model.builder.demo1;//指揮:核心 如何構(gòu)建由他決定 public class Director {//指揮工人按照順序造房子public Product build(Builder builder){builder.buildA();builder.buildB();builder.buildC();builder.buildD();return builder.getProduct();} } package model.builder.demo1;public class Test {public static void main(String[] args) {//指揮Director director=new Director();//指揮具體的工人完成產(chǎn)品Product build = director.build(new Worker());System.out.println(build.toString());} }

但是這樣,只是定死的內(nèi)容,我們大多數(shù)場(chǎng)景,是由用戶(hù)為指揮者。
我們舉例為麥當(dāng)勞,里面有套餐還可以用戶(hù)自定義 就是單點(diǎn)。

初始值就為套餐

package model.builder.demo2;//建造者 public abstract class Bulider {public abstract Bulider buliderA(String msg);//漢堡public abstract Bulider buliderB(String msg);//可樂(lè)public abstract Bulider buliderC(String msg);//薯?xiàng)lpublic abstract Bulider buliderD(String msg);//甜點(diǎn)abstract Product getProduct(); } package model.builder.demo2;//產(chǎn)品、套餐 public class Product {private String BuildA="漢堡";private String BuildB="可樂(lè)";private String BuildC="薯?xiàng)l";private String BuildD="甜點(diǎn)";public void setBuildA(String buildA) {BuildA = buildA;}public void setBuildB(String buildB) {BuildB = buildB;}public void setBuildC(String buildC) {BuildC = buildC;}public void setBuildD(String buildD) {BuildD = buildD;}@Overridepublic String toString() {return "Product{" +"BuildA='" + BuildA + '\'' +", BuildB='" + BuildB + '\'' +", BuildC='" + BuildC + '\'' +", BuildD='" + BuildD + '\'' +'}';} } package model.builder.demo2;//具體建造者 public class Worker extends Bulider{private Product product;public Worker() {this.product = new Product();}@Overridepublic Bulider buliderA(String msg) {product.setBuildA(msg);return this;}@Overridepublic Bulider buliderB(String msg) {product.setBuildB(msg);return this;}@Overridepublic Bulider buliderC(String msg) {product.setBuildC(msg);return this;}@Overridepublic Bulider buliderD(String msg) {product.setBuildD(msg);return this;}@OverrideProduct getProduct() {return product;} } package model.builder.demo2;public class Test {public static void main(String[] args) {//服務(wù)員Worker worker=new Worker();Product product = worker.buliderA("全家桶").getProduct();System.out.println(product.toString());} }

這樣我們就可以自定義建造什么了。

原型模式

原型模式就是當(dāng)我們new出來(lái)一個(gè)對(duì)象,如果想克隆這個(gè)對(duì)象,不用new 而是把這個(gè)對(duì)象當(dāng)作一個(gè)原型所引用。
我們舉個(gè)例子,視頻搬運(yùn)。

package model.prototype.demo1;import java.util.Date;/* 1. 實(shí)現(xiàn)一個(gè)接口 Cloneable 2. 重寫(xiě)一個(gè)方法 clone()*///Video public class Video implements Cloneable {//搬運(yùn),克隆別人的視頻private String name;private Date createTime;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public Video(String name, Date createTime) {this.name = name;this.createTime = createTime;}public Video() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}@Overridepublic String toString() {return "Video{" +"name='" + name + '\'' +", createTime=" + createTime +'}';} } package model.prototype.demo1;import java.util.Date;/* 客戶(hù)端: 克隆*/ public class Bilibili {public static void main(String[] args) throws CloneNotSupportedException {//原型對(duì)象Date date = new Date();Video v1 = new Video("三金", date);System.out.println(v1);System.out.println("hash="+v1.hashCode());//v1可以克隆v2Video v2 = (Video) v1.clone();//克隆出來(lái)的對(duì)象和原來(lái)一樣System.out.println(v2);System.out.println("hash="+v2.hashCode());v2.setName("克隆三金");System.out.println(v2);} }

結(jié)果是

Video{name='三金', createTime=Wed Apr 21 19:04:56 GMT+08:00 2021} hash=1735600054 Video{name='三金', createTime=Wed Apr 21 19:04:56 GMT+08:00 2021} hash=21685669 Video{name='克隆三金', createTime=Wed Apr 21 19:04:56 GMT+08:00 2021}

但是如果我們改變的了date的值,發(fā)現(xiàn)v1 v2都會(huì)改變。這就是淺克隆。
基本類(lèi)型值會(huì)相互克隆,引用類(lèi)型會(huì)指向相同的地址。
一般我們都希望互不干擾,就是深克隆。
所以我們重寫(xiě)clone方法。

@Overrideprotected Object clone() throws CloneNotSupportedException {Object clone =super.clone();Video v= (Video) clone;v.createTime= (Date) this.createTime.clone();return clone;} Video{name='三金', createTime=Thu Jan 01 12:12:31 GMT+08:00 1970} Video{name='克隆三金', createTime=Wed Apr 21 19:12:32 GMT+08:00 2021}

這樣就可以變成一對(duì)一的了

適配器模式

適配器模式我們可以想象成電腦網(wǎng)線轉(zhuǎn)換器

適配器就是讓兩個(gè)東西相互兼容,相互影響。
舉例如下:
網(wǎng)線-適配器-usb

網(wǎng)線:

package model.adapter;//要被適配的類(lèi) : 網(wǎng)線 public class Adaptee {public void request(){System.out.println("連接網(wǎng)線上網(wǎng)。");} }

適配器:

package model.adapter;//真正的適配器 需要連接usb 網(wǎng)線 public class Adapter extends Adaptee implements NetToUSB{@Overridepublic void handleRequest() {super.request();//可以上網(wǎng)了} }

usb:

package model.adapter;//接口轉(zhuǎn)換器的抽象實(shí)現(xiàn) public interface NetToUSB {//處理請(qǐng)求 把網(wǎng)線插到usbpublic void handleRequest(); }

測(cè)試:

package model.adapter;//客戶(hù)端類(lèi) : 想上網(wǎng),插不上網(wǎng)線 public class Computer {//我們電腦需要連接到轉(zhuǎn)接器才能上網(wǎng)public void net(NetToUSB adapter){//上網(wǎng)的具體實(shí)現(xiàn) 找一個(gè)轉(zhuǎn)接頭adapter.handleRequest();}public static void main(String[] args) {//電腦 適配器 網(wǎng)線Computer computer = new Computer();//電腦Adapter adapter = new Adapter();//轉(zhuǎn)接器Adaptee adaptee = new Adaptee();//網(wǎng)線computer.net(adapter);} }

這樣就簡(jiǎn)單的實(shí)現(xiàn)了適配器模式的基本用途。

但是我們不想只要這一根網(wǎng)線進(jìn)這一個(gè)適配器(因?yàn)橛昧死^承)
所以對(duì)適配器進(jìn)行改進(jìn)

package model.adapter;//組合 //對(duì)象適配器 public class Adapter2 implements NetToUSB{private Adaptee adaptee;public Adapter2(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void handleRequest() {adaptee.request();} }

這樣每次調(diào)用的時(shí)候可以指定網(wǎng)線了。

package model.adapter;//客戶(hù)端類(lèi) : 想上網(wǎng),插不上網(wǎng)線 public class Computer {//我們電腦需要連接到轉(zhuǎn)接器才能上網(wǎng)public void net(NetToUSB adapter){//上網(wǎng)的具體實(shí)現(xiàn) 找一個(gè)轉(zhuǎn)接頭adapter.handleRequest();}public static void main(String[] args) {//電腦 適配器 網(wǎng)線Computer computer = new Computer();//電腦Adaptee adaptee = new Adaptee();//網(wǎng)線Adapter2 adapter2 = new Adapter2(adaptee);//轉(zhuǎn)接線2computer.net(adapter2);} }

要體會(huì)這里的思想。

橋接模式

我們看下面的圖

如果想獲得蘋(píng)果筆記本電腦 或者 聯(lián)想臺(tái)式電腦 該如何呢。
我們應(yīng)該在這兩個(gè)直接搭一個(gè)橋梁(可能有點(diǎn)像適配器模式,不過(guò)是不一樣的,我們需要仔細(xì)考慮考慮)

我們根據(jù)上述建立代碼

package model.bridge;public interface Brand {void info(); } package model.bridge;//蘋(píng)果品牌 public class Apple implements Brand{@Overridepublic void info() {System.out.println("蘋(píng)果");} } package model.bridge;//聯(lián)想品牌 public class Lenovo implements Brand{@Overridepublic void info() {System.out.println("聯(lián)想");} }

一個(gè)分支結(jié)束。

package model.bridge;//抽象的電腦類(lèi)型類(lèi) public abstract class Computer {//組合,品牌~protected Brand brand;public Computer(Brand brand) {this.brand = brand;}public void info(){//自帶品牌brand.info();} } class Desktop extends Computer{public Desktop(Brand brand) {super(brand);}@Overridepublic void info() {super.info();System.out.println("臺(tái)式機(jī)");} } class Laptop extends Computer{public Laptop(Brand brand) {super(brand);}@Overridepublic void info() {super.info();System.out.println("筆記本");} }

這里我們使用了組合 ,通過(guò)構(gòu)造器讓兩個(gè)分支有了聯(lián)系。

這里如果體會(huì)不到好處的話 ,我再畫(huà)一個(gè)圖

這樣就會(huì)變成多繼承的關(guān)系。

所以就體現(xiàn)出了橋接的好處。

代理模式

為什么要學(xué)習(xí)代理模式?因?yàn)檫@就是SpringAOP的底層!【SpringAOP 和 Spring MVC】面試必問(wèn)

代理模式的分類(lèi):

  • 靜態(tài)代理
  • 動(dòng)態(tài)代理

靜態(tài)代理

角色分析:

  • 抽象角色:一般會(huì)使用接口或者抽象類(lèi)來(lái)解決
  • 真實(shí)角色:被代理的角色
  • 代理角色:代理真實(shí)角色,代理真實(shí)角色后,我們一般會(huì)做一些附屬操作
  • 客戶(hù):訪問(wèn)代理對(duì)象的人

代碼步驟:

  • 接口
  • package com.sanjin.demo01;//租房 public interface Rent {public void rent(); }
  • 真實(shí)角色
  • package com.sanjin.demo01;//房東 public class Host implements Rent{public void rent() {System.out.println("房東要出租房子");} }
  • 代理角色
  • package com.sanjin.demo01;public class Proxy implements Rent{private Host host;public Proxy(Host host) {this.host = host;}public Proxy() {}public void rent() {host.rent();seeHouse();fee();contract();}//看房public void seeHouse(){System.out.println("中介帶你看房");}//收中介費(fèi)public void fee(){System.out.println("收中介費(fèi)");}//合同public void contract(){System.out.println("簽租賃合同");}}
  • 客戶(hù)端訪問(wèn)代理角色
  • package com.sanjin.demo01;public class Client {public static void main(String[] args) {//房東要租房子Host host = new Host();//代理,中介幫房東租房子,代理角色一般會(huì)有附屬操作Proxy proxy = new Proxy(host);//你不用面對(duì)房東,直接找中介proxy.rent();} }

    代理模式的好處:

    • 可以使真實(shí)角色的操作更加純粹,不用去關(guān)注一些公共業(yè)務(wù)
    • 公共業(yè)務(wù)就交給代理角色,實(shí)現(xiàn)了業(yè)務(wù)的分工
    • 公共業(yè)務(wù)發(fā)生拓展的時(shí)候,方便集中管理!

    缺點(diǎn):

    • 一個(gè)真實(shí)角色,就會(huì)又一個(gè)代理角色,代碼量會(huì)翻倍,開(kāi)發(fā)效率會(huì)變低

    加深理解

  • 接口
  • package com.sanjin.demo02;public interface UserService {void add();void delete();void apdate();void query(); }
  • 真實(shí)角色
  • package com.sanjin.demo02;//真實(shí)對(duì)象 public class UserServiceImpl implements UserService{public void add() {System.out.println("增加了一個(gè)用戶(hù)");}public void delete() {System.out.println("刪除了一個(gè)用戶(hù)");}public void apdate() {System.out.println("修改了一個(gè)用戶(hù)");}public void query() {System.out.println("查找了一個(gè)用戶(hù)");} }
  • 代理角色
  • package com.sanjin.demo02;//代理增加日志 public class UserServiceProxy implements UserService{private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService = userService;}public void add() {log("add");userService.add();}public void delete() {log("del");userService.delete();}public void apdate() {log("upd");userService.apdate();}public void query() {log("query");userService.query();}//日志方法public void log(String msg){System.out.println("使用了"+msg+"方法");} }
  • 客戶(hù)端
  • package com.sanjin.demo02;public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();UserServiceProxy userServiceProxy = new UserServiceProxy();userServiceProxy.setUserService(userService);userServiceProxy.add();} }

    動(dòng)態(tài)代理

    • 動(dòng)態(tài)代理和靜態(tài)代理角色一樣
    • 動(dòng)態(tài)代理的類(lèi)是動(dòng)態(tài)生成的,不是我們直接寫(xiě)好的
    • 動(dòng)態(tài)代理分為兩大類(lèi):基于接口的動(dòng)態(tài)代理;基于類(lèi)的動(dòng)態(tài)代理
      • 基于接口— JDK 動(dòng)態(tài)代理【我們?cè)龠@里使用】
      • 基于類(lèi):cglib
      • java字節(jié)碼實(shí)現(xiàn):javassist

    需要了解兩個(gè)類(lèi):Proxy: ?代理, InvocationHandler:調(diào)用處理程序

    InvocationHandler

    動(dòng)態(tài)代理類(lèi)

    package com.sanjin.domo04;import com.sanjin.demo03.Rent;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;//我們會(huì)用這個(gè)類(lèi) 自動(dòng)生成代理類(lèi) public class Proxy2 implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}//處理代理實(shí)例,并返回結(jié)果public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//動(dòng)態(tài)代理的本質(zhì)就是使用反射log(method.getName());Object result = method.invoke(target, args);return result;}public void log(String mes){System.out.println("執(zhí)行了"+mes+"日志方法");}}

    測(cè)試類(lèi)

    package com.sanjin.domo04;import com.sanjin.demo02.UserService; import com.sanjin.demo02.UserServiceImpl;public class Client {public static void main(String[] args) {//真實(shí)角色UserServiceImpl userService = new UserServiceImpl();//代理角色Proxy2 proxy2 = new Proxy2();proxy2.setTarget(userService);//設(shè)置要代理的對(duì)象//動(dòng)態(tài)生成代理類(lèi)UserService proxy = (UserService) proxy2.getProxy();proxy.add();proxy.delete();} }

    動(dòng)態(tài)代理的好處:

    • 可以使真實(shí)角色的操作更加純粹,不用去關(guān)注一些公共業(yè)務(wù)
    • 公共業(yè)務(wù)就交給代理角色,實(shí)現(xiàn)了業(yè)務(wù)的分工
    • 公共業(yè)務(wù)發(fā)生拓展的時(shí)候,方便集中管理!
    • 一個(gè)動(dòng)態(tài)代理類(lèi)代理的是一個(gè)接口,一般就是對(duì)應(yīng)的一類(lèi)業(yè)務(wù)
    • 一個(gè)動(dòng)態(tài)代理類(lèi)可以代理多個(gè)類(lèi),只要是實(shí)現(xiàn)了同一個(gè)接口即可

    總結(jié)

    以上是生活随笔為你收集整理的设计模式(待更新)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。