设计模式

设计模式

1、介绍

GOF是Gang of four(四人帮)的简称,是由四位java业界的专家编写的针对特定场景下问题的专家级解决方案。大概包含23中设计模式,设计模式本身与技术没有太大关系,主要是设计思想的运用,比较著名的像单例模式、工厂模式等。本文不打算给出所有设计模式的说明,主要给出实际应用较普遍的几种且比较经典的设计模式。

2、单例模式

单例模式是最经典的设计模式之一,原则是确保类在运行时有且只有一个实例。核心思想是构造私有,通过静态方法访问唯一实例,切要考虑线程安全问题。单例模式分为饿汉式和懒汉式两种实现。

  • 懒汉式

    package com.oldboy.java.gof.singleton;
    
    /**
     * 回收站
     */
    public class Trash {
      //静态指向自身的引用
      private static Trash instance ;
    
      //懒汉式
      public static Trash getInstance(){
        if(instance != null){
          return instance ;
        }
        //安全性控制
        synchronized (Trash.class){
          //需要增加该项控制
          if(instance == null){
            instance = new Trash() ;
          }
        }
        return instance ;
      }
      //构造私有
      private Trash(){
      }
    
      public static void main(String[] args) {
        //多线程场景实现
        new Thread() {
          public void run() {
            Trash t = Trash.getInstance();
            System.out.println(t);
          }
        }.start();
        new Thread() {
          public void run() {
            Trash t = Trash.getInstance();
            System.out.println(t);
          }
        }.start();
      }
    }
    

  • 饿汉式

    饿汉式比较简单,相比较懒汉式更加具有安全性,因为实在类加载时进行对象的创建,不会涉及并发问题。

    package com.oldboy.java.gof.singleton;
    
    /**
     * 回收站
     */
    public class Trash {
    	//静态指向自身的引用
    	private static Trash instance = new Trash();
    
    	//
    	public static Trash getInstance(){
    		return instance ;
    	}
    
    	private Trash(){
    	}
    
    	public static void main(String[] args) {
          	//多线程场景实现
    		new Thread() {
    			public void run() {
    				Trash t = Trash.getInstance();
    				System.out.println(t);
    			}
    		}.start();
    		new Thread() {
    			public void run() {
    				Trash t = Trash.getInstance();
    				System.out.println(t);
    			}
    		}.start();
    	}
    }
    

3、工厂模式

工厂模式也是使用较多的设计模式之一,有静态工厂和非静态工厂的分区。

  • 静态工厂

    package com.oldboy.java.gof.factory;
    public class Factory1 {
    	/**
    	 * 静态工厂
    	 */
    	public static TVSet newTVSet(){
    		TVSet tv = new TVSet();
    		tv.setBrand("SkyWorth");
    		tv.setColor("red");
    		tv.setSize(120);
    		return tv ;
    	}
    }
    

  • 非静态工厂

    package com.oldboy.java.gof.factory;
    /**
     * 非静态工厂
     */
    public class Factory2 {
    
    	/**
    	 * 非静态工厂
    	 */
    	public TVSet newTVSet(){
    		TVSet tv = new TVSet();
    		tv.setBrand("SkyWorth");
    		tv.setColor("red");
    		tv.setSize(120);
    		return tv ;
    	}
    }
    

4、Builder模式

builder模式我们称为构建器模式,通过方法方式编程,本质上是突破了标准的javabean规范。

package com.oldboy.java.gof.builder;

/**
 * 电脑
 */
public class Computer {
	private String cpu;
	private String memory ;
	private String hardDisk ;

	public String getCpu() {
		return cpu;
	}

	public void setCpu(String cpu) {
		this.cpu = cpu;
	}

	public String getMemory() {
		return memory;
	}

	public void setMemory(String memory) {
		this.memory = memory;
	}

	public String getHardDisk() {
		return hardDisk;
	}

	public void setHardDisk(String hardDisk) {
		this.hardDisk = hardDisk;
	}

	/**
	 * 内部构建器
	 */
	public static class Builder{
		private Computer computer = new Computer() ;

		public Builder setCpu(String cpu){
			computer.setCpu(cpu);
			return this ;
		}
		public Builder setMemory(String mem){
			computer.setMemory(mem);
			return this ;
		}
		public Builder setHardDisk(String disk){
			computer.setHardDisk(disk);
			return this ;
		}

		public Computer build(){
			return computer ;
		}
	}
}

//调用方式
class App {
	public static void main(String[] args) {
      	//链式编程
		Computer c = new Computer.Builder()
							 .setCpu("intel")
							 .setMemory("sanxing")
							 .setHardDisk("xishu")
							 .build();

	}
}

5、适配器模式

适配器模式主要针对接口的情况下,进行预实现,具体使用时就不需要对所有方法进行实现了。比较典型的swing中的WindowAdpator。

package java.awt.event;

/**
 * 窗口适配器
 */
public abstract class WindowAdapter
  implements WindowListener, WindowStateListener, WindowFocusListener
{
    public void windowOpened(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {}
    public void windowGainedFocus(WindowEvent e) {}
    public void windowLostFocus(WindowEvent e) {}
}

public class App {
	public static void main(String[] args) {
		JFrame f = new JFrame() ;
		f.setBounds(0 ,0 , 1366 , 768);
		f.setTitle("标题栏");
		//适配器模式应用
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(-1);
			}
		});

		f.setVisible(true);
	}
}

