【设计模式】单例模式,代理模式,工厂设计模式,装饰器模式,适配器模式,观察者模式,建造者模式….

导读:本篇文章讲解 【设计模式】单例模式,代理模式,工厂设计模式,装饰器模式,适配器模式,观察者模式,建造者模式….,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

设计模式

Java 中一般认为有 23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌握。下面列出了所有的设计模式。需要掌握的设计模式我单独列出来了,当然能掌握的越多越好。

总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式。其定义为:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式实现方式:

/**
 * @ fileName:eSingleton
 * @ description: 饿汉式单例模式
 * @ author:wxh
 * @ createTime:2022/6/17 19:01
 * @ version:1.0.0
 */
public class ESingleton {


    public static ESingleton eSingleton = new ESingleton();

    public ESingleton() {
    }

    public static ESingleton getSingleton(){
        return eSingleton;
    }

}
/**
 * @ fileName:LSingleton
 * @ description: 懒汉式
 * @ author:wxh
 * @ createTime:2022/6/17 19:06
 * @ version:1.0.0
 */
public class LSingleton {
    private static LSingleton lSingleton;

    public LSingleton() {
    }
	//双重校验锁
    public static LSingleton getlSingleton(){
        if(lSingleton != null){
            synchronized (LSingleton.class){
                lSingleton = new LSingleton();
            }
        }
        return lSingleton;
    }
}
 public static void main(String[] args){
      //创建单例模式 饿汉式
      ESingleton eSingleton = ESingleton.getSingleton();
      ESingleton eSingleton2 = ESingleton.getSingleton();
      System.out.println(eSingleton == eSingleton2);

      //懒汉式
      System.out.println(LSingleton.getlSingleton() == LSingleton.getlSingleton());

  }

代理模式

静态代理

静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口、被代理类、代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。

public interface ITeacherDao {
	void teach(); // 授课的方法
}
public class TeacherDao implements ITeacherDao {
	@Override
	public void teach() {
		//对象实现类
		System.out.println(" 老师授课中  。。。。。");
	}
}
/**
 * @description: 通过构造将被代理类传进来 调用方法
 *
 * @return {@link null}
 * @author  wangxihao
 * @email wangxh0108@163.com
**/
public class  TeacherDaoProxy implements ITeacherDao{
	private ITeacherDao target; // 目标对象,通过接口来聚合
	//构造器
	public TeacherDaoProxy(ITeacherDao target) {
		this.target = target;
	}
	@Override
	public void teach() {
		// TODO Auto-generated method stub
		System.out.println("开始代理  完成某些操作。。。。。 ");//方法
		target.teach();
		System.out.println("提交。。。。。");//方法
	}
}
public static void main(String[] args) {
       //创建目标对象(被代理对象)
       TeacherDao teacherDao = new TeacherDao();
       //创建代理对象, 同时将被代理对象传递给代理对象
       TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
       //通过代理对象,调用到被代理对象的方法
       //即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
       teacherDaoProxy.teach();
   }

JDK 动态接口代理

JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类
的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建
一个符合某一接口的实例,生成目标类的代理对象。

public interface ITeacherDao {
	void teach(); // 授课方法
}
public class TeacherDao implements ITeacherDao {
	@Override
	public void teach() {
		System.out.println(" 老师授课中.... ");
	}
}
public class ProxyFactory {

	//维护一个目标对象 , Object
	private Object target;
	//构造器 对target 进行初始化 将代理对象传进来
	public ProxyFactory(Object target) {
		this.target = target;
	}

