java基础之设计模式

1 设置模式之单例设计模式

概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

(1)饿汉式:

/**
 * @Description 饿汉式
 * @author refuel
 * @version v1.0
 */
public class TestSingleton{
	public static void main(String[] args) {
		Singleton sing = Singleton.getInstance(); 
		sing.show();
	}
}
class Singleton {	
	//1、将构造器私有化
	private Singleton() {}
	//2、定义创建一个私有对象 
	private static Singleton Sing = new Singleton();
	//3、定义公共静态方法返回该类类型的对象 
	public static Singleton getInstance() {
		return Sing;
	}
}

(2)饱汉式,线程不安全

/**
 * @Description 饱汉式,线程不安全
 * @author refuel
 * @version v1.0
 */
public class TestSingleton{
	public static void main(String[] args) {
		Singleton sing = Singleton.getInstance(); 
		sing.show();
	}
}
class Singleton {	
	//1、将构造器私有化
	private Singleton() {}
	//2、定义创建一个私有对象 
	private static Singleton Sing;
	//3、定义公共静态方法返回该类类型的对象 
	public static Singleton getSingleton() {
		if(Sing == null) {
			Sing = new Singleton();
		}
		return Sing;
	}
}

 

2 设置模式之工厂模式

2.1 简单工厂

简单工厂模式其实不是一个设计模式,反而比较像一种编程习惯。主要我们定义一个非常简单的类主要负责帮我们生产不同的产品。例子如下:

/**
 * @Description 简单工厂
 * @author refuel
 * @version v1.0
 */
public class SimpleFactory {
	//④使用工厂方法,通过传递类型信息来获取实体类的对象
	public static void main(String[] args) {

		Factory1 w = new Factory1();
		//获取Student1Work的对象,并调用他的doWork方法
		Product1 product = w.getExamples("Student1Work");
		product.show();
		//获取Teacher1Work的对象,并调用他的doWork方法
		Product1 product1 = w.getExamples("Teacher1Work");
		product1.show();
		//获取Worker1Work的对象,并调用他的doWork方法
		Product1 product2 = w.getExamples("Worker1Work");
		product2.show();
		
	}
	
}

 //①创建一个 Product接口
interface Product1{
	void show();
}
// ②实现Product 接口的实体类
class Student1 implements Product1 {
	@Override
	public void show() {
		System.out.println("学生学习");
	}	
}
class Teacher1 implements Product1 {
	@Override
	public void show() {
		System.out.println("老师教书育人");
	}	
}
class Worker1 implements Product1 {
	@Override
	public void show() {
		System.out.println("工人建高楼大厦");
	}	
}
//③定义工厂类 生成基于给定信息的实体类的对象
class Factory1 {
	//使用getExamples方法获取工作性质类型的对象
	public Product1 getExamples(String workType) {
		if(workType ==null) {
			return null;
		}
		if(workType.equalsIgnoreCase("Student1Work")) {
			return new Student1();
		}
		else if(workType.equalsIgnoreCase("Teacher1Work")) {
			return new Teacher1();
		}
		else if(workType.equalsIgnoreCase("Worker1Work")) {
			return new Worker1();
		}
		return null;
	}
}

2.2 工厂方法模式

简单工厂模式有一个缺点是不同的产品需要不同的额外参数的时候,是不支持的,而且如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

工厂方法模式概念:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类

何时使用:主要解决接口选择的问题,我们明确地计划不同条件下创建不同实例时。

/**
 * @Description 工厂模式
 * @author refuel
 * @version v1.0
 */
public class FactoryPattern {
	
	public static void main(String[] args) {

		Factory2 s = new StudentFactory2();
		s.getExamples().show();
		Factory2 t = new TeacherFactory2();
		t.getExamples().show();
		Factory2 w = new WorkerFactory2();
		w.getExamples().show();
	}
	
}

 //①创建一个 Product接口
