解释:在创建对象的同时隐藏创建逻辑,而不是使用new运算符直接实例化对象,使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活
解释:关注类和对象的组合,继承的概念被用来组合接口各定义组合对象获得新功能
解释:关注对象间的通信
责任链模式(Chain of Responsibility Pattern)
命令模式(Command Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
观察者模式(Observer Pattern)
状态模式(State Pattern)
空对象模式(Null Object Pattern)
策略模式(Strategy Pattern)
模板模式(Template Pattern)
访问者模式(Visitor Pattern
懒初始化,不是线程安全的
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒初始化,线程安全、效率很低
第一次调用才会初始化,避免内存浪费
必须加锁synchronized才能保证单例,加锁会影响效率(任时刻,只能有一个线程可以调用这个方法,其余的会排队等待。)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
不是懒初始化,线程安全,但容易产生垃圾对象
没有加锁,效率高
类加载时就初始化,浪费内存
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
public class Singleton {
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
例子:工业革命前,如果一个客户想要一台车,必须自己创造,然后拿来用;工业革命后,用户不需要创建宝马车,工厂完成创建车的过程,且工厂有多个车间,可以根据用户的需求创建不同型号的车。
步骤 1 创建一个接口。
//Shape.java
public interface Shape {
void draw();
}
步骤 2 创建实现接口的实体类。
//Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
步骤 3 创建一个工厂,生成基于给定信息的实体类的对象。
//ShapeFactory.java
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
return null;
}
}
步骤 4
使用该工厂,通过传递类型信息来获取实体类的对象。
//FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象
//Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
//shape2.draw();
}
}
Class.forName(clz.getName()).newInstance()
实现简单工厂模式好处:
增加一种产品时不需要修改Factory中的方法
//步骤3:创建工厂类
public class ShapeFactory {
/**
* 传入Class实例化具体产品类
*/
public static T getShape(Class clz) {
T result = null;
try {
result = (T) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
//步骤 4:
使用该工厂
//FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象
Shape shape1 = shapeFactory.getShape(Circle.class);
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象
Shape shape2 = shapeFactory.getShape(Rectangle.class);
//调用 Rectangle 的 draw 方法
shape2.draw();
}
}
1. 创建一个抽象产品类,Shape接口
2. 创建实现接口的实体类(具体产品)
3. 创建一个抽象工厂类,
4. 创建具体的工厂类,根据给定信息生成特定的实体类对象
步骤 1
创建一个接口。
//Shape.java
public interface Shape {
void draw();
}
步骤 2
创建实现接口的实体类。
//Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
步骤3
创建抽象工厂类,制定每个工厂必须生产出的指标
//AbstractFactory.java
public abstract class AbstractFactory {
abstract Shape getShape(String shapeType) ;
}
步骤 4
创建具体工厂类,生成基于给定信息的实体类的对象。
//ShapeFactory.java
public class ShapeFactory extends AbstractFactory{
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equals("CIRCLE")){
return new Circle();
} else if(shapeType.equals("RECTANGLE")){
return new Rectangle();
}
return null;
}
}
使用该工厂,通过传递类型信息来获取实体类的对象。
//FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args) {
AbstractFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
}
}
当类中的产品构成了不同等级的==产品族==,就使用抽象工厂模式
步骤 1
为形状创建一个接口。
//Shape.java
public interface Shape {
void draw();
}
步骤 2
创建实现接口的实体类。
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
//Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
步骤 3
为颜色创建一个接口。
//Color.java
public interface Color {
void fill();
}
步骤4
创建实现接口的实体类。
//Red.java
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
//Green.java
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
步骤 5
创建抽象工厂类,制定每个工厂必须生产出两个指标:颜色和类型(发动机和空调)。
AbstractFactory.java
public abstract class AbstractFactory {
abstract Color getColor();
abstract Shape getShape() ;
}
步骤 6
具体工厂A类:红色圆形
//FactoryA.java
public class FactoryA extends AbstractFactory {
//一个具体工厂类创建了两个具体产品类
@Override
public Color getColor(){
return new Red();
}
@Override
public Shape getShape(){
return new Circle();
}
}
具体工厂B类:绿色矩形
//FactoryB.java
public class FactoryA extends AbstractFactory {
@Override
public Color getColor(){
return new Green();
}
@Override
public Shape getShape(){
return new Rectangle();
}
}
步骤 8
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
AbstractFactory aFactory = new FactoryA();
aFactory.getShape().draw();
aFactory.getColor().fill();
AbstractFactory bFactory = new FactoryB();
bFactory.getShape().draw();
bFactory.getColor().fill();
}
}
在对象之坚定了一一对多的依赖,当一个对象改变状态(被观察者),依赖它的对象(观察者)就会收到通知并自动更新
1、定义一个抽象被观察者接口
复制代码
package com.jstao.observer;
/***
* 抽象被观察者接口
* 声明了添加、删除、通知观察者方法
* @author jstao
*
*/
public interface Observerable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
2、定义一个抽象观察者接口
package com.jstao.observer;
/***
* 抽象观察者
* 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。
* @author jstao
*
*/
public interface Observer {
public void update(String message);
}
复制代码
3、定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。
复制代码
package com.jstao.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 被观察者,也就是微信公众号服务
* 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现
* @author jstao
*
*/
public class WechatServer implements Observerable {
//注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
private List list;
private String message;
public WechatServer() {
list = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if(!list.isEmpty())
list.remove(o);
}
//遍历
@Override
public void notifyObserver() {
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
}
public void setInfomation(String s) {
this.message = s;
System.out.println("微信服务更新消息: " + s);
//消息更新,通知所有观察者
notifyObserver();
}
}
复制代码
4、定义具体观察者,微信公众号的具体观察者为用户User
复制代码
package com.jstao.observer;
/**
* 观察者
* 实现了update方法
* @author jstao
*
*/
public class User implements Observer {
private String name;
private String message;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到推送消息: " + message);
}
}
复制代码
5、编写一个测试类
首先注册了三个用户,ZhangSan、LiSi、WangWu。公众号发布了一条消息"PHP是世界上最好用的语言!",三个用户都收到了消息。
用户ZhangSan看到消息后颇为震惊,果断取消订阅,这时公众号又推送了一条消息,此时用户ZhangSan已经收不到消息,其他用户
还是正常能收到推送消息。
复制代码
package com.jstao.observer;
public class Test {
public static void main(String[] args) {
WechatServer server = new WechatServer();
Observer userZhang = new User("ZhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的语言!");
System.out.println("----------------------------------------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的语言!");
}
}
含义:提供了对目标对象另外的访问方式:通过代理对象访问目标对象
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理
关键点:代理对象与目标对象,代理对象是对目标对象的扩展,并且会调用目标对象
静态:程序运行前就编译好的,不是由程序动态产生代理类
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象必须实现==相同的接口或者继承相同的父类==,然后通过相同的方法来调用目标对象的方法
保存动作,定义一个保存动作的接口IUserDao.java,目标对象(Target)实现了这个接口,如果使用静态代理,需要在代理对象(ProxyUserDao)中也实现这个接口,调用的时候通过调用代理对象的方法来调用目标对象
/**
* 接口
*/
public interface IUserDao {
void save();
}
/**
* 目标对象
*/
public class Target implements IUserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
/**
* 代理对象,静态代理----实现接口式
*/
public class ProxyUserDao implements IUserDao{
//接收保存目标对象
private IUserDao target;
public ProxyUserDao(IUserDao target){
this.target=target;
}
public void save() {
System.out.println("开始事务...");//对目标对象该方法的扩充部分
target.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
/**
* 测试类---实现接口式
*/
public class App {
public static void main(String[] args) {
//目标对象
Target target = new Target();
//代理对象,把目标对象传给代理对象,建立代理关系(代理对象的构造喊数有参数的)
ProxyUserDao proxy = new ProxyUserDao(target);
proxy.save();//执行的是代理的方法
}
}
继承式
public class ProxyUserDao extenda Target{
//省略构造方法,因为构造函数无参
public void save() {
System.out.println("开始事务...");//对目标对象该方法的扩充部分
super.save();//执行目标对象的方法
System.out.println("提交事务...");
}
}
/**
* 测试类
*/
public class App {
public static void main(String[] args) {
//不需要将目标对象传给代理对象,因为代理对象的构造函数是继承的Target无参的
ProxyUserDao proxy = new ProxyUserDao();
proxy.save();//执行的是代理的方法
}
}
含义:代理对象不需要实现接口,代理对象的生成是利用JDK中的API,动态在内存中构建代理对象
static Object newProxyInstance(ClassLoader loader, Class>[] interfaces,InvocationHandler h )
/**
* 接口
*/
public interface IUserDao {
void save();
}
/**
* 目标对象
*/
public class Target implements IUserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
/**
* 创建动态代理对象
* 动态代理不需要实现接口,但是需要指定接口类型
*/
public class ProxyFactory{
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
//创建一个实现InvocationHandler接口的类,它必须实现invoke()方法
new InvocationHandler() {
@Override--匿名内部类
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务2");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
}
}
);
}
}
/**
* 测试类
*/
public class App {
public static void main(String[] args) {
// 目标对象
IUserDao target = new UserDao();
// 【原始的类型 class cn.itcast.b_dynamic.UserDao】
System.out.println(target.getClass());
// 给目标对象,创建代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
// class $Proxy0 内存中动态生成的代理对象
System.out.println(proxy.getClass());
// 执行方法 【代理对象】
proxy.save();
}
}
背景:上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理
含义:在内存中构建一个子类对象从而实现对目标对象功能的扩展.
特点:
- 若想要代理没有实现接口的类,可以用Cglib实现
- Cglib是一个代码生成包,可以在运行期扩展java类与实现java接口,被很多AOP框架使用
- Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.
步骤:
1. 需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2. 引入功能包后,就可以在内存中动态构建子类
3. 代理的类不能为final,否则报错(final修饰的方法不可被继承)
4. 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
/**
* 目标对象,没有实现任何接口
*/
public class UserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
}
/**
* Cglib子类代理工厂
* 对UserDao在内存中动态构建一个子类对象
*/
public class ProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务...");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
}
/**
* 测试类
*/
public class App {
@Test
public void test(){
//目标对象
UserDao target = new UserDao();
//代理对象
UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.save();
}
}