5、装饰模式

装饰模式比较典型的是java中的IO流,缓冲区流、压缩流都是装饰模式的体现。即在原有组件的功能基础上,增加或增强部分功能。java IO中装饰模式的根类是FilterInputStream。装饰模式的设计原则是:

class A{
  public void aa(){
  	..
  }
}

class WrappedA extends A{
  private A a ;
  public WrappedA(A a){
  	this.a = a ;
  }
  
  public void aa(){
  	..
    a.aa() ;
    ..
  }
}

FilterInputStream的类如下:

public
  class FilterInputStream extends InputStream {
    protected volatile InputStream in;
    protected FilterInputStream(InputStream in) {
      this.in = in;
    }

    public int read() throws IOException {
      return in.read();
    }
    ...
  }

6、观察者模式

观察者模式jdk给出的固定编程场景,当某个事物发生时,对其进行观察的主体就会做出响应的工作。但要注意观察者模式也成为等待通知模式,不过和多线程中的等待通知模型没有任何关系。警察与小偷的这个行为关系可以比较典型用观察者模式来实现。这里警察是观察者,观察小偷的行为,小偷是被观察者,小偷一旦进行偷窃行为,所有的警察都一拥而上,完成个自己的任务。因此设计的类如下:

/**
 * 小偷,可被观察,因此集成java.util.Observable类。
 */
class Thief extends Observable{
  public void stealOneThing(String thing){
    //
    System.out.println("偷了一个东西 : " + thing);
    //设置改变标记
    setChanged();
    //通知所有观察者
    notifyObservers();
  }
}

/*
 * 警察1-观察者
 */
class Police1 implements Observer{
  public void update(Observable o, Object arg) {
    System.out.println("行动1");
  }
}

/**
 * 警察2-观察者
 */
class Police2 implements Observer {
  public void update(Observable o, Object arg) {
    System.out.println("行动2");
  }
}

class App{
  public static void main(String[] args) {
    //创建被观察者,
    Thief a = new Thief();
    //添加观察者
    a.addObserver(new Police1());
    a.addObserver(new Police2());
	//让小偷开始行动
    a.stealOneThing("iphone 6 plus");
  }
}

7、责任链模式

责任链模式可以理解为流水线上的工人,每个工作做完自己的工作后交给下一个工作继续处理。因此类似于java中链表数据结构的概念。比如生产一辆汽车需要上轮胎、安装发动机、方向盘安装、座椅、喷漆等一序列工作,均有不同的工人完成,就可以采用责任链编程模式。代码如下:

/**
 * 工人抽象类
 */
public abstract class Worker {
  //下一个工人
  private Worker nextWorker ;

  public Worker(){
  }
  public Worker(Worker nextWorker){
    this.nextWorker = nextWorker ;
  }

  public void setNextWorker(Worker nextWorker) {
    this.nextWorker = nextWorker;
  }

  public void work(){
    doWork();
    if(nextWorker != null){
      nextWorker.work();
    }
  }

  public abstract void doWork()  ;
}

/**
 * 轮胎工
 */
public class TireWorker extends Worker{
  public void doWork() {
    System.out.println("上轮胎");
  }
}

/**
 * 上发动机
 */
public class EngineWorker extends Worker{
  public void doWork() {
    System.out.println("上发动机");
  }
}

/**
 * 喷漆工
 */
public class PaintWorker extends Worker{
  public void doWork() {
    System.out.println("喷漆");
  }
}
/**
 * 汽车类
 */
public class Car {
  public void handledBy(Worker worker){
    worker.work();
  }
}

/**
 * App访问方式
 */
class App {
  public static void main(String[] args) {
    TireWorker w1 = new TireWorker();
    EngineWorker w2 = new EngineWorker();
    PaintWorker w3 = new PaintWorker();
    w1.setNextWorker(w2);
    w2.setNextWorker(w3);

    Car car = new Car();
    car.handledBy(w1);
  }
}

8、代理模式

代理模式是通过jdk提供的Proxy类实现的,其能类似于装饰模式,不同之处是可以将装饰模式理解为静态的增强实现,通常是对某些特定功能或某方面固定需求进行的实现,比如缓冲区、压缩等等。代理是一种动态的机制,在内存中动态产生对象对并对其方法进行增强,具有更加强大的功能。例如对方法执行时间进行计时统计,就可以通过代理模式来时先:

/**
 * 接口
 */
static interface WelcomeService{
  public void sayHello() ;
}
/**
 * 实习类
 */
class WelcomeServiceImpl implements WelcomeService{
  public void sayHello() {
    System.out.println("hello world");
  }
}

//主函数
public static void main(String[] args) {
  final WelcomeService ws = new WelcomeServiceImpl() ;
  //处理器
  InvocationHandler h = new InvocationHandler() {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      long start = System.nanoTime() ;
      Object obj = method.invoke(ws , args) ;
      System.out.println("执行耗时 : " + (System.nanoTime() - start));
      return obj;
    }
  } ;
  ClassLoader loader = ClassLoader.getSystemClassLoader() ;
  //创建代理对象
  WelcomeService proxy = (WelcomeService) Proxy.newProxyInstance(loader ,new Class[]{WelcomeService.class} , h);
  proxy.sayHello();
}
posted @ 2018-09-08 11:45  大道至简(老徐)  阅读(346)  评论(0编辑  收藏  举报