设计模式(工厂,单例,代理,模板)

单列模式:保证在一个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

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值