1.適配器模式
定義:是兩個不兼容的接口之間的橋樑,例如讀卡器可以讓筆記本電腦讀取內存卡里的內容,這裏的讀卡器就是一個橋樑。
代碼示例(美國電器電壓110V,中國220V,把110V轉爲220V)
public interface AmericaVoltage {
public String voltage110();
}
public interface ChinaVoltage {
public String voltage220();
}
public class OutputVoltage implements ChinaVoltage{
@Override
public String voltage220() {
return "輸出220V電壓";
}
}
public class VoltageAdapter implements AmericaVoltage{
private ChinaVoltage chinaVoltage;
public VoltageAdapter(ChinaVoltage chinaVoltage){
this.chinaVoltage = chinaVoltage;
}
@Override
public String voltage110() {
return chinaVoltage.voltage220();
}
}
測試:
public class AdapterTest {
public static void main(String []args){
AmericaVoltage americaVoltage = new VoltageAdapter(new OutputVoltage());
System.out.println(americaVoltage.voltage110());
}
}
結果:
適配器模式不適合在詳細設計設計階段使用,它是一種補償模式,用於在系統後期的擴展,修改時使用。
過多的使用適配器會讓系統非常凌亂,不易整體進行把握。
2.代理模式
定義:爲對象提供一種代理來控制對這個對象的訪問(目的是控制)。
靜態代理:是在程序運行前就存在代理類的字節碼文件,代理類和委託類的關係在運行前就已經確定了。
代理對象和真實對象都有一個共同的接口,代理對象中含有對真實對象的引用。
假設我現在有一個類,我想要在這個類中每個public方法真正執行數據庫操作前先查詢緩存,這時候除了修改原始的類之外的方式就是我可以寫個代理類來替代它,這樣符合開閉原理。
示例:
public interface UserDao {
public String getUserById(String id);
public void updateUser(String user);
}
public class UserDaoImpl implements UserDao {
UserDaoImpl(){
System.out.println("對象被創建了");
}
@Override
public String getUserById(String id) {
return "用戶"+id+"的信息爲。。。。。。";
}
@Override
public void updateUser(String user) {
System.out.println("數據庫更新用戶信息:"+user);
}
}
public class UserDaoImplProxy implements UserDao {
private UserDao userDaoImpl;
@Override
public String getUserById(String id) {
System.out.println("查找之前輸出ID:"+id);
if (userDaoImpl == null){
userDaoImpl = new UserDaoImpl();
}
String result = userDaoImpl.getUserById(id);
System.out.println("查找之後輸出記錄:"+result);
return result;
}
@Override
public void updateUser(String user) {
System.out.println("更新之前輸出:"+user);
if (userDaoImpl == null){
userDaoImpl = new UserDaoImpl();
}
userDaoImpl.updateUser(user);
}
}
測試:
public class ProxyTest {
public static void main(String[] args){
UserDao userDaoImplProxy = new UserDaoImplProxy();
userDaoImplProxy.getUserById("1");
userDaoImplProxy.updateUser("{id:1,name:junjun,age:27}");
}
}
結果:
動態代理:是在程序運行期間由JVM根據反射機制動態生成的,不存在代理類的字節碼文件,代理角色和真實角色是在程序運行期間確定的(spring的aop)。
示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class UserHandler implements InvocationHandler {
private UserDao userDaoImpl;
public UserHandler(UserDao userDaoImpl){
this.userDaoImpl = userDaoImpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
System.out.println("我要開始調用方法了");
if (method.getName().equals("updateUser")){
object = method.invoke(userDaoImpl,args);
}else {
System.out.println("被攔截了,方法不能執行了:"+method.getName());
}
System.out.println("方法執行結束了");
return object;
}
}
測試:
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args){
UserHandler userHandler = new UserHandler(new UserDaoImpl());
UserDao userProxy = (UserDao) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{UserDao.class},userHandler);
userProxy.updateUser("{id:1,name:junjun,age:27}");
userProxy.getUserById("1");
}
}
結果: