设计模式初学

设计模式基础

选择恰当的设计模式可以大大提高代码质量,可以说是优秀程序员编程智慧的产物。设计模式巧妙运用java基础知识:

  • 多态:动态绑定
    。。。(待补充,觉得最核心的就是多态)

单例模式

  • 本质:确保类的实例化对象有且仅有一个
  • 应用:配置文件、日志、缓存、线程池等
  • 优点:避免过多占用资源或者数据同步问题
  • 分类

    • 饿汉模式:静态化实例跟随类一同加载,无论是否在外部创建实例
      step1:实例由构造方法创建,故改写构造方法(public -> private)
      确保外部不能随意调用
      step2:创建用于返回的私有静态实例,静态确保了唯一性
      step3:返回实例的getInstance( )方法

    • 懒汉模式:只是声明静态实例,只有当用户获取时才判断并创建实例
      step1:构造方法私有化
      step2:声明类的唯一实例
      step3:获取实例方法

  • 区别
    是否在内部进行实例化


工厂模式

  • 目的:实现对象间的低耦合
  • 特点
    对象的创建由工厂负责
    客户类产品成员面向接口,通过多态获取各工厂的产品
    可以按照需求指定特定工厂来生产产品
  • 技术支持
    反射,class Properties/File.properties
  • 简单工厂模式
    所有的产品均由一个工厂生产,根据客户端要求生产出特定的产品,其缺点就是大大增加了工厂类的负担
class Factory{
    public Product getProduct1(){
        return new Product1();
    }

    public Product getProduct2(){
        return new Product2();
    }
}
  • 抽象工厂模式
    1. 产品:接口派生出各类产品
      eg : class Product1 implements Product
      class Product2 implements Product
    2. 工厂:接口派生出用于生产各类产品的工厂
interface ProductFactory{
    public Product getProduct();
}

class Product1Factory implements ProductFactory{
    @override
    public Product getProduct(){
        return new Product1();
    }
}

class Product1Factory implements ProductFactory{
    @override
    public Product getProduct(){
        return new Product2();
    }
}

3.客户:创建工厂获得产品
eg:Product p = Product1Factory.getProduct( );


观察者模式

  • 使用场景:
    对象间存在依赖关系(理解成星型依赖)当 中心变化时需要其余周围对象及时更新自己。最近学习MQTT协议感觉观察者模式比较适用。

  • 使用方法:
    观察者:

    //更新方法:
    public void update()

    被观察者:

      //维护一个观察者列表
      private List<Watcher> watcherList = new ArrayList<Watcher>(); 
      //添加观察者方法
      public void addWatcher(Watcher watcher);
      //删除观察者方法
      public void delWatcher(Watcher watcher);
      //通知观察者方法
      public void notifyWatchers();
  • 推拉方式
    推方式:被观察者维护一个自己的状态(可以考虑JavaBean),当状态发生改变时主动将状态发送给观察者。适用于被观察者比较复杂,观察者必须获得一些信息的情况。
    拉模式:观察者主动从被观察者处获得状态,只是被观察者需要提供一个状态获取接口。

  • 使用java.util.Observable和java.util.Observer

//源码不多,直接粘过来
public class Observable
{
  private boolean changed = false;
  private Vector<Observer> obs = new Vector();

  public synchronized void addObserver(Observer paramObserver)
  {
    if (paramObserver == null) {
      throw new NullPointerException();
    }
    if (!obs.contains(paramObserver)) {
      obs.addElement(paramObserver);
    }
  }

  public synchronized void deleteObserver(Observer paramObserver)
  {
    obs.removeElement(paramObserver);
  }

  public void notifyObservers()
  {
    notifyObservers(null);
  }

  public void notifyObservers(Object paramObject)
  {
    Object[] arrayOfObject;
    synchronized (this)
    {
      if (!changed) {
        return;
      }
      arrayOfObject = obs.toArray();
      clearChanged();
    }
    for (int i = arrayOfObject.length - 1; i >= 0; i--) {
      ((Observer)arrayOfObject[i]).update(this, paramObject);
    }
  }

  public synchronized void deleteObservers()
  {
    obs.removeAllElements();
  }

  protected synchronized void setChanged()
  {
    changed = true;
  }

  protected synchronized void clearChanged()
  {
    changed = false;
  }

  public synchronized boolean hasChanged()
  {
    return changed;
  }

  public synchronized int countObservers()
  {
    return obs.size();
  }
}

