阿里云【名师课堂】Java面向对象开发71 ~ 72:接口的设计模式

@


Java一共有二十多种设计模式,最常用到的有三种:工厂、代理、单例。

71:工厂(Factory)设计模式(重点)

首先来看一个简单的程序范例:在进行类的设计时,首先需要有接口,而后接口要通过子类才可以进行对象的实例化处理

1、传统开发模式

范例:传统开发模式

interface IFruit { // 定义一个描述水果的操作
	public void eat() ; // 定义:吃水果的方法
}

class Apple implements IFruit {
	public void eat() {
		System.out.println("吃苹果前先削皮") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		IFruit fruit = new Apple() ;
		fruit.eat() ;
	}
}

那么我们讨论这个程序的问题:
这段代码实现的关键在于IFruit fruit = new Apple() ;,如果没有这句,接口对象无法进行实例化处理,这也是问题所在。
我们把主方法视为客户端,那么对于程序的修改不应该影响到客户端。

  • 理解:如果这时有个新水果:橘子,定义吃法为吃橘子前先剥皮,那么客户端想要吃橘子的时候,要把苹果子类换为橘子子类,实例化一个新对象。

在传统的设计模式中,关键字new是整个开发过程中造成耦合的最大元凶。如果不想每次都要更换子类,应该怎么做?

  • 耦合:一个接口与一个子类捆绑在一起。
  • 如果想要解耦合,就要引入一个第三方类(类比于JVM),这个类通过Factory来描述。
  • 联想:Java的可移植性、平台无关性的核心:Java虚拟机(JVM)的存在。当Java在不同的系统上运行时,程序员不需要更改任何代码,只需要使用匹配的JVM来执行、解释字节码文件。可以说,程序与操作系统之间没有任何直接关系,JVM是它们的桥梁。

2、通过Factory来描述

interface IFruit { // 定义一个描述水果的操作
	public void eat() ; // 定义:吃水果的方法
}

class Factory {
	// 这里为什么用static?
	// 因为此时Factory产生实例化对象没有意义,它只是一个方法
	public static IFruit getInstance(String className) {
		if ("apple".equals(className)) {
			return new Apple() ;
		}
		if ("mandarinorange".equals(className)) {
			return new MandarinOrange() ;
		}
		return null ; // 如果两种水果都不是,返回空
	}
}

class Apple implements IFruit {
	public void eat() {
		System.out.println("吃苹果前先削皮") ;
	}
}

class MandarinOrange implements IFruit {
	public void eat() {
		System.out.println("吃橘子前先剥皮") ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		if (args.length != 1) { // 首先判断是否正确传入参数
			System.out.println("ERROR! Wrong Input. ") ;
			System.exit(1) ; // 退出程序
		}
		IFruit fruit = Factory.getInstance(args[0]) ;
		fruit.eat() ;
	}
}

在这里插入图片描述
通过观察程序我们可以发现,当变更使用的子类时主方法(客户端)没有发生任何改变,这样的设计就称为工厂设计模式。

3、总结

以后只要编写接口,如果要取得接口的实例化对象,第一反应就是写工厂类。
工厂设计模式整体结构:有接口、有实现子类、有一个工厂类,工厂类可以取得接口对象,调用方法。

72:代理(proxy)设计模式

1、基本概念

代理设计模式就是两个字类共同实现一个接口,其中一个子类负责真实的业务实现,而另外的子类负责完成辅助真实业务主体的操作。

  • 理解:定义一个接口:饿了要吃饭,首先对于接口有一个核心实现:吃饭这个动作,然后要有辅助实现:找餐馆开始吃结账走人这些功能。

2、实现代理设计

interface ISubject {
	public void eat() ; // 定义:吃
}

class RealSubject implements ISubject { // 核心实现
	public void eat() {
		System.out.println("开冲!") ;
	}
}

class ProxySubject implements ISubject {
	private ISubject subject ; // 真正的操作业务
	// 创建代理类对象的时候必须要设置要代理的真实主题
	public ProxySubject(ISubject subject) {
		this.subject = subject ;
	}
	
	public void lookFor() {
		System.out.println("1、找到一家饭菜好吃的餐馆") ;
	}
	public void leave() {
		System.out.println("2、吃完饭要结账走人") ;
	}
	public void eat() { // 记住:接口子类一定要实现接口的抽象方法
		this.lookFor() ;
		this.subject.eat() ; // 调用真实的业务(通过subject传递)
		this.leave() ;
	}
}

class Factory {
	public static ISubject getInstance() {
		// 通过new RealSubject()真实主题传给ProxySubject()
		return new ProxySubject(new RealSubject()) ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		// 客户端应该只关注eat()这个主题,不操心有没有代理类
		ISubject sub = Factory.getInstance() ;
		// 通过代理类对象sub发出,利用代理类来实现真实业务
		sub.eat() ; // 调用代理的核心操作:吃饭
	}
}

3、总结

代理类本质是:所有的真实业务操作都会有一个与之辅助的功能类共同完成。

  • 想吃饭,有餐厅给你提供食物、清洗餐具······
  • 想打游戏,有厂商做游戏、提供支持······
posted @ 2020-06-19 11:19  溺水的情书  阅读(262)  评论(0编辑  收藏  举报