interface Product2{
	void show();
}
// ②实现Product 接口的实体类
class Student2 implements Product2 {
	@Override
	public void show() {
		System.out.println("学生学习");
	}	
}
class Teacher2 implements Product2 {
	@Override
	public void show() {
		System.out.println("老师教书育人");
	}	
}
class Worker2 implements Product2 {
	@Override
	public void show() {
		System.out.println("工人建高楼大厦");
	}	
}
//③定义一个工厂接口
interface Factory2 {
	Product2 getExamples();
}
//④定义一个学生工厂接口
class StudentFactory2 implements Factory2 {
	public Product2 getExamples() {
		return new Student2();
	}
}
//⑤定义一个老师工厂接口
class TeacherFactory2 implements Factory2 {
	public Product2 getExamples() {
		return new Teacher2();
	}
}
//⑥定义一个工人工厂接口
class WorkerFactory2 implements Factory2 {
	public Product2 getExamples() {
		return new Worker2();
	}
}

2.3 抽象工厂模式

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

抽象工厂模式,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

/**
 * @Description 抽象工厂模式
 * @author refuel
 * @version v1.0
 */
public class AbstractFactoryPattern {
	
	public static void main(String[] args) throws ClassNotFoundException, 
	InstantiationException, IllegalAccessException {

		AbstractFactory sbstractFactory = SuperFactory.getFactory("com.refuel.factory.StudentFactory");
		Product SmallStudent = sbstractFactory.getExamples("com.refuel.factory.SmallStudent");
		SmallStudent.show();
		
	}
	
}

 //最高级抽象产品,用于抽象工厂的建造方法的返回值
abstract class Product{
	abstract void show();
}
//学生产品类
abstract class StudentProduct extends Product{
	
}
//小学生产品
class SmallStudent extends StudentProduct{
	public void show() {
		System.out.println("小学生");
	}		
}

//中学生产品
class MiddleStudent extends StudentProduct{
	public void show() {
		System.out.println("小学生");
	}		
}
//老师产品类
abstract class TeacherProduct extends Product{
	
}
//数学老师产品
class MathTeacher extends TeacherProduct{
	public void show() {
		System.out.println("数学老师");
	}		
}

//历史老师产品
class HistoryTeacher extends TeacherProduct{
	public void show() {
		System.out.println("历史老师");
	}		
}

//超级工厂类
class SuperFactory {
	public static AbstractFactory getFactory(String type) throws ClassNotFoundException, 
	InstantiationException, IllegalAccessException {
		 Class cl = Class.forName(type);
	     System.out.println("创建工厂" + type);
	     return (AbstractFactory) cl.newInstance();
	}
}
//抽象工厂类
abstract class AbstractFactory {
	protected abstract Product getExamples(String type) throws ClassNotFoundException, 
	InstantiationException, IllegalAccessException;
}

//学生工厂类,覆盖所有学生的生产方法
class StudentFactory extends AbstractFactory{
    public Product getExamples(String type) throws ClassNotFoundException, 
    InstantiationException, IllegalAccessException {
        Class cl = Class.forName(type);
        return (StudentProduct)cl.newInstance();
    }
}
//老师工厂类,覆盖所有老师的生产方法
class TeacherFactory extends AbstractFactory{
  public Product getExamples(String type) throws ClassNotFoundException, 
  InstantiationException, IllegalAccessException {
      Class cl = Class.forName(type);
      return (TeacherProduct)cl.newInstance();
  }
}

2.4 简单工厂模式,工厂模式与抽象工厂模式的比较

简单工厂模式:(1)优点:工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。(2)缺点:没有遵守开放—封闭原则(开放接口,封闭修改)。如果将来需要添加一个产品,那么,在简单工厂模式中,就必须在简单工厂类中添加相应的判断语句,这对程序的扩展本身就不利。

工厂模式:(1)优点 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。(2)缺点每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

抽象工厂模式:(1)优点:能够从多个产品族的多个产品中,简洁的获取想要的具体产品。解决了工厂模式中的不符合开闭原则的问题(增加新的产品时候,不修改工厂,而是增加工厂)。(2)缺点:产品族扩展比较困难,要增加一个系列的某一产品,要增加具体的产品类,还要增加对应的工厂类(或者修改对应产品族的工厂类)。产品族难扩展,产品等级易扩展。】

 

3 代理模式

提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。如果需改别人写好的代码时,可以通过代理的方式来扩展该方法。

