常用设计模式笔记

#创建型模式--单例模式、工厂模式 ##单例模式 该模式目的是使类在使用过程中只存在一个实例。例:spring容器默认bean是单例的。

单例模式可分为饿汉模式、懒汉模式。两者区别在于是否在类加载时创建唯一实例。

饿汉模式(先创建实例;加载类较慢,运行时较快;线程安全)

    //1.构造方法私有化
	private Singleton(){};
	
	//2.创建唯一类实例,private static
	private static Singleton instance = new Singleton();
	
	//3.提供能够用于获取实例的方法,public static
	public static Singleton getInstance() {
		return instance;
	}

懒汉模式(类使用时创建实例;加载类较快,运行时较慢;线程不安全--第一次创建实例时)

    //1.构造方法私有化
    private Singleton2(){}
	
    //2.创建类变量
	private static Singleton2 instance;
	
    //3.提供获取实例的方法,同时在第一次调用时创建实例
	public static Singleton2 getInstance() {
		if (instance == null) {
			instance = new Singleton2();
		}
		return instance;
	}

##工厂模式 该模式利用了java的多态性--程序中的定义的引用变量指向类的哪一个具体实例在程序运行时确定。 工厂模式可为实现了同一接口的实现类提供一个统一的实例化的方法。具体该方法如何实现,可根据场景定制。比如:

  
	/*
	 * 根据类型
	 */
	public AppInterface getApp(String key) {
		if ("game".equals(key)) {
			return new GameApp();
		} else if ("music".equals(key)) {
			return new MusicApp();
		}
		return null;
	}
	
	/*
	 * 根据类名
	 */
	public AppInterface getAppByClass(String className) {
		try {
			AppInterface app = (AppInterface) Class.forName(className).newInstance();
			return app;
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/*
	 * 根据类名。从properties中读取
	 */
	public AppInterface getAppByProperties(String key) {
		try {
            //PropertiesReader是一个自己写的类,它封装了可读取properties的方法
			Map<String,String> map = new PropertiesReader().getProperties();
			AppInterface app = (AppInterface) Class.forName(map.get(key)).newInstance();
			return app;
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

#结构型模式--代理模式、适配器模式 ##代理模式 代理模式是spring AOP的基础,它为其他对象提供一种代理以控制对这个对象的访问,相当于一个会为目标做点手脚的中介,常用于日志、事物等。

###自己实现代理模式

  • 声明一个接口,包含方法
  • 被代理对象实现这个接口
  • 代理类声明一个入参为接口类的构造函数(当然也要声明一个私有的接口类对象),将被代理对象注入到代理类中
  • 代理类实现上述接口,方法内部包涵对被代理对象该方法的调用(可以使用多个代理类)

来来来看代码,下面按顺序是 接口类、代理对象、代理类、测试类

public interface Moveable {
    public void run();
}
import java.util.Random;

public class Car implements Moveable {

	@Override
	public void run() {
		try {
			Random random = new Random();
			Thread.sleep(random.nextInt(1000));
			 System.out.println("my car is running...");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
public class CarLogProxy implements Moveable {
	
	public CarLogProxy(Moveable m) {
		super();
		this.m = m;
	}
	
	private Moveable m;

	@Override
	public void run() {
        System.out.println("my car is ready...");
        m.run();
        System.out.println("my car is crash...");
	}
}
public class Test {
	public static void main(String[] args) {
		Car car = new Car();
		CarLogProxy clp = new CarLogProxy(car);
		clp.run();
	}
}

###通过jdk实现代理模式(动态代理) 首先声明接口和被代理对象,然后我们来讲讲InvocationHander接口以及Proxy这个类。

InvocationHander接口

每一个动态代理类都必须实现InvocationHander这个接口,这个接口有个唯一的方法-invoke方法

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  • proxy:  指代我们所代理的那个真实对象
  • method:  指代的是我们所要调用真实对象的某个方法的Method对象
  • args:  指代的是调用真实对象某个方法时接受的参数
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {
	
	public TimeHandler(Object target) {
		super();
		this.target = target;
	}

	private Object target;

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		long st = System.currentTimeMillis();
        System.out.println("...the car is ready...");
        //当代理对象调用真实对象的方法时,会自动跳转代理对象关联的hander对象的invoke方法
		method.invoke(target);
		long et = System.currentTimeMillis();
		System.out.println("...the car has stoppted, and he runs " + (et - st) + " milliseconds...");
		return null;
	}
}

Proxy类

他的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法。

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
  • loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

  • interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

  • h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

测试类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import com.imooc.proxy.Car;
import com.imooc.proxy.Moveable;

public class Test {

	public static void main(String[] args) {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Class<?> cl = car.getClass();
        Moveable m = (Moveable)Proxy.newProxyInstance(cl.getClassLoader(), cl.getInterfaces(), h);
        m.run();
	}

}

##适配器模式 相比代理模式 ,适配器模式要简单的多,他通过继承或依赖已有对象,实现想要的目标接口。他就相当于一个转接器,比如将三孔插头转换为二孔插头。 比如我现在有一个二相插座

public class GBTwoPlug {
	public void powerWithTwo() {
		System.out.println("使用二相电流供电");
	}
}

有一个三相的接口

public interface ThreePlugIf {
    public void powerWithThree();
}

现在来看看适配器

/*
 * 使用继承方法
 */
public class TwoPlugAdapterExtends extends GBTwoPlug implements ThreePlugIf {

	@Override
	public void powerWithThree() {
		System.out.println("使用继承适配器");
		this.powerWithTwo();
	}

}

另一个适配器

/*
 * 使用依赖方法
 */
public class TwoPlugAdapter implements ThreePlugIf {
	
	private GBTwoPlug two;
	
	public TwoPlugAdapter(GBTwoPlug two) {
		this.two = two;
	}

	@Override
	public void powerWithThree() {
		System.out.println("使用二相转三相适配器");
		two.powerWithTwo();
	}

}

#行为型模式--观察者模式、责任链模式、策略模式、模板模式 ##观察者模式 观察者模式包含四个主要类:

  • 观察者接口(Observer),定义在目标发生改变时更新自己的方法update
  • 具体观察者(ConcreteObserver),实现观察者接口定义的更新方法update
  • 目标对象(Subject),保存所有的观察者,提供注册和删除的方法;还有一个notify的通知方法
  • 具体目标对象(ConcreteSubject),继承目标对象,负责将有关变化或状态存入观察者对象

###自己实现的观察者模式

public interface Observer {
    
	public void update(Subject subject);
}
public class ConcreteObserver implements Observer {
	
	private String observerState;

	@Override
	public void update(Subject subject) {
 		observerState = ((ConcreteSubject)subject).getSubjectState();
	}

}
public class Subject {
    private List<Observer> observers = new ArrayList<Observer>();
    
    public void attach(Observer ob) {
    	observers.add(ob);
    }
    
    public void detach(Observer ob) {
    	observers.remove(ob);
    }
    
    /*
     * 通知所有注册的观察者对象
     * 推模型中传的是固定值(即被观察者知道观察者所需),update(某个String类型之类)
     * 拉模型传的是整个对象实例(观察者收到后自行处理),update(this)
     */
    protected void notifyObservers() {
    	for (Observer observer:observers) {
    		observer.update(this);
    	}
    }
}
public class ConcreteSubject extends Subject {
    private String subjectState;

	public String getSubjectState() {
		return subjectState;
	}

	public void setSubjectState(String subjectState) {
		this.subjectState = subjectState;
		this.notifyObservers();
	}
}

###jdk实现的观察者模式 jdk提供了观察者接口 Observer 和 目标对象 Observable,我们只要实现具体观察者和具体目标对象就行了。其中具体目标对象发生更改时必须加一句this.setChanged();

import java.util.Observable;
import java.util.Observer;

public class ConcreteWeatherObserver implements Observer {
	
	private String observerName;

	public String getObserverName() {
		return observerName;
	}

	public void setObserverName(String observerName) {
		this.observerName = observerName;
	}

	private String explain;

	public String getExplain() {
		return explain;
	}

	public void setExplain(String explain) {
		this.explain = explain;
	}

	@Override
	public void update(Observable o, Object arg) {
		//推模型
		System.out.println(observerName + "收到了" + arg + ", " + explain);
		//拉模型
		//System.out.println(observerName + "收到了" + 
		//                  ((ConcreteWeatherSubject)o).getContent()+ ", " + explain);
		
	}

}
import java.util.Observable;

public class ConcreteWeatherSubject extends Observable {
	
	private String content;

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
		
		//在使用jdk自带的Observer时,必须加
		this.setChanged();
		
		//主动通知,推模式(传参)|拉模式(不传参)
		this.notifyObservers(content);
		
	}

}

看看我的测试类与结果

public class Client {
	public static void main(String[] args) {
		  //创建天气作为目标
		ConcreteWeatherSubject subject = new ConcreteWeatherSubject();
		
		ConcreteWeatherObserver girl = new ConcreteWeatherObserver();
		girl.setObserverName("蠢汪");
		girl.setExplain("老婆我想你了");
		
		ConcreteWeatherObserver bro = new ConcreteWeatherObserver();
		bro.setObserverName("飞");
		bro.setExplain("晚上回去跳舞撒");
		
		subject.addObserver(girl);
		subject.addObserver(bro);
		
		subject.setContent("天气很好,约一波");
		
	}
	

观察者模式测试结果

##责任链模式 责任链模式是将自己无法处理的责任按链一步一步传递直到可处理。他的一个实例就是类加载机制的双亲委派模型。

要构建责任链模式,需定义一个抽象类,他包含一个处理责任的抽象方法,以及可定义下一责任人的具体方法;处于责任链中的类都需继承该抽象类。 话不多说看代码:

public abstract class PriceHandler {
    
	protected PriceHandler successor;

	public void setSuccessor(PriceHandler successor) {
		this.successor = successor;
	}
	
	public abstract void processDiscount(float discount);
}
/*
 * 销售,可处理5%以内的折扣
 */
public class Sales extends PriceHandler {

	@Override
	public void processDiscount(float discount) {
		if (discount <= 0.05) {
			System.out.format("%s批准了折扣: %.2f%n", this.getClass().getName(), discount);
		} else {
			successor.processDiscount(discount);
		}
	}
}
/*
 * 经理,可允许30%折扣
 */
public class Manager extends PriceHandler {

	@Override
	public void processDiscount(float discount) {
		if (discount <= 0.3) {
			System.out.format("%s批准了折扣: %.2f%n", this.getClass().getName(), discount);
		} else {
			successor.processDiscount(discount);
		}
	}

}

public class CEO extends PriceHandler {

	@Override
	public void processDiscount(float discount) {
		if (discount <= 0.55) {
			System.out.format("%s批准了折扣: %.2f%n", this.getClass().getName(), discount);
		} else {
			System.out.format("%s拒绝了折扣: %.2f%n", this.getClass().getName(), discount);
		}
	}

}

这里结合工厂模式,定义每个责任人对应的下一个责任人


public class PriceHandlerFactory {
	
	public static PriceHandler createHandler() {
		Sales sales = new Sales();
		Director dr = new Director();
		Manager ma = new Manager();
		CEO ceo = new CEO();
		
		sales.setSuccessor(dr);
		dr.setSuccessor(ma);
		ma.setSuccessor(ceo);
		
		return sales;
	}

}

到这边责任链模式就完成了,当然我们可以测试一下

public class Customer {
	
	private PriceHandler priceHandler;
	
	public void setPriceHandler(PriceHandler priceHandler) {
		this.priceHandler = priceHandler;
	}
	
	public void requestDiscount(float discount) {
					priceHandler.processDiscount(discount);
	}
	
	public static void main(String[] args) {
		Customer customer = new Customer();
		customer.setPriceHandler(PriceHandlerFactory.createHandler());
		
		Random random = new Random();
		
		for (int i = 0; i < 100; i++) {
			System.out.println(i + ":");
			customer.requestDiscount(random.nextFloat());
		}
	}

}

##策略模式 策略模式把 一个类可能改变的方法提出来作为一个接口,然后在使用时调用实现接口的不同实例。

策略接口与实现类:

public interface CuteStrategy {
	
	public void performCute();

}
public class ActionCute implements CuteStrategy {

	@Override
	public void performCute() {
		System.out.println("蹭蹭蹭~腿~");
	}

}

public class NoCute implements CuteStrategy {

	@Override
	public void performCute() {
		System.out.println("我才不会卖萌呢~喵~");
	}

}

猫咪的类

public class Cat {
	
	public void mew() {
		System.out.println("喵~~喵~~喵~~");
	}
	
	public void move() {
		System.out.println("走猫步中~~~");
	}

	
	private CuteStrategy cuteStrategy;

	public void setCute(CuteStrategy cuteStrategy) {
		this.cuteStrategy = cuteStrategy;
	}
	
	public void cute() {
		cuteStrategy.performCute();
	}

}

具体使用时调用setCute(new ActionCute())或者setCute(new NoCute())就可以了。

##模板模式   定义一个操作中的算法的骨架,而将步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。

他的成员包括包含模板方法的抽象类实现抽象类中抽象方法的具体类

public abstract class RefreshBeverage {	
	
	/*
	 * 
	 */
	public final void step() {
		boilWater(); //煮沸水
		brew();
		pourInCup();
		if (addFlag()) {
			addCondiments();
		}
	}

	private void boilWater() {
		System.out.println("将水煮沸");
	}

	protected abstract void brew();

	private void pourInCup() {
		System.out.println("倒入杯中");
	}

	protected abstract void addCondiments();
	
	/*
	 * Hook,钩子函数
	 * 判断是否加入调料
	 */
	protected boolean addFlag() {
		return true;
	}
	
}
public class Coffee extends RefreshBeverage {
	
	@Override
	protected void brew() {
		System.out.println("冲泡咖啡~");
	}
	
	protected void addCondiments() {
		System.out.println("加点牛奶");
	}
    
	//protected boolean addFlag(){
	//	return false;
	//}
}

测试类

public class CoffeeTest {

	public static void main(String[] args) {
		RefreshBeverage coffee = new Coffee();
		coffee.step();
	}

}

转载于:https://my.oschina.net/jingzigege/blog/856111

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值