public abstract interface Observer
{
  public abstract void update(Observable paramObservable, Object paramObject);
}

代理模式

代理十分好理解就是代替被代理的对象完成一些行为,类比现实生活中的销售代理,就是为厂家去销售产品,而不是只有厂家直销一种方式。
厂家: 我们映射为被代理对象、真实对象。
销售代理: 我们映射为代理对象,它具有真实对象的行为,即有相同的接口实现。

粗糙例子一个:
厂家授权代理负责产品的销售(实现相同接口)
代理按照厂家吩咐对外有定价(接口中具体实现比厂家更细致)
代理下单,厂家发货(最终仍然使用厂家的接口实现)

/*
 * sell product interface
 */
public interface sellProduct(){
    public void sell();
}
/*
 * factory
 */
public class Factory implements sellProduct{
    @Override
    public void sell(){
        System.out.println("sell a product");
    }
}
/*
 * proxy
 */
public class Proxy implements sellProduct{

    private double price;

    //real object
    private Factory factory;

    public Factory getFactory() {
        return factory;
    }

    public void setFactory(Factory factory) {
        this.factory = factory;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public void sell(){
        if(price >= 9999)
            factory.sell();
        else if(price > 0 && price < 9999)
            System.out.println("cannot afford");
        else
            System.out.println("don't joke me");
    }
}
/*
 * deal
 */
public static void main(Stirng[] args){
    Proxy proxy = new Proxy();
    Factory factory = new Factory();
    proxy.setFactory(factory);
    proxy.setPrice(9999);
    proxy.sell();
}

动态代理模式

在代理模式的基础之上运用反射技术。
当前常用的动态代理模式是JDK动态代理CGLIB动态代理

JDK使用过程很简便:

  • 实现java.lang.reflect.InvocationHandler
  • 建立代理对象和真实对象之间的关系
    private real object;
    bind( );
  • 实现代理逻辑方法:
    invoke( );

简单粗糙例子一个,只列出以上三步:

public class JDKProxy implements InvocationHandler {
    // real object
    private Object target;

    /*
     * step1: create relation between proxy object and real object
     * 
     * @param real object
     * 
     * @return proxy object
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    /*
     * step2: proxy method
     * @param proxy object
     * @param method
     * @param arguments
     * @return proxy result
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        System.out.println("enter into proxy logical method");
        System.out.println("before invoke real object");
        Object obj = method.invoke(target, args);
        System.out.println("after invoke real object");
        return obj;
    }   
}

CGLIG动态代理
与JDK类似但是不同之处在于JDK代理的类必须实现接口,而CGLIB则是通过生成被代理类的子类,通过增强方法覆盖父类方法

  • 增强方法获得被代理对象,以被代理类为父类。
  • 实现代理逻辑方法

简单粗糙例子

public class CGLIBProxy implements MethodInterceptor {
    public Object getProxy(Class realObject) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(realObject);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /*
     * implements logical proxy method
     * 
     * @param proxy object
     * 
     * @param method????
     * 
     * @param method arguements
     * 
     * @param proxy method
     * 
     * @return result
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before call real object");
        Object result = methodProxy.invokeSuper(proxy, args);
        System.out.println("after call real object");
        return result;
    }
}

适配器模式

实践出真知,经历的积累就会形成一个人阅历,对待事物有不同深度的理解。
对适配器模式的学习理解,恰恰经历了马哲辩证法中知识与实践相互促进的过程(扯远了)

  • 初识:适配器模式就像是视频线转换口,笔记本上只有HDMI口,而显示器只有VGA口,现在没有可以直接相连的线。所以需要淘一个东西把VGA的口“改造”一下,让笔记本以为显示器就是提供的HDMI插口,于是连接工作。
  • 验证:初识只是举了一个形象的例子,算是将抽象的概念简单的形象化一下。实践中,才深刻体会到适配器模式的意义。
    IC卡表向web应用迁移,将原有的MFC客户端的工作迁移到浏览器上,使用的仍然是厂家提供的操作库——原已有接口
    浏览器通过ActiveX调用底层接口,ActiveX采用ATL开发生成dll,在该dll中调用库接口实现对外的接口——适配后目标接口
    用户可以使用JS直接引入ActiveX,并使用新接口
  • 强化初识认知,适配器模式两大要点
    1. 用已有接口实现
    2. 实现适配接口

装饰器模式

和适配器模式类似,区别在于适配器模式按照需要改造接口,而装饰器模式保留接口原貌但是功能进行增强。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值