3.1 静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。

/**
 * @Description 静态代理
 * @author refuel
 * @version v1.0
 */
public class TestProxy {
	public static void main(String[] args) {
		//客户租房子,找代理
		ProcyObject proxy = new ProcyObject(new SubjectImpl());
		proxy.action();
	}
}
//接口
interface Subject{
	void action();
}
//中介(代理)
class ProcyObject implements Subject {
	//中介和业主有关系,所以定义关联关系
	SubjectImpl subject = null;
	public ProcyObject(SubjectImpl subject) {
		this.subject = subject;
	}
	@Override
	public void action() {
		//调用业主的方法,自己没有
		subject.action();
	}
	
}
//业主
class SubjectImpl implements Subject{

	@Override
	public void action() {
		System.out.println("业主的房子");
	}
	
}

 

3.2 动态代理

动态代理也叫做:JDK代理,接口代理。代理对象不需要实现接口,但是目标对象一定要实现接口。代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)。

代理类所在包:java.lang.reflect.Proxy,JDK代理使用newProxyInstance方法。

/**
 * @Description 动态代理
 * @author refuel
 * @version v1.0
 */
public class DynamicProxy {
	public static void main(String[] args) {
		//目标对象
		Subject1 s = new SubjectImpl1();
		//给目标对象创建代理对象,内存中动态生成的代理对象
		Subject1 proxy = (Subject1)new ProxyFactory(s).getProxyInstance();
		proxy.action();
	}
}

interface Subject1 {
	void action();
}

/**
 * @Description 业主类
 * @author refuel
 * @version v1.0
 */
class SubjectImpl1 implements Subject1 {

	@Override
	public void action() {
		System.out.println("业主的房子");
	}

}

/**
 * @Description 代理工厂类
 * @author refuel
 * @version v1.0
 */
class ProxyFactory {
	// 中介和业主有关系,所以定义关联关系,来维护一个目标对象
	Object subject = null;

	public ProxyFactory(Object subject) {
		this.subject = subject;
	}

	// 给目标对象生成一个代理对象
	public Object getProxyInstance() {
		// ClassLoader loader:指定当前对象使用类加载器,获取类加载器的方法是固定的
		// Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方式确认
		// InvocationHandler h:事件处理,执行目标对象时,会触发事件处理器的方法,会把当前执行的目标对象作为的方法作为参数传入
		return Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("开始事务");
						// 执行目标对象方法
						Object invokeValue = method.invoke(subject, args);
						System.out.println("提交事务");
						return invokeValue;
					}

				});
	}
}

 

3.3 Cglib代理

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。静态代理和动态代理模式都是要求目标对象实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理。

/**
 * @Description Cglib类
 * @author refuel
 * @version v1.0
 */
public class CglibProxy {
	public static void main(String[] args) {
		//目标对象
		SubjectImpl2 target = new SubjectImpl2();
		//代理对象
		SubjectImpl2 proxy = (SubjectImpl2)new ProxyFactory(target).getProxyInstance();
		//执行代理对象的方法
		proxy.action();

	}
}
/**
 * @Description 业主类,目标对象,没有实现任何接口
 * @author refuel
 * @version v1.0
 */
class SubjectImpl2 {
	public void action() {
		System.out.println("业主的房子");
	}
}
/**
 * @Description Cglib子类代理工厂,对SubjectImpl2在内存中动态创建一个子类对象
 * @author refuel
 * @version v1.0
 */
