单列模式:保证在一个JVM中只能有一个实例。
单列有七种写法:目前只需要知道懒汉式和饿汉式
懒汉式-->天生的线程不安全
饿汉式-->线程安全,当Class被加载的时候,被初始化了
饿汉式和懒汉式的优缺点:
懒汉式:1、线程安全
* 2、因为有synchronized(同步)所以调用效率不高
* 3、可以延时加载
* 要点:资源利用率高了。但是每次调用getInstance()方法都要同步,并发效率低了
恶汉式:1、天然线程安全,不需要加synchronized
* 2、方法没有同步,调用效率高
* 3、没有延时加载
/**饿汉式 单列模式
* @author jxy
* 单列设计模式
* 解决的问题:使得一个类只能创建一个对象.
* 如何实现?
* 1.私有化构造器
* 2.在类的内部创建一个类的实例
* 3.私有化此对象,通过公共的方法调用
* 4.此方法只能通过类来调用,类的实例必须声明成static
*/
public class 单列设计模式饿汉式 {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1);//com.jxy.basics.Singleton@15db9742
System.out.println(s2);//com.jxy.basics.Singleton@15db9742
}
}
class Singleton{
//1.私有化构造器
private Singleton(){
}
//2.在类的内部创建一个类的实例
private static Singleton instance = new Singleton();
//3.私有化此对象,通过公共的方法调用
//4.此方法只能通过类来调用,类的实例必须声明成static
public static Singleton getInstance() {
return instance;
}
}
public class 单列设计模式懒汉式 {
public static void main(String[] args) {
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s1); //com.jxy.basics.Singleton1@15db9742
System.out.println(s2);//com.jxy.basics.Singleton1@15db9742
}
}
//懒汉模式存在线程安全问题
class Singleton1{
//1.私有化构造器
private Singleton1(){
}
//2.在类的内部创建一个类的实例
private static Singleton1 instance = null;
//3.私有化此对象,通过公共的方法调用
//4.此方法只能通过类来调用,类的实例必须声明成static
public static Singleton1 getInstance() {
if(instance==null){
instance = new Singleton1();
}
return instance;
}
}
/**
* 静态内部类实现方式(也是一种懒加载方式)
* @author admin
* 外部类没有static属性,则不会像饿汉式那样立即加载对象
* 只有真正调用getInstance才会加载静态内部类。加载类时是线程安全的。
* instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性。
* 兼备了并发高效调用和延迟加载的优势
*/
public class Singleton03 {
private static class SingletonHolder {
private static final Singleton03 INSTANCE = new Singleton03();
}
private Singleton03() {
}
public static final Singleton03 getInstance() {
return SingletonHolder.INSTANCE;
}
}
反序列化破解单列模式
public class Client3 {
public static void main(String[] args) throws Exception {
Singleton3 s = Singleton3.getInstance();
Singleton3 s2 = Singleton3.getInstance();
System.out.println(s);
System.out.println(s2);
//通过反序列化破解单例
//序列化
FileOutputStream fos = new FileOutputStream("D:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.close();
fos.close();
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/a.txt"));
Singleton3 s3 = (Singleton3) ois.readObject();
System.out.println(s3);
//打印结果如下
// com.jxy.SJMS.FXL.Singleton3@2d7fc1e7 这是s对象
// com.jxy.SJMS.FXL.Singleton3@2d7fc1e7 这是s2对象
// com.jxy.SJMS.FXL.Singleton3@5162ab9 这个是s3的对象
}
}
防止反序列化破解单例模式
/**
* 通过反射破解单例模式(不包括枚举:枚举是不能破解的)
* @author admin
* 通过反序列化破解(不包括枚举:枚举是不能破解的)
* 如何防止反射和反序列化漏洞
*/
public class Singleton3 implements Serializable{
private static Singleton3 instance;
private Singleton3 (){
//在这里加这句就可以防止通过反射破解单例模式
if(instance!=null){
throw new RuntimeException();
}
}
public static synchronized Singleton3 getInstance() {
if (instance == null) {
instance = new Singleton3();
}
return instance;
}
/**这样可以防止反序列化破解单例模式
*
* 在反序列化时,直接返回instance,而不需要把反序列化得到的新对象返回
* @param @return
* @param @throws ObjectStreamException
* @return Object
* @author jiangxueyou
*/
public Object readResolve() throws ObjectStreamException{
return instance;
}
}
枚举实现单例模式
/**
* 枚举式实现单例模式
* 枚举本身就是单例模式,有JVM从根本上提供了保障,避免通过反射和反序列化的漏洞
* 缺点:就是无延迟加载
* @author admin
*
*/
public enum Singleton04 {
/**
* 定义一个枚举的元素,本身就是单例
*/
INSTANCE;
/**
* 添加仔细需要的操作
* @param
* @return void
* @author jiangxueyou
*/
public void SingletonOperation() {
// 功能处理
}
}
代理设计模式:
静态代理模式:就相当于某人去买房,找到中介一样
动态代理模式:JDK自带的动态代理模式、cglib代理设计模式
/**
*买房的接口
*/
public interface Hose {
/**
*
* @methodDesc: 功能描述:(买房代理)
* @author: 余胜军
* @param:
* @createTime:2017年8月27日 上午2:54:34
* @returnType: void
* @copyright:上海每特教育科技有限公司
*/
public void mai();
}
/**
* 实际要买房的人
* @author Administrator
*
*/
public class XiaoMing implements Hose {
@Override
public void mai() {
System.out.println("我是小明,我要买房啦!!!!haha ");
}
}
/**
* 静态代理类
* @author Administrator
*
*/
public class Proxy implements Hose{
private XiaoMing xiaoMing;
public Proxy(XiaoMing xiaoMing) {
this.xiaoMing = xiaoMing;
}
public void mai() {
System.out.println("我是中介 看你买房开始啦!");
xiaoMing.mai();
System.out.println("我是中介 看你买房结束啦!");
}
public static void main(String[] args) {
Hose proxy = new Proxy(new XiaoMing());
proxy.mai();
}
}
/**
* JDK代理
* @author Administrator
*
*/
public class JDKProxy implements InvocationHandler {
private Object tarjet;
public JDKProxy(Object tarjet) {
this.tarjet = tarjet;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是房产中介.....开始监听你买房啦!");
Object oj = method.invoke(tarjet, args);
System.out.println("我是房产中介.....结束监听你买房啦!");
return oj;
}
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
JDKProxy jdkProxy = new JDKProxy(xiaoMing);
//Jdk 动态代理 通过反射机制生产代理
Hose hose=(Hose) Proxy.newProxyInstance(xiaoMing.getClass().getClassLoader(), xiaoMing.getClass().getInterfaces(), jdkProxy);
hose.mai();
}
}
/**
* 使用cglib方式代理,不是jdk自带的代理类,需要引入jar保 asm 和cglib jar包
* @author Administrator
*
*/
public class Cglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("我是买房中介 , 开始监听你买房了cglib....");
Object invokeSuper = methodProxy.invokeSuper(o, args);
System.out.println("我是买房中介 , 开结束你买房了....");
return invokeSuper;
}
public static void main(String[] args) {
Cglib cglib = new Cglib();
//动态代理使用 asm框架生产代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(XiaoMing.class);
enhancer.setCallback(cglib);
Hose hose = (Hose) enhancer.create();
hose.mai();
}
}
工厂设计模式:简单工厂设计模式,工厂方法设计模式,抽象工厂设计模式
简单工厂模式
public class CarFactory {
static public Car createCar(String carName) {
Car car = null;
if (carName.equals("奥迪")) {
car = new AoDi();
} else if (carName.equals("奔驰")) {
car = new BenChi();
}
return car;
}
/**
*
* @methodDesc: 功能描述:(简单工厂)
* @author: 余胜军
* @param: @param
* args
* @createTime:2017年8月27日 上午2:03:01
* @returnType:@param args void
* @copyright:上海每特教育科技有限公司
*/
public static void main(String[] args) {
Car car1 = CarFactory.createCar("奥迪");
Car car2 = CarFactory.createCar("奔驰");
car1.run();
car2.run();
}
}
工厂方法设计模式
public interface Car {
public void run();
}
public class BenChi implements Car {
@Override
public void run() {
System.out.println("奔驰....");
}
}
public class AoDi implements Car {
@Override
public void run() {
System.out.println("奥迪....");
}
}
public class AoDiChiFactory {
static public Car createCar() {
return new AoDi();
}
}
public class BenChiFactory {
static public Car createCar() {
return new BenChi();
}
}
public class Main {
public static void main(String[] args) {
Car c1 = AoDiChiFactory.createCar();
Car c2 = BenChiFactory.createCar();
c1.run();
c2.run();
}
}
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
抽象工厂就是对接口的抽象,比如下面一个列子
抽象工厂抽象出具体的动作接口,然后由具体的工厂去实现
//抽象工厂抽象出具体的动作接口
public abstract class AbstractFactory {
abstract Juice createJuice();
abstract Pie createPie();
}
//接口1
public interface Juice {
public void desc();
}
//接口2
public interface Pie {
public void desc();
}
//子类实现1
public class BananaPie implements Pie {
@Override
public void desc() {
System.out.println("香蕉派");
}
}
//子类实现2
public class BananaJuice implements Juice {
@Override
public void desc() {
System.out.println("香蕉汁.");
}
}
//具体的实现由具体的工厂去继承抽象接口,然后实现
public class AppleFactory extends AbstractFactory{
@Override
Juice createJuice() {
return new AppleJuice();
}
@Override
Pie createPie() {
return new ApplePie();
}
}
//具体的实现由具体的工厂去继承抽象接口,然后实现
public class BananaFactory extends AbstractFactory{
@Override
Juice createJuice() {
return new BananaJuice();
}
@Override
Pie createPie() {
return new BananaPie();
}
}
//测试
public class Test {
public static void main(String args[]){
AbstractFactory factory1 = new AppleFactory();
factory1.createJuice().desc();
factory1.createPie().desc();
//假设我们之前需要的是applePie和appleJuice对象,现在需要换成bananaPie和BananaJuice对象
//我们只需要替换对应的实现工厂(把new AppleFactory换成new BananFactory就可以了,耦合比较低)
AbstractFactory factory2 = new BananaFactory();
factory2.createJuice().desc();
factory2.createPie().desc();
}
}
模板方法设计模式:就是把一部分确定的自己实现,不确定暴露出去由子类实现.
当功能内部一部分实现是确定的,一部分实现是不确定的时候,可以把不确定的部分暴露出去,让子类实现。
编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式。
public class 模板设计模式 {
public static void main(String[] args) {
new Broder().setTemple();
}
}
abstract class father{
public abstract void eat();
public void setTemple(){
long start = System.currentTimeMillis();
this.eat();
long end = System.currentTimeMillis();
System.out.println("花费的时间是:"+(end-start));
}
}
class Broder extends father{
@Override
public void eat() {
int sum = 0;
for (int i = 0; i < 10000; i++) {
sum+=i-=2;
}
System.out.println("sum的值为:"+sum);
}
}
//打印结果:sum的值为:-1073741826 花费的时间是:1317