	//给目标对象 生成一个代理对象
	public Object getProxyInstance() {

		//说明
		/*
		 *  public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

            //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
            //2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
            //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler() {

			//目标对象实现的接口类型 反射获取加载器 目标对象实现的接口类型

					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("JDK代理开始~~");
						//反射机制调用目标对象的方法
						Object returnVal = method.invoke(target, args);
						System.out.println("JDK代理提交");
						return returnVal;
					}
				});
	}
}
public static void main(String[] args) {
      //创建目标对象
      ITeacherDao target = new TeacherDao();
      //给目标对象,创建代理对象, 可以转成 ITeacherDao
      ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
      // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
      System.out.println("proxyInstance=" + proxyInstance.getClass());
      //通过代理对象,调用目标对象的方法
      proxyInstance.teach();

  }

CGlib动态代理

CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,
可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新
的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,
而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。

public class TeacherDao {
	public String teach() {
		System.out.println(" 老师授课中  , 我是cglib代理,不需要实现接口 ");
		return "hello";
	}
}

在这里插入图片描述

public class ProxyFactory implements MethodInterceptor {


	/**
	 * <!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
	 * <dependency>
	 *     <groupId>org.ow2.asm</groupId>
	 *     <artifactId>asm</artifactId>
	 *     <version>7.1</version>
	 * </dependency>
	 * <!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-commons -->
	 * <dependency>
	 *     <groupId>org.ow2.asm</groupId>
	 *     <artifactId>asm-commons</artifactId>
	 *     <version>7.1</version>
	 * </dependency>
	 * <!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-tree -->
	 * <dependency>
	 *     <groupId>org.ow2.asm</groupId>
	 *     <artifactId>asm-tree</artifactId>
	 *     <version>7.1</version>
	 * </dependency>
	 * <!-- https://mvnrepository.com/artifact/cglib/cglib -->
	 * <dependency>
	 *     <groupId>cglib</groupId>
	 *     <artifactId>cglib</artifactId>
	 *     <version>3.3.0</version>
	 * </dependency>
 	 */

	//维护一个目标对象
	private Object target;
	//构造器,传入一个被代理的对象
	public ProxyFactory(Object target) {
		this.target = target;
	}
	//返回一个代理对象:  是 target 对象的代理对象
	public Object getProxyInstance() {
		//1. 创建一个工具类
		Enhancer enhancer = new Enhancer();
		//2. 设置父类
		enhancer.setSuperclass(target.getClass());
		//3. 设置回调函数
		enhancer.setCallback(this);
		//4. 创建子类对象,即代理对象
		return enhancer.create();
	}
	//重写  intercept 方法,会调用目标对象的方法
	@Override
	public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("Cglib代理模式 ~~ 开始");
		Object returnVal = method.invoke(target, args);
		System.out.println("Cglib代理模式 ~~ 提交");
		return returnVal;
	}
}
  public static void main(String[] args) {
      //创建目标对象
      TeacherDao target = new TeacherDao();
      //获取到代理对象,并且将目标对象传递给代理对象
      TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();
      //执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
      String res = proxyInstance.teach();
      System.out.println("res=" + res);
  }

工厂设计模式

工厂模式分为工厂方法模式和抽象工厂模式。

工厂方法模式
工厂方法模式分为三种:

普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

普通工厂模式:

public interface User {
    public void createUser();
}
public class Usera implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Usera!");
    }
}
public class Userb implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Userb!");
    }
}
public class UserFactory {
    public User produce(String type){
        if(type.contains("a")){
            return new Usera();
        }else{
            return new Userb();
        }
    }
}

 public static void main(String[] args){

     //普通工厂
     UserFactory userFactory = new UserFactory();
     User a = userFactory.produce("a");
     a.createUser();
 }

多工厂方法模式

该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

public interface User {
    public void createUser();
}
public class Usera implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Usera!");
    }
}
public class Userb implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Userb!");
    }
}
public class UserFactory {
    public User createUsera(){
        return new Usera();
    }
    public User createUserb(){
        return new Userb();
    }
}
public static void main(String[] args){
      //普通多工厂
      UserFactory userFactory = new UserFactory();
      User usera = userFactory.createUsera();
      User userb = userFactory.createUserb();
      usera.createUser();
      userb.createUser();
  }

抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

public interface User {
    public void createUser();
}
public class Usera implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Usera!");
    }
}
public class Userb implements User {
    @Override
    public void createUser() {
        System.out.println("创建了Userb!");
    }
}