class ProxyFactory implements MethodInterceptor{
	// 中介和代理有关系,所以定义关联关系,来维护一个目标对象
		Object subject = null;
		public ProxyFactory(Object subject) {
			this.subject = subject;
		}
		// 给目标对象创建一个代理对象
		public Object getProxyInstance() {
			//1.工具类
			Enhancer en = new Enhancer();
			//2.设置父类
			en.setSuperclass(subject.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(subject, args);
			 System.out.println("提交");
			 return returnValue;
		 }

}

2.4 静态代理,动态代理,Cglib代理的比较

静态代理:(1)优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.。(2)缺点:因为目标对象要与代理对象实现一样的接口,所以会产生很多的代理类,导致类太多。接口增加方法,目标对象与代理对象都要进行维护。

动态代理:(1)优点:由于java封装了newProxyInstance这个方法的实现细节,所以使用起来非常方便。(2)缺点:静态代理和JDK代理有一个共同的缺点,就是目标对象必须实现一个或多个接口

Cglib代理:(1)优点:目标对象与代理对象都不用实现接口。(2)缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。

在Spring的AOP编程中,如果加入容器的目标对象有实现接口,用JDK代理,如果目标对象没有实现接口,用Cglib代理

 

4 策略模式(Strategy Pattern)

4.1 什么是策略模式

针对一组算法,将每一种算法(策略类)都封装到具有共同接口的独立类中,从而他们可以相互替换,可以在不影响客户端的情况下发生改变,从而改变不同的功能。

一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

特点:封装变化的概念;面向接口编程(编程中使用接口而不是使用具体的实现类)。

组成部分:(1)抽象策略角色:是抽象的角色,一般使用接口或抽象类实现,如Comparator接口;

(2)具体策略角色:包装了具体的算法和行为,如一组实现了Comparator接口的实现类;

(3)环境角色:内部有一个抽象角色的引用,给客户端调用,如TreeSet类,内部一定有一个策略类的一个成员变量,这样在创建TreeSet对象的时候可以接收向它传递的具体的策略类。

4.2 为什么使用策略模式

在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。算法可以自由切换,扩展良好;不过策略类会增多,还要对外暴露。

4.3 什么情况下可以使用

(1)如果一个系统中有很多的类,他们之间的区别是他们的行为不同,就可以用策略模式让一个对象在那么多的行为中选择一种;

(2)一个系统需要动态的在几种算法中实现一种。

如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

4.4 案例

实现List集合增删查的功能

编写步骤:(1)定义抽象策略角色(定义一个策略对象的公共接口);(2)编写具体策略角色(实现抽象策略角色这个公共接口);(3)定义环境变量(内部一定要持有一个策略类的引用)。

(1) 定义抽象策略角色:

/**
 * @Description 定义抽象策略角色
 * @author refuel
 * @version v1.0
 */
public interface AbstarctStrategy<T> {
	//实现对List集合的操作
	public Boolean handle(List<T> list,T t);
}

(2)编写具体策略角色

/**
 * @Description 定义增加策略
 * @author refuel
 * @version v1.0
 */
public class AddStrategy<T> implements AbstarctStrategy<T> {
	//实现handle方法,完成增加元素操作
	@Override
	public Boolean handle(List<T> list, T t) {
		return list.add(t);
	}

}


/**
 * @Description 定义删除策略
 * @author refuel
 * @version v1.0
 */
public class RemoveStrategy<T> implements AbstarctStrategy<T> {
	//实现handle方法,完成删除元素操作
	@Override
	public Boolean handle(List<T> list, T t) {
		return list.remove(t);
	}

}


/**
 * @Description 定义查询策略
 * @author refuel
 * @version v1.0
 */
public class QueryStrategy<T> implements AbstarctStrategy<T> {
	//实现handle方法,完成查看元素是否存在操作
	@Override
	public Boolean handle(List<T> list, T t) {
		return list.contains(t);
	}

}

(3)定义环境变量

/**
 * @Description 环境角色
 * @author refuel
 * @version v1.0
 */
public class Environment<T> {
	//策略类的引用
	private AbstarctStrategy<T> strategy;
	public Environment(AbstarctStrategy<T> strategy) {
		this.strategy = strategy;
	}
	public Boolean handleList(List<T> list,T t) {
		return strategy.handle(list, t);
	}
}

(4)测试

/**
 * @Description 测试类
 * @author refuel
 * @version v1.0
 */
public class Test {
	public static void main(String[] args) {
		Environment<Integer> en = new Environment<>(new AddStrategy<Integer>());
		List<Integer> arrList = Arrays.asList(10,20,30,40,50);
		List<Integer> list = new ArrayList<>(arrList);
		en.handleList(list, 60);
		for (Integer i : list) {
			System.out.print(i + " ");  //运行结果 10 20 30 40 50 60 
		}
	}
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值