讀完本文,你會有一個最佳的答案。html
Adapter:java
Bridge:
把抽象和實現解藕,因而接口和實現可在徹底獨立開來。程序員
Composite:
讓使用者把單獨的對象和組合對象混用。web
Decorator:
爲一個對象動態的加上一系列的動做,而不須要由於這些動做的不一樣而產生大量的繼承類。這個模式在JDK中幾乎無處不在,因此,下面的列表只是一些典型的。面試
Facade:
用一個簡單的接口包狀一組組件,接口,抽象或是子系統。算法
Flyweight:
有效率地存儲大量的小的對象。spring
Proxy:
用一個簡單的對象來代替一個複雜的對象。sql
Abstract factory:**數據庫
Builder:
主要用來簡化一個複雜的對象的建立。這個模式也能夠用來實現一個 Fluent Interface。編程
Factory:
簡單來講,按照需求返回一個類型的實例。
Prototype:
使用本身的實例建立另外一個實例。有時候,建立一個實例而後再把已有實例的值拷貝過去,是一個很複雜的動做。因此,使用這個模式能夠避免這樣的複雜性。
Singleton:
只容許一個實例。在 Effective Java中建議使用Emun.
Chain of responsibility:
把一個對象在一個連接傳遞直到被處理。在這個鏈上的全部的對象有相同的接口(抽象類)但卻有不一樣的實現。
Command:
把一個或一些命令封裝到一個對象中。
Interpreter:
一個語法解釋器的模式。
Iterator:
提供一種一致的方法來順序遍歷一個容器中的全部元素。
Mediator:
用來減小對象單的直接通信的依賴關係。使用一箇中間類來管理消息的方向。
Memento:
給一個對象的狀態作一個快照。Date類在內部使用了一個long型來作這個快照。
Null Object:
這個模式用來解決若是一個Collection中沒有元素的狀況。
Observer:
容許一個對象向全部的偵聽的對象廣播本身的消息或事件。
State:
這個模式容許你能夠在運行時很容易地根據自身內部的狀態改變對象的行爲。
Strategy:
定義一組算法,並把其封裝到一個對象中。而後在運行時,能夠靈活的使用其中的一個算法。
Template method:
容許子類重載部分父類而不須要徹底重寫。
Visitor:
做用於某個對象羣中各個對象的操做. 它可使你在不改變這些對象自己的狀況下,定義做用於這些對象的新操做.
MVC 模式表明 Model-View-Controller(模型-視圖-控制器) 模式。這種模式用於應用程序的分層開發。
攔截過濾器模式(Intercepting Filter Pattern)用於對應用程序的請求或響應作一些預處理/後處理。定義過濾器,並在把請求傳給實際目標應用程序以前應用在請求上。過濾器能夠作認證/受權/記錄日誌,或者跟蹤請求,而後把請求傳給相應的處理程序。如下是這種設計模式的實體。
咱們將建立 FilterChain、FilterManager、Target、Client 做爲表示實體的各類對象。AuthenticationFilter 和 DebugFilter 表示實體過濾器。
InterceptingFilterDemo,咱們的演示類使用 Client 來演示攔截過濾器設計模式。
建立過濾器接口 Filter。
Filter.java
public interface Filter { void execute(String request); } 12345
建立實體過濾器。
AuthenticationFilter.java
public class AuthenticationFilter implements Filter { @Override public void execute(String request){ System.out.println("Authenticating request: " + request); } }
DebugFilter.java
public class DebugFilter implements Filter { @Override public void execute(String request){ System.out.println("request log: " + request); } }
建立 Target。
Target.java
*/ public class Target { public void execute(String request){ System.out.println("Executing request: " + request); } }
建立過濾器鏈。
FilterChain.java
public class FilterChain { private List<Filter> filters = new ArrayList(); private Target target; public void addFilter(Filter filter){ filters.add(filter); } public void execute(String request){ for (Filter filter : filters) { filter.execute(request); } target.execute(request); } public void setTarget(Target target){ this.target = target; } }
建立過濾管理器。
FilterManager.java
public class FilterManager { FilterChain filterChain; public FilterManager(Target target){ filterChain = new FilterChain(); filterChain.setTarget(target); } public void setFilter(Filter filter){ filterChain.addFilter(filter); } public void filterRequest(String request){ filterChain.execute(request); } }
建立客戶端 Client。
Client.java
public class Client { FilterManager filterManager; public void setFilterManager(FilterManager filterManager){ this.filterManager = filterManager; } public void sendRequest(String request){ filterManager.filterRequest(request); } }
使用 Client 來演示攔截過濾器設計模式。
InterceptingFilterDemo.java
public class InterceptingFilterPatternDemo { public static void main(String[] args) { FilterManager filterManager = new FilterManager(new Target()); filterManager.setFilter(new AuthenticationFilter()); filterManager.setFilter(new DebugFilter()); Client client = new Client(); client.setFilterManager(filterManager); client.sendRequest("HOME"); } }
驗證輸出。
Authenticating request: HOME request log: HOME Executing request: HOME
優勢:
缺點:
private static boolean flag = false; private Singleton() { if (flag == false) { flag = !flag; } else { throw new RuntimeException("單例模式被侵犯!"); } } public static void main(String[] args) { }
(主要使用懶漢和懶漢式)
package com.lijie; //餓漢式 public class Demo1 { // 類初始化時,會當即加載該對象,線程安全,調用效率高 private static Demo1 demo1 = new Demo1(); private Demo1() { System.out.println("私有Demo1構造參數初始化"); } public static Demo1 getInstance() { return demo1; } public static void main(String[] args) { Demo1 s1 = Demo1.getInstance(); Demo1 s2 = Demo1.getInstance(); System.out.println(s1 == s2); } }
package com.lijie; //懶漢式 public class Demo2 { //類初始化時,不會初始化該對象,真正須要使用的時候纔會建立該對象。 private static Demo2 demo2; private Demo2() { System.out.println("私有Demo2構造參數初始化"); } public synchronized static Demo2 getInstance() { if (demo2 == null) { demo2 = new Demo2(); } return demo2; } public static void main(String[] args) { Demo2 s1 = Demo2.getInstance(); Demo2 s2 = Demo2.getInstance(); System.out.println(s1 == s2); } }
package com.lijie; // 靜態內部類方式 public class Demo3 { private Demo3() { System.out.println("私有Demo3構造參數初始化"); } public static class SingletonClassInstance { private static final Demo3 DEMO_3 = new Demo3(); } // 方法沒有同步 public static Demo3 getInstance() { return SingletonClassInstance.DEMO_3; } public static void main(String[] args) { Demo3 s1 = Demo3.getInstance(); Demo3 s2 = Demo3.getInstance(); System.out.println(s1 == s2); } }
package com.lijie; //使用枚舉實現單例模式 優勢:實現簡單、枚舉自己就是單例,由jvm從根本上提供保障!避免經過反射和反序列化的漏洞 缺點沒有延遲加載 public class Demo4 { public static Demo4 getInstance() { return Demo.INSTANCE.getInstance(); } public static void main(String[] args) { Demo4 s1 = Demo4.getInstance(); Demo4 s2 = Demo4.getInstance(); System.out.println(s1 == s2); } //定義枚舉 private static enum Demo { INSTANCE; // 枚舉元素爲單例 private Demo4 demo4; private Demo() { System.out.println("枚舉Demo私有構造參數"); demo4 = new Demo4(); } public Demo4 getInstance() { return demo4; } } }
package com.lijie; //雙重檢測鎖方式 public class Demo5 { private static Demo5 demo5; private Demo5() { System.out.println("私有Demo4構造參數初始化"); } public static Demo5 getInstance() { if (demo5 == null) { synchronized (Demo5.class) { if (demo5 == null) { demo5 = new Demo5(); } } } return demo5; } public static void main(String[] args) { Demo5 s1 = Demo5.getInstance(); Demo5 s2 = Demo5.getInstance(); System.out.println(s1 == s2); } }
單例模式是 Java 中最簡單的設計模式之一。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。
這種模式涉及到一個單一的類,該類負責建立本身的對象,同時確保只有單個對象被建立。這個類提供了一種訪問其惟一的對象的方式,能夠直接訪問,不須要實例化該類的對象。
注意:
一、單例類只能有一個實例。
二、單例類必須本身建立本身的惟一實例。
三、單例類必須給全部其餘對象提供這一實例。
明肯定義後,看一下代碼:
public class SingletonEH { /** *是否 Lazy 初始化:否 *是否多線程安全:是 *實現難度:易 *描述:這種方式比較經常使用,但容易產生垃圾對象。 *優勢:沒有加鎖,執行效率會提升。 *缺點:類加載時就初始化,浪費內存。 *它基於 classloder 機制避免了多線程的同步問題, * 不過,instance 在類裝載時就實例化,雖然致使類裝載的緣由有不少種, * 在單例模式中大多數都是調用 getInstance 方法, * 可是也不能肯定有其餘的方式(或者其餘的靜態方法)致使類裝載, * 這時候初始化 instance 顯然沒有達到 lazy loading 的效果。 */ private static SingletonEH instance = new SingletonEH(); private SingletonEH (){} public static SingletonEH getInstance() { System.out.println("instance:"+instance); System.out.println("加載餓漢式...."); return instance; } }
餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了。
public class SingletonLH { /** *是否 Lazy 初始化:是 *是否多線程安全:否 *實現難度:易 *描述:這種方式是最基本的實現方式,這種實現最大的問題就是不支持多線程。由於沒有加鎖 synchronized,因此嚴格意義上它並不算單例模式。 *這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工做。 */ private static SingletonLH instance; private SingletonLH (){} public static SingletonLH getInstance() { if (instance == null) { instance = new SingletonLH(); } return instance; } }
而懶漢比較懶,只有當調用getInstance的時候,纔回去初始化這個單例。
一、線程安全:
餓漢式天生就是線程安全的,能夠直接用於多線程而不會出現問題,
懶漢式自己是非線程安全的,爲了實現線程安全有幾種寫法。
例:
public class SingletonLHsyn { /** *是否 Lazy 初始化:是 *是否多線程安全:是 *實現難度:易 *描述:這種方式具有很好的 lazy loading,可以在多線程中很好的工做,可是,效率很低,99% 狀況下不須要同步。 *優勢:第一次調用才初始化,避免內存浪費。 *缺點:必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。 *getInstance() 的性能對應用程序不是很關鍵(該方法使用不太頻繁)。 */ private static SingletonLHsyn instance; private SingletonLHsyn (){} public static synchronized SingletonLHsyn getInstance() { if (instance == null) { instance = new SingletonLHsyn(); } return instance; } }
二、資源加載和性能:
餓漢式在類建立的同時就實例化一個靜態對象出來,無論以後會不會使用這個單例,都會佔據必定的內存,可是相應的,在第一次調用時速度也會更快,由於其資源已經初始化完成。
而懶漢式顧名思義,會延遲加載,在第一次使用該單例的時候纔會實例化對象出來,第一次調用時要作初始化,若是要作的工做比較多,性能上會有些延遲,以後就和餓漢式同樣了。
意圖:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
主要解決:一個全局使用的類頻繁地建立與銷燬。
什麼時候使用:當您想控制實例數目,節省系統資源的時候。
如何解決:判斷系統是否已經有這個單例,若是有則返回,若是沒有則建立。
關鍵代碼:構造函數是私有的。
應用實例:
一、一個黨只能有一個主席。
二、Windows是多進程多線程的,在操做一個文件的時候,就不可避免地出現多個進程或線程同時操做一個文件的現象,因此全部文件的處理必須經過惟一的實例來進行。
三、一些設備管理器經常設計爲單例模式,好比一個電腦有兩臺打印機,在輸出的時候就要處理不能兩臺打印機打印同一個文件。
優勢:
一、在內存裏只有一個實例,減小了內存的開銷,尤爲是頻繁的建立和銷燬實例(好比管理學院首頁頁面緩存)。
二、避免對資源的多重佔用(好比寫文件操做)。
缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。
使用場景:
一、要求生產惟一序列號。
二、WEB 中的計數器,不用每次刷新都在數據庫里加一次,用單例先緩存起來。
三、建立的一個對象須要消耗的資源過多,好比 I/O 與數據庫的鏈接等。 注意事項:getInstance() 方法中須要使用同步鎖,synchronized (Singleton.class) 防止多線程同時進入形成instance 被屢次實例化。
1.Spring IOC
2.爲何Spring IOC要使用工廠設計模式建立Bean呢
簡單工廠 :用來生產同一等級結構中的任意產品。(不支持拓展增長產品) 工廠方法 :用來生產同一等級結構中的固定產品。(支持拓展增長產品) 抽象工廠 :用來生產不一樣產品族的所有產品。(不支持拓展增長產品;支持增長產品族) 123 我下面來使用代碼演示一下:
什麼是簡單工廠模式
代碼演示:
package com.lijie; public interface Car { public void run(); }
package com.lijie; public class Bmw implements Car { public void run() { System.out.println("我是寶馬汽車..."); } }
package com.lijie; public class AoDi implements Car { public void run() { System.out.println("我是奧迪汽車.."); } }
package com.lijie; public class CarFactory { public static Car createCar(String name) { if ("".equals(name)) { return null; } if(name.equals("奧迪")){ return new AoDi(); } if(name.equals("寶馬")){ return new Bmw(); } return null; } }
package com.lijie; public class Client01 { public static void main(String[] args) { Car aodi =CarFactory.createCar("奧迪"); Car bmw =CarFactory.createCar("寶馬"); aodi.run(); bmw.run(); } }
單工廠的優勢/缺點
什麼是工廠方法模式
代碼演示:
package com.lijie; public interface Car { public void run(); }
package com.lijie; public interface CarFactory { Car createCar(); }
package com.lijie; public class AoDi implements Car { public void run() { System.out.println("我是奧迪汽車.."); } }
package com.lijie; public class Bmw implements Car { public void run() { System.out.println("我是寶馬汽車..."); } }
package com.lijie; public class AoDiFactory implements CarFactory { public Car createCar() { return new AoDi(); } }
package com.lijie; public class BmwFactory implements CarFactory { public Car createCar() { return new Bmw(); } }
package com.lijie; public class Client { public static void main(String[] args) { Car aodi = new AoDiFactory().createCar(); Car jili = new BmwFactory().createCar(); aodi.run(); jili.run(); } }
什麼是抽象工廠模式
package com.lijie; //汽車 public interface Car { void run(); } class CarA implements Car{ public void run() { System.out.println("寶馬"); } } class CarB implements Car{ public void run() { System.out.println("摩拜"); } }
package com.lijie; //發動機 public interface Engine { void run(); } class EngineA implements Engine { public void run() { System.out.println("轉的快!"); } } class EngineB implements Engine { public void run() { System.out.println("轉的慢!"); } }
package com.lijie; public interface TotalFactory { // 建立汽車 Car createChair(); // 建立發動機 Engine createEngine(); } //總工廠實現類,由他決定調用哪一個工廠的那個實例 class TotalFactoryReally implements TotalFactory { public Engine createEngine() { return new EngineA(); } public Car createChair() { return new CarA(); } }
package com.lijie; public class Test { public static void main(String[] args) { TotalFactory totalFactory2 = new TotalFactoryReally(); Car car = totalFactory2.createChair(); car.run(); TotalFactory totalFactory = new TotalFactoryReally(); Engine engine = totalFactory.createEngine(); engine.run(); } }
什麼是靜態代理
代碼演示:
package com.lijie; //接口類 public class UserDao{ public void save() { System.out.println("保存數據方法"); } } 12345678 package com.lijie; //運行測試類 public class Test{ public static void main(String[] args) { UserDao userDao = new UserDao(); userDao.save(); } }
修改代碼,添加代理類
package com.lijie; //代理類 public class UserDaoProxy extends UserDao { private UserDao userDao; public UserDaoProxy(UserDao userDao) { this.userDao = userDao; } public void save() { System.out.println("開啓事物..."); userDao.save(); System.out.println("關閉事物..."); } } 1234567891011121314151617 //添加完靜態代理的測試類 public class Test{ public static void main(String[] args) { UserDao userDao = new UserDao(); UserDaoProxy userDaoProxy = new UserDaoProxy(userDao); userDaoProxy.save(); } }
什麼是動態代理
package com.lijie; //接口 public interface UserDao { void save(); } 123456 package com.lijie; //接口實現類 public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存數據方法"); } }
package com.lijie; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; // 每次生成動態代理類對象時,實現了InvocationHandler接口的調用處理器對象 public class InvocationHandlerImpl implements InvocationHandler { // 這其實業務實現類對象,用來調用具體的業務方法 private Object target; // 經過構造函數傳入目標對象 public InvocationHandlerImpl(Object target) { this.target = target; } //動態代理實際運行的代理方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("調用開始處理"); //下面invoke()方法是以反射的方式來建立對象,第一個參數是要建立的對象,第二個是構成方法的參數,由第二個參數來決定建立對象使用哪一個構造方法 Object result = method.invoke(target, args); System.out.println("調用結束處理"); return result; } }
package com.lijie; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { // 被代理對象 UserDao userDaoImpl = new UserDaoImpl(); InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDaoImpl); //類加載器 ClassLoader loader = userDaoImpl.getClass().getClassLoader(); Class<?>[] interfaces = userDaoImpl.getClass().getInterfaces(); // 主要裝載器、一組接口及調用處理動態代理實例 UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl); newProxyInstance.save(); } }
CGLIB動態代理原理:
什麼是CGLIB動態代理
代碼演示:
package com.lijie; //接口 public interface UserDao { void save(); } 123456 package com.lijie; //接口實現類 public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存數據方法"); } } 12345678 package com.lijie; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; //代理主要類 public class CglibProxy implements MethodInterceptor { private Object targetObject; // 這裏的目標類型爲Object,則能夠接受任意一種參數做爲被代理類,實現了動態代理 public Object getInstance(Object target) { // 設置須要建立子類的類 this.targetObject = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } //代理實際方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("開啓事物"); Object result = proxy.invoke(targetObject, args); System.out.println("關閉事物"); // 返回代理對象 return result; } } 123456789101112131415161718192021222324252627282930 package com.lijie; //測試CGLIB動態代理 public class Test { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl()); userDao.save(); } }
建造者模式一般包括下面幾個角色:
使用場景:
package com.lijie; //裝備類 public class Arms { //頭盔 private String helmet; //鎧甲 private String armor; //武器 private String weapon; //省略Git和Set方法........... }
package com.lijie; public interface PersonBuilder { void builderHelmetMurder(); void builderArmorMurder(); void builderWeaponMurder(); void builderHelmetYanLong(); void builderArmorYanLong(); void builderWeaponYanLong(); Arms BuilderArms(); //組裝 }
package com.lijie; public class ArmsBuilder implements PersonBuilder { private Arms arms; //建立一個Arms實例,用於調用set方法 public ArmsBuilder() { arms = new Arms(); } public void builderHelmetMurder() { arms.setHelmet("奪命頭盔"); } public void builderArmorMurder() { arms.setArmor("奪命鎧甲"); } public void builderWeaponMurder() { arms.setWeapon("奪命寶刀"); } public void builderHelmetYanLong() { arms.setHelmet("炎龍頭盔"); } public void builderArmorYanLong() { arms.setArmor("炎龍鎧甲"); } public void builderWeaponYanLong() { arms.setWeapon("炎龍寶刀"); } public Arms BuilderArms() { return arms; } }
package com.lijie; public class PersonDirector { //組裝 public Arms constructPerson(PersonBuilder pb) { pb.builderHelmetYanLong(); pb.builderArmorMurder(); pb.builderWeaponMurder(); return pb.BuilderArms(); } //這裏進行測試 public static void main(String[] args) { PersonDirector pb = new PersonDirector(); Arms arms = pb.constructPerson(new ArmsBuilder()); System.out.println(arms.getHelmet()); System.out.println(arms.getArmor()); System.out.println(arms.getWeapon()); } }
例如:
package com.lijie; //模板方法 public abstract class RestaurantTemplate { // 1.看菜單 public void menu() { System.out.println("看菜單"); } // 2.點菜業務 abstract void spotMenu(); // 3.吃飯業務 public void havingDinner(){ System.out.println("吃飯"); } // 3.付款業務 abstract void payment(); // 3.走人 public void GoR() { System.out.println("走人"); } //模板通用結構 public void process(){ menu(); spotMenu(); havingDinner(); payment(); GoR(); } }
package com.lijie; public class RestaurantGinsengImpl extends RestaurantTemplate { void spotMenu() { System.out.println("人蔘"); } void payment() { System.out.println("5快"); } }
package com.lijie; public class RestaurantLobsterImpl extends RestaurantTemplate { void spotMenu() { System.out.println("龍蝦"); } void payment() { System.out.println("50塊"); } }
package com.lijie; public class Client { public static void main(String[] args) { //調用第一個模板實例 RestaurantTemplate restaurantTemplate = new RestaurantGinsengImpl(); restaurantTemplate.process(); } }
package com.lijie; //阿里短信消息 public interface AliSmsService { void sendSms(); } 123456 package com.lijie; public class AliSmsServiceImpl implements AliSmsService { public void sendSms() { System.out.println("阿里短信消息"); } }
package com.lijie; //發送郵件消息 public interface EamilSmsService { void sendSms(); } 123456 package com.lijie; public class EamilSmsServiceImpl implements EamilSmsService{ public void sendSms() { System.out.println("發送郵件消息"); } }
package com.lijie; //微信消息推送 public interface WeiXinSmsService { void sendSms(); } 123456 package com.lijie; public class WeiXinSmsServiceImpl implements WeiXinSmsService { public void sendSms() { System.out.println("發送微信消息推送"); } }
package com.lijie; 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(); } }
package com.lijie; public class Client { public static void main(String[] args) { //普通模式須要這樣 AliSmsService aliSmsService = new AliSmsServiceImpl(); EamilSmsService eamilSmsService = new EamilSmsServiceImpl(); WeiXinSmsService weiXinSmsService = new WeiXinSmsServiceImpl(); aliSmsService.sendSms(); eamilSmsService.sendSms(); weiXinSmsService.sendSms(); //利用外觀模式簡化方法 new Computer().sendMsg(); } }
咱們Spring框架中的多例就是使用原型。
package com.lijie; import java.util.ArrayList; public class User implements Cloneable { private String name; private String password; private ArrayList<String> phones; protected User clone() { try { User user = (User) super.clone(); //重點,若是要連帶引用類型一塊兒複製,須要添加底下一條代碼,若是不加就對因而複製了引用地址 user.phones = (ArrayList<String>) this.phones.clone();//設置深複製 return user; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } //省略全部屬性Git Set方法...... }
package com.lijie; import java.util.ArrayList; public class Client { public static void main(String[] args) { //建立User原型對象 User user = new User(); user.setName("李三"); user.setPassword("123456"); ArrayList<String> phones = new ArrayList<>(); phones.add("17674553302"); user.setPhones(phones); //copy一個user對象,而且對象的屬性 User user2 = user.clone(); user2.setPassword("654321"); //查看倆個對象是不是一個 System.out.println(user == user2); //查看屬性內容 System.out.println(user.getName() + " | " + user2.getName()); System.out.println(user.getPassword() + " | " + user2.getPassword()); //查看對於引用類型拷貝 System.out.println(user.getPhones() == user2.getPhones()); } }
//默認引用類型爲淺複製,這是設置了深複製 user.phones = (ArrayList<String>) this.phones.clone();
package com.lijie; //策略模式 定義抽象方法 全部支持公共接口 abstract class PayStrategy { // 支付邏輯方法 abstract void algorithmInterface(); }
package com.lijie; class PayStrategyA extends PayStrategy { void algorithmInterface() { System.out.println("微信支付"); } }
package com.lijie; class PayStrategyB extends PayStrategy { void algorithmInterface() { System.out.println("支付寶支付"); } }
package com.lijie; class PayStrategyC extends PayStrategy { void algorithmInterface() { System.out.println("銀聯支付"); } }
package com.lijie;// 使用上下文維護算法策略 class Context { PayStrategy strategy; public Context(PayStrategy strategy) { this.strategy = strategy; } public void algorithmInterface() { strategy.algorithmInterface(); } }
package com.lijie; class ClientTestStrategy { public static void main(String[] args) { Context context; //使用支付邏輯A context = new Context(new PayStrategyA()); context.algorithmInterface(); //使用支付邏輯B context = new Context(new PayStrategyB()); context.algorithmInterface(); //使用支付邏輯C context = new Context(new PayStrategyC()); context.algorithmInterface(); } }
實現有兩種方式:
package com.lijie; //觀察者的接口,用來存放觀察者共有方法 public interface Observer { // 觀察者方法 void update(int state); }
package com.lijie; // 具體觀察者 public class ObserverImpl implements Observer { // 具體觀察者的屬性 private int myState; public void update(int state) { myState=state; System.out.println("收到消息,myState值改成:"+state); } public int getMyState() { return myState; } }
package com.lijie; import java.util.Vector; //定義主題,以及定義觀察者數組,並實現增、刪及通知操做。 public class Subjecct { //觀察者的存儲集合,不推薦ArrayList,線程不安全, private Vector<Observer> list = new Vector<>(); // 註冊觀察者方法 public void registerObserver(Observer obs) { list.add(obs); } // 刪除觀察者方法 public void removeObserver(Observer obs) { list.remove(obs); } // 通知全部的觀察者更新 public void notifyAllObserver(int state) { for (Observer observer : list) { observer.update(state); } } }
package com.lijie; //具體主題 public class RealObserver extends Subjecct { //被觀察對象的屬性 private int state; public int getState(){ return state; } public void setState(int state){ this.state=state; //主題對象(目標對象)值發生改變 this.notifyAllObserver(state); } }
package com.lijie; public class Client { public static void main(String[] args) { // 目標對象 RealObserver subject = new RealObserver(); // 建立多個觀察者 ObserverImpl obs1 = new ObserverImpl(); ObserverImpl obs2 = new ObserverImpl(); ObserverImpl obs3 = new ObserverImpl(); // 註冊到觀察隊列中 subject.registerObserver(obs1); subject.registerObserver(obs2); subject.registerObserver(obs3); // 改變State狀態 subject.setState(300); System.out.println("obs1觀察者的MyState狀態值爲:"+obs1.getMyState()); System.out.println("obs2觀察者的MyState狀態值爲:"+obs2.getMyState()); System.out.println("obs3觀察者的MyState狀態值爲:"+obs3.getMyState()); // 改變State狀態 subject.setState(400); System.out.println("obs1觀察者的MyState狀態值爲:"+obs1.getMyState()); System.out.println("obs2觀察者的MyState狀態值爲:"+obs2.getMyState()); System.out.println("obs3觀察者的MyState狀態值爲:"+obs3.getMyState()); } }