Java常用设计模式学习笔记

作为一名Java开发者,了解并学习一些常用的设计模式是很有必要的,不常用的就可以先不管它了,要用到的时候再去了解,现在学习了解一下常用的几种设计模式,单例模式、工厂模式、建造模式、适配器模式、代理模式、观察者模式

一、单例模式

单例模式的主要目的是使内存中始终保持一个对象,Demo如下:

 

public class Singleton {
	
	//将自身的实例对象设置为一个属性,并加上Static和final修饰符
	private static final Singleton instance = new Singleton();

	//将构造方法设置成私有形式
	private Singleton() {
		
	}

	//通过一个静态方法向外界提供这个类的实例
	public static Singleton getInstance() {
		return instance;
	}
}

这样每次都使用Singleton.getInstance()方法来获得一个对象,内存中始终就保持着一个对象,这就是单例模式。

 

 

二、工厂模式

工厂模式主要目的是统一提供实例对象的引用,Demo如下:

 

public class Factory {
	public ClassesDao getClassesDao() {
		ClassesDao cd = new ClassesDaoImpl();
		return cd;
	}
}

interface ClassesDao {
	public String getClassesName();
}

class ClassesDaoImpl implements ClassesDao {
	public String getClassesName() {
		System.out.println("A班");
	}
}

class test {
	public static void main(String[] args) {
		Factory f = new Factory();
		f.getClassesDao().getClassesName();
	}
}

这样子,使用工厂来获得对象实例的引用,即每次都使用f.getClassesDao()获得对象实例的引用。

 

 

三、建造模式

 

将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。

public interface Builder {
	// 创建部件A 比如创建汽车车轮
	void buildPartA();

	// 创建部件B 比如创建汽车方向盘 
	void buildPartB();
	// 创建部件C 比如创建汽车发动机
	void buildPartC();
	// 返回最后组装成品结果 (返回最后装配好的汽车)
	// 成品的组装过程不在这里进行,而是转移到下面的Director类别中进行。
	// 从而实现了解耦过程和部件
	Product getResult();
}

public class Director {
	private Builder builder;

	public Director( Builder builder ) {      
		this.builder = builder;   
	}

	// 将部件partA partB partC最后组成复杂对象
	// 这里是将车轮 方向盘和发动机组装成汽车的过程
	public void construct() {
		builder.buildPartA();
		builder.buildPartB();
		builder.buildPartC();
	}
}}

这样就将产品的内部表象和产品的生成过程分割开了,从而使一个建造过程生成具有不同的内部表象的产品对象。

 

四、适配器模式

把一个类的接口变换为客户端所期待的另一种接口,从而使原本因接口不匹配造成无法一起工作的两个雷可以一起工作,适配器可以根据参数返还一个合适的实例给客户端。

 

public interface IRoundPeg {
	public void insertIntoHole(String msg);
}

public interface ISquarePeg {
	public void insert(String str);
}

public class PegAdapter implements IRoundPeg, ISquarePeg {
	private RoundPeg roundPeg;
	private SquarePeg squarePeg;

	// 构造方法
	public PegAdapter(RoundPeg peg) {
		this.roundPeg = peg;
	}

	// 构造方法
	public PegAdapter(SquarePeg peg) {
		this.squarePeg = peg;
	}

	public void insert(String str) {
		roundPeg.insertIntoHole(str);
	}

	public void insertIntoHole(String str) {
		SquarePeg.insert(str);
	}
}

这样就可以根据参数来返还IRoundPeg或者是ISquarePeg实例给客户端了。

 

五、代理模式

代理模式有两种实现方式,一种是静态代理,另一种是动态代理,各大框架都喜欢用动态代理。

静态代理

 

public interface Subject {
    void visit();
}
//实现Subject接口的两个类
public class RealSubject implements Subject {

    private String name = "byhieg";
    @Override
    public void visit() {
        System.out.println(name);
    }
}

public class ProxySubject implements Subject{

    private Subject subject;

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void visit() {
        subject.visit();
    }
}

//然后如下方式调用
public class Client {

    public static void main(String[] args) {
        ProxySubject subject = new ProxySubject(new RealSubject());
        subject.visit();
    }
}

通过上面的代理代码,我们可以看出代理模式的特点,代理类接受一个Subject接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,如果接口增加方法,则代理类也必须跟着修改。其次,代理类每一个接口对象对应一个委托对象,如果委托对象非常多,则静态代理类就非常臃肿,难以胜任。

 

 

 

 

 

