单例模式要解决的问题?
保证一个类只有一个实例,并且可以全局访问它。
保证不能实例化多个该对象,必须自行创建该实例
单例类特点
构造方法私有,确保其他类无法通过new 关键字创建它,保证了该类只能有一个实例
有一个静态私有成员变量和静态公有工厂方法,工厂方法负责检查该实例
是否存在,并实例化,然后存储在静态成员变量中
什么时候使用单例模式?
1.要求产生唯一序列号
2.必须存在一个对象,客户端能够从一个公共资源访问到它
3.需要控制实例数目,创建一个对象消耗过多资源,如数据库连接,
为了节省系统资源的时候。
懒汉式加载
public class Singleton_lazy {
private static Singleton_lazy lazy = null;
private Singleton_lazy(){
// 具体逻辑
}
public static synchronized Singleton_lazy getLazy(){
if(lazy == null){
lazy = new Singleton_lazy();
}
return lazy;
}
}
懒汉式加载-双重检查加锁
public class Singleton_lazy {
//volatile保证,当uniqueInstance变量被初始化成Singleton实例时,多个线程可以正确处理uniqueInstance变量
private volatile static Singleton_lazy lazy = null;
private Singleton_lazy(){
// 具体逻辑
}
public static Singleton_lazy getLazy(){
if(lazy == null){
synchronized(this){
lazy = new Singleton_lazy();
}
}
return lazy;
}
}
使用到了volatile关键字来保证数据的可见性
饿汉式加载
public class Singleton_hunger {
private static Singleton_hunger lazy = new Singleton_hunger();
private Singleton_hunger(){
// 具体逻辑
}
public static Singleton_hunger getLazy(){
return lazy;
}
}
代理模式是什么?
可以使真实角色更加纯粹,不用去关注一些公共的业务
公共的业务交给代理角色,实现了业务的分工
公共业务发生扩展时,方便集中管理
代理模式分类有哪些?
静态代理和动态代理
静态代理的实现步骤
- 抽象具体业务
- 真实角色实现或继承抽象接口
- 代理角色实现或继承抽象接口
- 客户端访问代理类
静态代理的缺点是什么?
一个真实角色会产生一个真实代理,代码量会翻倍,开发效率变低
如何实现静态代理?
1:
// 抽象角色 - 租房方法
public interface RentDao {
// 租房
void rent();
}
2:
// 真实角色 - 房东
public class Host implements RentDao{
@Override
public void rent() {
System.out.println("房东出租房子!");
}
}
3:
// 代理类(中介)
public class AgentProxy implements RentDao{
private Host host;
// Spring 不建议使用有参构造方法注入
//public AgentProxy(Host host){
// this.host = host;
//}
public void setAgentProxy(Host host){
this.host = host;
}
@Override
public void rent() {
this.lookHose();
host.rent();
this.hetong();
}
// 切入其他操作
private void lookHose(){
System.out.println("中介带领看房子");
}
// 切入其他操作
private void hetong(){
System.out.println("中介带领签合同");
}
}
4:
// 访问代理的人 - 租房者
public class User {
public static void main(String[] args) {
Host host = new Host();
AgentProxy agent = new AgentProxy();
agent.setAgentProxy(host);
agent.rent();
}
}
如何理解动态代理?
为了解决静态代理的缺点,应使用动态代理。可以代理多个类。
动态代理的和静态代理所代理的角色一样。
动态代理的代理类是动态生成的,本质是反射实现的。
动态代理方式有哪些,有什么区别?
- 基于接口的动态代理 - JDK 的动态代理
- 基于类的动态代理 - cglib
JDK 动态代理是通过反射机制,目标类实现了接口
CGLIB 基于继承,采用字节码技术,目标类没有实现接口,主要是覆盖父类的方法。
动态代理的两个重要的类是什么?
java.util.reflect 包下:
1. Proxy - 生成代理类
2. InvocationHandler 接口,反射包 - 调用处理程序,处理代理实例并返回一个结果
如何实现动态代理?
public interface UserService {
void add();
void delete();
void update();
void query();
}
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("add...");
}
@Override
public void delete() {
System.out.println("delete...");
}
@Override
public void update() {
System.out.println("update...");
}
@Override
public void query() {
System.out.println("query...");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvicationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target){
this.target = target;
}
// 生成代理类,继承抽象接口
public Object getProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
this.getClass().getInterfaces(), this);
}
// 处理代理实例,返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target);
return result;
}
void log(String action){
System.out.println("执行了" + action + "方法");
}
}
public class Test {
public static void main(String[] args) {
// 真实角色
UserServiceImpl userService = new UserServiceImpl();
ProxyInvicationHandler pih = new ProxyInvicationHandler();
pih.setTarget(userService);
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
工厂模式是什么?
1.把对象的创建和使用分开
2.降低代码重复
3.降低维护成本
工厂模式有三种:
1.普通工厂模式
2.静态工厂模式
普通工厂模式是什么?
就是建立一个工厂类,对实现同一接口的类进行实例的创建
案例:
我们举一个发送邮件和短信的例子
首先,创建二者的共同接口:
public interface Sender {
public void Send();
}
其次,创建实现类:
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mailsender!");
}
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
最后,建工厂类:
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}
测试类:
public class FactoryTest {
public static void main(String[] args) {
SendFactory factory = new SendFactory();
Sender sender = factory.produce("sms");
sender.Send();
}
}
静态工厂模式是什么?
将多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可
案例:
public class SendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
测试类:
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}