设计模式
设计模式
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();
}