阿里云【名师课堂】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() ;
}
}
通过观察程序我们可以发现,当变更使用的子类时主方法(客户端)没有发生任何改变,这样的设计就称为工厂设计模式。
- 回顾:
String args[]
表示该类执行时所需要的相关参数。具体有关内容请参考《阿里云【名师课堂】Java面向对象开发44 ~ 47:static关键字》中46:分析主方法组成。
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、总结
代理类本质是:所有的真实业务操作都会有一个与之辅助的功能类共同完成。
- 想吃饭,有餐厅给你提供食物、清洗餐具······
- 想打游戏,有厂商做游戏、提供支持······
目前还是不适应博客园的界面,等学成了再回归吧,对我来说当下还是csdn比较方便快捷:https://blog.csdn.net/weixin_43624945