您好,登錄后才能下訂單哦!
創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式
什么是單例?
保證一個類只會創建一個實例
應用場景:
運行時動態獲取類信息
餓漢式
/**
* 餓漢式:
* 類初始化時,會立即加載對象,線程天生安全,效率高
*/
public class User {
// 存在方法區,不會回收
private static User user = new User();
private User() {
}
public User getInstance() {
return user;
}
懶漢式
/**
* 懶漢式:
* 類初始化時,不會真正創建對象,只有使用時才真正創建對象
*/
public class User {
private static User user;
private User() {
}
public static synchronized User getInstance() {
if (user == null)
user = new User();
return user;
}
}
靜態內部類
/**
* 靜態內部類:
* 兼顧了懶漢模式的內存優化(使用時才初始化)以及餓漢模式的安全性(不會被反射***)
*/
public class User {
private User(){
}
static class SingletonClassInstance{
private static final User user = new User();
}
public static User getInstance() {
return SingletonClassInstance.user;
}
}
枚舉方式
/**
* 枚舉:
* 枚舉天生就是單例,從JVM提供保障單例,避免反射,缺點沒有延遲加載
*/
public class User {
private User() {
}
public static User getInstance() {
return SingletonUserEnum.INSTANCE.getInstance();
}
static enum SingletonUserEnum{
INSTANCE;
private User user;
private SingletonUserEnum() {
user = new User();
}
public User getInstance() {
return this.user;
}
}
}
雙重檢驗鎖
/**
* 雙重檢驗鎖:
* 線程安全的單例模式
*/
public class User {
private String userName;
private volatile static User3 user3;
private User(){
}
public User getInstance(){
if (user == null) {
synchronized (this) {
if (user == null){
user = new User();
}
}
}
return user;
}
}
如何防止反射漏洞***?
在類里面增加一個 flag,初始值為 false,創建對象后更改為 true,如果為 true,就拋出異常
如何選擇單例創建方式?
需要延遲加載,選擇靜態內部類、懶漢式
不需要延遲加載,選擇枚舉類、餓漢式
多線程應用首選雙重檢驗鎖
什么是工廠模式?
實現了創建者和調用者分離,工廠模式分為簡單工廠、工廠方法、抽象工廠模式
應用場景:
簡單工廠
/**
* 簡單工廠相當于一個工廠有各種產品,用戶無需知道具體產品的名稱,只需要知道產品對應的參數即可
* 缺點是類型過多不利于擴展維護
*/
public class CarFactory {
public static Car createrCar(String name) {
if (name == null || name.equals(""))
return null;
if (name.equals("比亞迪"))
return new BydCar();
if (name.equals("吉利"))
return new JiliCar();
return null;
}
}
工廠方法
/**
* 核心工廠不在負責所有產品的創建,而是將具體實現交給子類
*/
public interface CarFactory {
Car createrCar(String name);
}
class BydFactory implements CarFactory {
@Override
public Car createrCar(String name) {
return new BydCar();
}
}
class JiliFactory implements CarFactory {
@Override
public Car createrCar(String name) {
return new JiliCar();
}
}
什么是抽象工廠模式?
抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創建其他工廠
該超級工廠又稱為其他工廠的工廠,這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式
在抽象工廠模式中,接口是負責創建一個相關對象的工廠,不需要顯式指定它們的類,每個生成的工廠都能按照工廠模式提供對象
應用場景:
/**
* 抽象工廠簡單地說是工廠的工廠,抽象工廠可以創建具體工廠,由具體工廠來產生具體產品
*/
public interface Engine {
void run();
}
class EngineA implements Engine{
@Override
public void run() {
System.out.println("發動機轉速快");
}
}
class EngineB implements Engine {
@Override
public void run() {
System.out.println("發動機轉速慢");
}
}
public interface Chair {
void run();
}
class ChairA implements Chair {
@Override
public void run() {
System.out.println("自動加熱");
}
}
class ChairB implements Chair {
@Override
public void run() {
System.out.println("不能加熱");
}
}
public interface CarFactory {
// 創建發動機
Engine createEngine();
// 創建座椅
Chair createChair();
}
public class JiliFactory implements CarFactory{
@Override
public Engine createEngine() {
return new EngineA();
}
@Override
public Chair createChair() {
return new ChairA();
}
}
簡單工廠、工廠方法、抽象工廠小結
什么是代理模式?
代理模式可以控制對象的訪問之前之后做一些操作,即 AOP
應用場景:
SpringAOP、事物原理、日志打印、權限控制、遠程調用、安全代理
靜態代理
/**
* 由程序員創建或工具生成代理類的源碼,再編譯代理類
* 所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委托類的關系在運行前就確定了
*/
public interface IUserDao {
void save();
}
public class UserDao implements IUserDao {
public void save() {
System.out.println("已經保存數據...");
}
}
代理類
public class UserDaoProxy implements IUserDao {
private IUserDao target;
public UserDaoProxy(IUserDao iuserDao) {
this.target = iuserDao;
}
public void save() {
System.out.println("開啟事物...");
target.save();
System.out.println("提交事物...");
}
}
jdk 動態代理
/**
* 是根據類加載器和接口創建代理類
* 通過實現InvocationHandler接口創建自己的調用處理器
* 通過為Proxy類指定ClassLoader對象和一組interface創建動態代理類
* 通過反射機制獲取動態代理類的構造函數
* 通過構造函數創建代理類實例
* 缺點必須提供接口
*/
public class InvocationHandlerImpl implements InvocationHandler {
// 目標對象
private Object target;
public InvocationHandlerImpl(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開啟事務");
// 返回執行結果
Object invoke = method.invoke(target, args);
System.out.println("提交事務");
return invoke;
}
public static void main(String[] args) {
IUserDao userDao = new UserDaoImpl();
InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(userDao);
// 獲得類加載器
ClassLoader classLoader = userDao.getClass().getClassLoader();
// 獲得接口
Class<?>[] interfaces = userDao.getClass().getInterfaces();
IUserDao o = (IUserDao) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
o.add();
}
}
cglib 動態代理
/**
* 利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理
* 不需要提供接口
*/
public class CglibAutoProxy implements MethodInterceptor {
// 目標對象
private Object target;
public Object getInstance(Object target){
this.target = target;
// 操作字節碼生成虛擬子類
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("開啟事務");
Object invoke = methodProxy.invoke(target, objects);
System.out.println("提交事務");
return invoke;
}
public static void main(String[] args) {
CglibAutoProxy cglibAutoProxy = new CglibAutoProxy();
UserDaoImpl o = (UserDaoImpl) cglibAutoProxy.getInstance(new UserDaoImpl());
o.add();
}
}
CGLIB 動態代理與 JDK 動態區別?
JDK 動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用 InvokeHandler 來處理
而 CGLIB 動態代理是利用 asm 開源包,對代理對象類的 class 文件加載進來,通過修改其字節碼生成子類來處理
Spring 中:
如果目標對象實現了接口,默認情況下會采用 JDK 的動態代理實現 AOP
如果目標對象實現了接口,可以強制使用 CGLIB 實現 AOP
如果目標對象沒有實現了接口,必須采用 CGLIB 庫,spring 會自動在 JDK 動態代理和 CGLIB 之間轉換
JDK 動態代理只能對實現了接口的類生成代理,而不能針對類 。
CGLIB 是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法
因為是繼承,所以該類或方法最好不要聲明成 final ,final 可以阻止繼承和多態
什么是建造者模式?
是將一個復雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
工廠模式提供的是創建單個類的模式,而建造者模式則是將各種產品集中起來管理,用來創建復合對象
建造者模式包含以下幾個角色:
Builder:給出一個抽象接口,以規范產品對象的各個組成成分的建造。這個接口規定要實現復雜對象的哪些部分的創建,并不涉及具體的對象部件的創建
ConcreteBuilder:實現Builder接口,針對不同的商業邏輯,具體化復雜對象的各部分的創建
Director:調用具體建造者來創建復雜對象的各個部分,在指導者中不涉及具體產品的信息,只負責保證對象各部分完整創建或按某種順序創建
Product:要創建的復雜對象
應用場景:
public class Person {
private String head;
private String body;
private String foot;
// 省略get和set
}
public interface PersonBuilder {
void builderHead();
void builderBody();
void builderFoot();
Person builderPerson();
}
public class ManBuilder implements PersonBuilder {
private Person person;
public ManBuilder(){
person = new Person();
}
public void builderHead() {
person.setHead("美國人頭部 鼻子尖、長臉、藍眼睛");
}
public void builderBody() {
person.setBody("美國人 長得比較高、塊頭大");
}
public void builderFoot() {
person.setFoot("美國人 腿長");
}
public Person builderPerson() {
return person;
}
}
public class PersonDirector {
public Person creater(PersonBuilder personBuilder) {
personBuilder.builderHead();
personBuilder.builderBody();
personBuilder.builderFoot();
return personBuilder.builderPerson();
}
public static void main(String[] args) {
PersonDirector personDirector = new PersonDirector();
Person creater = personDirector.creater(new ManBuilder());
System.out.println(creater);
}
}
什么是模板模式?
完成一件事情,有固定的數個步驟,但是每個步驟根據對象的不同,而實現細節不同;就可以在父類中定義一個完成該事情的總方法,按照完成事件需要的步驟去調用其每個步驟的實現方法,每個步驟的具體實現,由子類完成
應用場景:
// 短信模板
public abstract class MsgTemplate {
public void sendMsg() {
addHeadLog();
httpRequest();
addHeadLog();
}
// 開始日志
void addHeadLog() {
System.out.println("調用運營商開始。。。");
}
abstract void httpRequest();
void addFootLog() {
System.out.println("調用運營商結束。。。");
}
}
public class Liantong extends MsgTemplate {
void httpRequest() {
System.out.println("聯通。。。");
}
}
// 具體實現細節
public class Yidong extends MsgTemplate {
void httpRequest() {
System.out.println("移動。。。");
}
}
public class ClientTemplate {
public static void main(String[] args) {
Yidong yidong = new Yidong();
yidong.sendMsg();
}
}
什么是適配器模式
將一個類的接口轉換成客戶希望的另一個接口,適配器模式讓那些接口不兼容的類可以一起工作
應用場景:
public interface JP110VInterface {
void connect();
}
public class JP110VInterfaceImpl implements JP110VInterface {
public void connect() {
System.out.println("日本110V電源接口");
}
}
public interface ZN220VInterface {
public void connect();
}
public class ZN220VInterfaceImpl implements ZN220VInterface {
public void connect() {
System.out.println("中國220V電源接口");
}
}
public class ElectricCooker {
private JP110VInterface jp110VInterface;
public ElectricCooker(JP110VInterface jp110VInterface) {
this.jp110VInterface = jp110VInterface;
}
public void cook(){
jp110VInterface.connect();
System.out.println("開啟做飯");
}
}
public class PowerAdpater implements JP110VInterface {
private ZN220VInterface zn220VInterface;
public PowerAdpater(ZN220VInterface zn220VInterface) {
this.zn220VInterface = zn220VInterface;
}
public void connect() {
zn220VInterface.connect();
}
public static void main(String[] args) {
ZN220VInterface zn220VInterface = new ZN220VInterfaceImpl();
PowerAdpater powerAdpater = new PowerAdpater(zn220VInterface);
ElectricCooker electricCooker = new ElectricCooker(powerAdpater);
electricCooker.cook();
}
}
什么是外觀模式?
外觀模式門面模式,隱藏系統的復雜性,并向客戶端提供了一個客戶端可以訪問系統的接口
應用場景:
// 微信推送消息
public interface WeiXinSmsService {
public void sendSms();
}
public class WeiXinSmsServiceImpl implements WeiXinSmsService{
public void sendSms() {
System.out.println("發送微信消息");
}
}
// 發送郵件
public interface EamilSmsService {
public void sendSms();
}
public class EamilSmsServiceImpl implements EamilSmsService{
@Override
public void sendSms() {
System.out.println("發送郵件消息");
}
}
// 支付寶推送消息
public interface AliSmsService {
public void sendSms();
}
public class AliSmsServiceImpl implements AliSmsService {
@Override
public void sendSms() {
System.out.println("支付寶發送消息...");
}
}
public class Computer {
AliSmsService aliSmsService;
EamilSmsService eamilSmsService;
WeiXinSmsService weiXinSmsService;
public Computer() {
aliSmsService = new AliSmsServiceImpl();
eamilSmsService = new EamilSmsServiceImpl();
weiXinSmsService = new WeiXinSmsServiceImpl();
}
public void sendMsg() {
aliSmsService.sendSms();
eamilSmsService.sendSms();
weiXinSmsService.sendSms();
}
}
public class Client {
public static void main(String[] args) {
new Computer().sendMsg();
}
}
什么是原型模式?
原型模式可以用來克隆對象,被復制的實例就是原型,多用于創建復雜的實例,更節約性能。
應用場景:
淺復制和深復制:
只拷貝基本數據類型的數據,對于引用類型數據,僅復制引用,也就是說原型和復制后的對象共享一個變量,如果引用地址的數據發生改變,那么復制出來的對象也會發生改變,我們成為淺復制
深復制是在內存中開辟一塊空間存放復制對象
public class Book implements Cloneable{
private String title;
private ArrayList<String> listImg = new ArrayList<String>();
public Book() {
super();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getListImg() {
return listImg;
}
public void setListImg(ArrayList<String> listImg) {
this.listImg = listImg;
}
public void addImage(String img) {
this.listImg.add(img);
}
public void showBook() {
System.out.println("----------------start--------------");
System.out.println("title:" + title);
for (String img:listImg) {
System.out.println("img:" + img);
}
System.out.println("-----------------end---------------");
}
@Override
protected Object clone() throws CloneNotSupportedException {
Book book = (Book) super.clone();
book.listImg=(ArrayList<String>)this.listImg.clone();
return book;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Book book = new Book();
book.setTitle("圖書1");
book.addImage("第一章");
book.showBook();
Book book1 = (Book) book.clone();
book1.addImage("第二章");
book1.showBook();
book.showBook();
}
}
什么是策略模式?
定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化
應用場景:
package com.kernel.strategy;
public interface Strategy {
void algorithmInterface();
}
class StrategyA implements Strategy{
public void algorithmInterface() {
System.out.println("級別一處理邏輯");
}
}
class StrategyB implements Strategy{
public void algorithmInterface() {
System.out.println("級別二處理邏輯");
}
}
class StrategyC implements Strategy{
public void algorithmInterface() {
System.out.println("級別三處理邏輯");
}
}
class Context{
private Strategy strategy;
Context(Strategy strategy) {
this.strategy = strategy;
}
void algorithmInterface() {
strategy.algorithmInterface();
}
}
class Client {
public static void main(String[] args) {
Strategy strategyA = new StrategyA();
Context context = new Context(strategyA);
context.algorithmInterface();
context = new Context(new StrategyB());
context.algorithmInterface();
context = new Context(new StrategyC());
context.algorithmInterface();
}
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。