public interface Provider {
    public User CreateUserFactory();
}
public class UseraFactory implements Provider {
    @Override
    public User CreateUserFactory() {
        return new Usera();
    }
}
public class UserbFactory implements Provider {
    @Override
    public User CreateUserFactory() {
        return new Userb();
    }
}
public static void main(String[] args){
     //总体工厂创建接口 创建工厂并创建对象
     Provider factory = new UseraFactory();
     User a = factory.CreateUserFactory();
     a.createUser();
 }

适配器设计模式

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

类的适配器模式

public interface IDept {
    public void createDept();
    public void createDeptb();
}
public class Dept {
    public void createDept(){
        System.out.println("创建dept");
    }
}
public class Adapter extends Dept implements IDept {
    @Override
    public void createDeptb() {
        System.out.println("创建b");
    }
}
//某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题
    public static void main(String[] args){
        Adapter adapter = new Adapter();
        adapter.createDept();
        adapter.createDeptb();
    }

对象的适配器模式
基本思路和类的适配器模式相同,只是将 Adapter 类作修改,这次不继承 Source 类,而是持有 Source 类的实例,以达到解决兼容性的问题。

接口的适配器模式
接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

装饰模式(Decorator)

顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

public interface User {
    public void method();
}
public class Usera implements User {
    @Override
    public void method() {
        System.out.println("usera!");
    }
}
public class Userb implements User {
    @Override
    public void method() {
        System.out.println("userb!");
    }
}
/**
 * @ fileName:DecoratorClass
 * @ description: 装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
 * @ author:wxh
 * @ createTime:2022/6/17 20:22
 * @ version:1.0.0
 */
public class DecoratorClass implements User {

    private User user;

    public DecoratorClass(User user) {
        this.user = user;
    }

    public DecoratorClass() {
    }

    @Override
    public void method() {
        System.out.println("之前新增装饰");
        user.method();
        System.out.println("之后新增装饰");
    }

    public static void main(String[] args){
        Usera usera = new Usera();
        DecoratorClass decoratorClass = new DecoratorClass(usera);
        decoratorClass.method();
    }
}

观察者模式(Observer)

观察者模式很好理解,类似于邮件订阅和 RSS 订阅,当我们浏览一些博客或 wiki 时,经常会看到 RSS 图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

public interface Observer {
    //定义观察者
    public void update();
}

class Observera implements Observer{
    //定义观察者 添加观察后执行的事件
    @Override
    public void update() {
        System.out.println("observea观察到改动执行");
    }
}
class Observerb implements Observer{
    //定义观察者 添加观察后执行的事件
    @Override
    public void update() {
        System.out.println("observeb观察到改动执行");
    }
}
/**
 * @ fileName:subject
 * @ description: 操作观察者
 * @ author:wxh
 * @ createTime:2022/6/17 20:30
 * @ version:1.0.0
 */
public interface subject {
    //操作观察者的事件
    public void add(Observer observer);
    public void delete(Observer observer);


    //通知所有观察者
    public void notifyObserver();
    //被观察者自身操作
    public void operation();
}
//抽象类 等待业务类继承调用
public abstract class AbstractObserver implements subject  {
    private Vector<Observer> vector = new Vector<>();
    //观察者的事件
    @Override
    public void add(Observer observer) {
        vector.add(observer);
    }
    @Override
    public void delete(Observer observer) {
        vector.remove(observer);
    }
    @Override
    public void notifyObserver() {
        Enumeration<Observer> elements = vector.elements();
        while (elements.hasMoreElements()){
            elements.nextElement().update();
        }
    }

    //被观察者自己的操作
    @Override
    public void operation() {

    }
}
/**
 * @ fileName:MySubject
 * @ description:  被观察者 业务类
 * @ author:wxh
 * @ createTime:2022/6/17 20:41
 * @ version:1.0.0
 */
public class MySubject extends AbstractObserver {

    @Override
    public void operation() {
        System.out.println("执行自己的业务!");
        notifyObserver();  //唤醒观察
    }
}
 public static void main(String[] args){
      MySubject mySubject = new MySubject();
      mySubject.add(new Observera()); //添加观察者a的事件
      mySubject.add(new Observerb());//添加观察者b的事件
      mySubject.operation();
  }

建造者模式(Builder)

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的 Test 结合起来得到的
在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/75438.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!