设计模式分为三种类型,共23种:
- 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
- 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
- 行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。 实际上能够掌握其中几种常用的设计模式就很不错了。
代码风格良好的标准
如果想要确认代码编写风格是否良好,可以遵从以下两个标准:
- 客户端(主方法)调用简单,不需要关注具体细节。
- 程序代码的修改,不会影响到客户端的调用,即使用者可以不去关心代码是否变更。
以后编写代码要遵循这两个标准。
工厂设计模式(Factory)
我们通过一个例子来了解工厂设计模式。
首先,定义一个Fruit接口1
2
3
4
5package Factory.design;
public interface Fruit {
public void eat(); // 定义抽象方法
}
编写Apple类和Orange类实现Fruit接口1
2
3
4
5
6
7
8package Factory.design;
public class Apple implements Fruit {
@Override
public void eat(){
System.out.println("吃苹果");
}
}
1 | package Factory.design; |
编写测试程序TestDemo1
2
3
4
5
6
7
8package Factory.design;
public class TestDemo {
public static void main(String[] args){
Fruit f=new Apple();
f.eat();
}
}
可以发现,上面的代码不是良好的代码编写风格。因为每次我们想实例化Fruit接口对象时,都需要通过子类来进行上转型操作。假设有另一个子类Orange也实现Fruit接口,当我们想得到Orange对象时,就需要修改客户端代码,也就是将Apple子类替换为Orange子类。那么,假设有很多子类实现了Fruit接口呢?
其实,在整个过程中,客户端只关心一件事:如何取得Fruit接口对象。至于这个接口是由那个子类对象实例化的客户端根本不需要知道,所以最大问题就在关键字new的使用上
。
那么,如何解决关键字new带来的耦合度问题呢?解决办法是让客户端只看见接口而不让其看见子类,但是需要一个中间工具类(也就是Factory工厂类)来取得接口对象
。这样客户端就不需要关心接口子类,只要通过Factory工厂类就可以获取接口对象。
增加一个工厂类进行过渡1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package Factory.design;
public class Factory { // 定义工厂类,此类不提供属性
/**
* 取得指定类型的接口对象
* @param className 要取得的类实例化对象标记
* @return 如果指定标记存在,则Fruit接口实例化相应对象,否则返回null
*/
public static Fruit getInstance(String className){
if("apple".equals(className)){ // 是否是苹果类
return new Apple();
}else if("orange".equals(className)){// 是否是橙子类
return new Orange();
}else{
return null; // 没有实例化对象会造成NullPointerException,这里再编写一个Other类实现Fruit接口,然后在这里实例化Other子类对象,就不会出现NullPointerException
}
}
}
相应的客户端代码:1
2
3
4
5
6
7
8package Factory.design;
public class TestDemo {
public static void main(String[] args){
Fruit f=Factory.getInstance("orange"); // 通过工厂类取得指定接口对象
f.eat(); // 调用接口方法
}
}
通过使用Factory.getInstance()方法根据指定子类的标记取得接口实例化对象,使得客户端不需要再关注具体子类,也不需要关注Factory类是怎么处理的,只需要关注如何取得接口对象,如何进行操作。这样的设计模式就是工厂设计模式。
代理设计模式
代理设计也是在java开发中使用较多的一种设计模式,所谓的代理设计就是指一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,就好比在生活中经常使用到的代理上网那样,客户通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网操作相关的操作。
用户只关注浏览网页这个功能,而其他业务操作(如:检查用户身份)交给代理服务器处理。1
2
3
4
5package proxy.design;
public interface NetWork { // NetWork接口
public void browse(); // 定义浏览网页的方法
}
1 | package proxy.design; |
1 | package proxy.design; |
1 | package proxy.design; |