动态代理

动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题。动态代理是实现方式,是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy,通过固定的规则生成。

接上面代码

 

public class DynamicProxy implements InvocationHandler {
    private Object object;
    public DynamicProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        return result;
    }
}

然后创建动态代理对象

 

 

Subject realSubject = new RealSubject();
DynamicProxy proxy = new DynamicProxy(realSubject);
ClassLoader classLoader = realSubject.getClass().getClassLoader();
Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new  Class[]{Subject.class}, proxy);
subject.visit();

 


六、观察者模式

 

 

 

观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明:

    报社方负责出版报纸.

    你订阅了该报社的报纸,那么只要报社发布了新报纸,就会通知你,或发到你手上.

    如果你不想再读报纸,可以取消订阅,这样,报社发布了新报纸就不会再通知你.

  理解其实以上的概念,就可以理解观察者模式,观察者模式中有主题(Subject)和观察者(Observer),分别对应报社和订阅用户(你).观察者模式定义了对象之间的一对多的依赖关系,这样,当"一"的一方状态发生变化时,它所依赖的"多"的一方都会收到通知并且自动更新.

 

package com.wang.observer;
//主题接口
 interface Subject {
     //添加观察者
     void addObserver(Observer obj);
     //移除观察者
     void deleteObserver(Observer obj);
     //当主题方法改变时,这个方法被调用,通知所有的观察者
     void notifyObserver();
}
package com.wang.observer;

interface Observer {
    //当主题状态改变时,会将一个String类型字符传入该方法的参数,每个观察者都需要实现该方法
    public void update(String info);
}

 

package com.wang.observer;

import java.util.ArrayList;
import java.util.List;

public class TeacherSubject implements Subject {
    //用来存放和记录观察者
    private List<Observer> observers=new ArrayList<Observer>();
    //记录状态的字符串
    private String info;
    
    @Override
    public void addObserver(Observer obj) {
        observers.add(obj);
    }

    @Override
    public void deleteObserver(Observer obj) {
        int i = observers.indexOf(obj);
        if(i>=0){
            observers.remove(obj);
        }
    }

    @Override
    public void notifyObserver() {
        for(int i=0;i<observers.size();i++){
            Observer o=(Observer)observers.get(i);
            o.update(info);
        }
    }
    //布置作业的方法,在方法最后,需要调用notifyObserver()方法,通知所有观察者更新状态
    public void setHomework(String info){
        this.info=info;
        System.out.println("今天的作业是"+info);
        this.notifyObserver();
    }

}

 

package com.wang.observer;

public class StudentObserver implements Observer {

    //保存一个Subject的引用,以后如果可以想取消订阅,有了这个引用会比较方便
    private TeacherSubject t;
    //学生的姓名,用来标识不同的学生对象
    private String name;
    //构造器用来注册观察者
    public Student(String name,Teacher t) {
        this.name=name;
        this.t = t;
        //每新建一个学生对象,默认添加到观察者的行列
        t.addObserver(this);
    }


    @Override
    public void update(String info) {
        System.out.println(name+"得到作业:"+info);
        
    }

}

测试:

 

 

package com.wang.observer;

public class TestObserver {

    public static void main(String[] args) {
        
        TeacherSubject teacher=new TeacherSubject();
        StudentObserver zhangSan=new StudentObserver("张三", teacher);
        StudentObserver LiSi=new StudentObserver("李四", teacher);
        StudentObserver WangWu=new StudentObserver("王五", teacher);
        
        teacher.setHomework("第二页第六题");
        teacher.setHomework("第三页第七题");
        teacher.setHomework("第五页第八题");
    }
}

打印结果:

 

 

今天的作业是第二页第六题
张三得到作业:第二页第六题
李四得到作业:第二页第六题
王五得到作业:第二页第六题
今天的作业是第三页第七题
张三得到作业:第三页第七题
李四得到作业:第三页第七题
王五得到作业:第三页第七题
今天的作业是第五页第八题
张三得到作业:第五页第八题
李四得到作业:第五页第八题
王五得到作业:第五页第八题

从打印结果看,每当老师布置作业的状态改变,就会通知每一个学生.以上就是一个简单的观察者模式的实现.

推荐大家一个Java的学习网站:Java知识学习网,Java资料下载,Java学习路线图,网址:https://www.java1010.com

 




 

 

 

 

 

 

 

 


 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值