设计模式

表示关系的UML标记

24种设计模式

  1. 代理模式
    在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。
    这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类。
  2. 优点
    隐藏委托类的实现
    解耦,不改变委托类代码的情况下做一些额外处理,比如添加初始判断及其他公共操作
    根据程序运行前代理类是否已经存在,可以将代理分为静态代理和动态代理。
    代理类在程序运行前已存在的代理方式称为静态代理。
    代理类在程序运行前未存在的代理、运行时由程序动态生成的代理方式称为动态代理。

  3. 静态代理
    由开发人员编写或是编译器生成代理类的方式属于静态代理。

  4. 动态代理
    三步骤:
    1.新建委托类
    public interface Operate {

    public void operateMethod1();
    
    public void operateMethod2();
    
    public void operateMethod3();
    

    }

    public class OperateImpl implements Operate {

    @Override
    public void operateMethod1() {
        System.out.println("Invoke operateMethod1");
        sleep(110);
    }
    
    @Override
    public void operateMethod2() {
        System.out.println("Invoke operateMethod2");
        sleep(120);
    }
    
    @Override
    public void operateMethod3() {
        System.out.println("Invoke operateMethod3");
        sleep(130);
    }
    
    private static void sleep(long millSeconds) {
        try {
            Thread.sleep(millSeconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    }
    2.实现InvocationHandler接口,这是负责连接代理类与委托类的中间类必须实现的接口
    public class TimingInvocationHandler implements InvocationHandler {

    private Object target;
    
    public TimingInvocationHandler() {}
    
    public TimingInvocationHandler(Object target) {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        Object obj = method.invoke(target, args);
        System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));
        return obj;
    }
    

    }

3.通过Proxy类新建代理类对象
    public class Main {
        public static void main(String[] args) {
            // create proxy instance
            TimingInvocationHandler timingInvocationHandler = new         TimingInvocationHandler(new OperateImpl());
 Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class},timingInvocationHandler));
            // call method of proxy instance
            operate.operateMethod1();
            System.out.println();
            operate.operateMethod2();
            System.out.println();
            operate.operateMethod3();
        }
    }
  1. 应用场景
    作用:目标函数值之间的耦合
    比如在 Dao 中,每次数据库操作都需要开启事务,而且在操作的时候需要关注权限。一般写法是在 Dao 的每个函数中添加相应逻辑,造成代码冗余,耦合度高。
    使用动态代理前伪代码如下:

    Dao {
    insert() {
        判断是否有保存的权限;
        开启事务;
        插入;
        提交事务;
    }
    
    delete() {
        判断是否有删除的权限;
        开启事务;
        删除;
        提交事务;
    }
    

    }
    使用动态代理的伪代码如下:
    使用动态代理,组合每个切面的函数,而每个切面只需要关注自己的逻辑就行,达到减少代码,松耦合的效果

invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
        判断是否有权限;
        开启事务;
        Object ob = method.invoke(dao, args);
        提交事务;
        return ob; 
    }

6.基于 REST 的 Android 端网络请求框架 Retrofit
作用:简化网络请求操作。
一般情况下每个网络请求我们都需要调用一次HttpURLConnection或者HttpClient进行请求,或者像 Volley 一样丢进等待队列中,Retrofit 极大程度简化了这些操作,示例代码如下:

   public interface GitHubService {
      @GET("/users/{user}/repos")
      List<Repo> listRepos(@Path("user") String user);
    }
    RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint("https://api.github.com").build();
GitHubService service = restAdapter.create(GitHubService.class);
 以后我们只需要直接调用
List<Repo> repos = service.listRepos("octocat");

设计模式汇总