写代码常用到的设计模式

一,装饰者模式

Paste_Image.png

总结:装饰者模式,就是对于父类A(Component),子类 B(ConcreteComponent)和C(Decorator)分别重新A中的方法,B中对方法进行实现,C及其子类可以调用B中实现的方法,也可以进行方法的拓展

二,代理模式

可以查看这篇文章,http://blog.csdn.net/luanlouis/article/details/24589193

https://www.zhihu.com/question/20794107
作者:雨夜偷牛的人
链接:https://www.zhihu.com/question/20794107/answer/23330381
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

最近正好在看,特来挖坟。
关于动态代理设计模式很可能题主就在不知不觉中使用了,例如Spring中的AOP,Struts2中的拦截器等。

先来看静态代理模式代码:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}


package test;

public class TestProxy 
{
   public static void main(String args[])
   {
       Subject sub = new SubjectProxy();
       sub.doSomething();
   }
}

刚开始我会觉得SubjectProxy定义出来纯属多余,直接实例化实现类完成操作不就结了吗?后来随着业务庞大,你就会知道,实现proxy类对真实类的封装对于粒度的控制有着重要的意义。但是静态代理这个模式本身有个大问题,如果类方法数量越来越多的时候,代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题。

先看代码:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  

public class ProxyHandler implements InvocationHandler
{
    private Object tar;

    //绑定委托对象,并返回代理类
    public Object bind(Object tar)
    {
        this.tar = tar;
        //绑定该类实现的所有接口,取得代理类 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    

    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
    {
        Object result = null;
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前,执行功能处理
        result = method.invoke(tar,args);
        //在调用具体函数方法后,执行功能处理
        return result;
    }
}


public class TestProxy
{
    public static void main(String args[])
    {
           ProxyHandler proxy = new ProxyHandler();
           //绑定该类实现的所有接口
           Subject sub = (Subject) proxy.bind(new RealSubject());
           sub.doSomething();
    }
}

看完代码,现在我来回答,动态代理的作用是什么:

  1. Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
  2. 可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
  3. 解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。

三,工厂模式

http://blog.csdn.net/jason0539/article/details/23020989
工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式
简单工厂就是利用factory类创建对象,
抽象工厂是用多个factory创建对象,

四,原型模式

http://blog.csdn.net/sbsujjbcy/article/details/49302717

五,模板方法模式

在Android源码中,View中的Draw()方法就是一个“模板方法”。它定义了一系列“Draw”过程,主要包括这几个步骤(截取自源代码):

    /*
     * Draw traversal performs several drawing steps which must be executed
     * in the appropriate order:
     *
     *      1. Draw the background
     *      2. If necessary, save the canvas' layers to prepare for fading
     *      3. Draw view's content
     *      4. Draw children
     *      5. If necessary, draw the fading edges and restore layers
     *      6. Draw decorations (scrollbars for instance)
     */

在view类的draw()函数中调用了onDraw和dispatchDraw函数,当继承View子类中,如果要重写或者扩展这个方法时,整个方法流程和基本内容不能够修改,子类只能通过扩展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)两个函数,使子类自己的View显示效果和别的具体子类的不同。现在来看看继承自View类的具体子类如何扩展Draw()模板方法显示自己的与众不同:


Paste_Image.png

TextView类中重写了OnDraw函数,SurfaceView重写了dispatchDraw()函数,ViewGroup类重写了dispatchDraw()函数。
根据模版方法中的方法,可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。其中我们这里的例子Draw()函数就是一个“模板方法”。
而基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method):
抽象方法:一个抽象方法由抽象类声明,由具体子类实现。
具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。
钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。我们这里的onDraw()函数就是一个钩子方法。

六,外观模式

就是多了层封装,SDK常用到

七,build模式

建造(Builder)模式是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
在没有运用构造模式之前,我们可能会使用构造方法还设置初始化对象时候的参数,但是有了build模式,就可以通过build来进行选择性的传参并实例化对象。例如,Android常用的第三方请求网络库okhttp,

OkHttpClient client = new OkHttpClient.Builder()
 .connectTimeout(15, TimeUnit.SECONDS)
 .readTimeout(15, TimeUnit.SECONDS)
 .build();

OkHttpClient类中该方法如下,

public Builder() {
 dispatcher = new Dispatcher();
 protocols = DEFAULT_PROTOCOLS;
 connectionSpecs = DEFAULT_CONNECTION_SPECS;
 proxySelector = ProxySelector.getDefault();
 cookieJar = CookieJar.NO_COOKIES;
 socketFactory = SocketFactory.getDefault();
 hostnameVerifier = OkHostnameVerifier.INSTANCE;
 certificatePinner = CertificatePinner.DEFAULT;
 proxyAuthenticator = Authenticator.NONE;
 authenticator = Authenticator.NONE;
 connectionPool = new ConnectionPool();
 dns = Dns.SYSTEM;
 followSslRedirects = true;
 followRedirects = true;
 retryOnConnectionFailure = true;
 connectTimeout = 10_000;
 readTimeout = 10_000;
 writeTimeout = 10_000;
}

八 ,观察者模式

观察者模式的底层其实是回调,Java中一般可以继承Observable 和Observer来实现被观察者和观察者,在安卓中,更是运用大量的观察者模式,例如,BaseAdapter关联了一个DataSetObservable对象,并实现registerDataSetObserver和unregisterDataSetObserver两个方法实现注册和撤销Observer,方法notifyDataSetChanged间接调用Observer的实现者的onChange()方法,以达到通知数据改变的作用。使用ListView和BaseAdapter组合时,当BaseAdapter的item改变时,我们经常会调用notifyDataSetChanged(),通知Listview刷新。

public abstract class DataSetObserver {
 /**
 * This method is called when the entire data set has changed,
 * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
 */
 public void onChanged() {
 // Do nothing
 }

 /**
 * This method is called when the entire data becomes invalid,
 * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
 * {@link Cursor}.
 */
 public void onInvalidated() {
 // Do nothing
 }
}
public abstract class Observable {
 /**
 * The list of observers. An observer can be in the list at most
 * once and will never be null.
 */
 protected final ArrayList mObservers = new ArrayList();

 /**
 * Adds an observer to the list. The observer cannot be null and it must not already
 * be registered.
 * @param observer the observer to register
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is already registered
 */
 public void registerObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 if (mObservers.contains(observer)) {
 throw new IllegalStateException("Observer " + observer + " is already registered.");
 }
 mObservers.add(observer);
 }
 }

 /**
 * Removes a previously registered observer. The observer must not be null and it
 * must already have been registered.
 * @param observer the observer to unregister
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is not yet registered
 */
 public void unregisterObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 int index = mObservers.indexOf(observer);
 if (index == -1) {
 throw new IllegalStateException("Observer " + observer + " was not registered.");
 }
 mObservers.remove(index);
 }
 }

 /**
 * Remove all registered observers.
 */
 public void unregisterAll() {
 synchronized(mObservers) {
 mObservers.clear();
 }
 }
}

可以看出,观察者并不一定要继承JDK中的Observable 和Observer。

你可能感兴趣的:(写代码常用到的设计模式)