全部章节 >>>>
本章目录
6.1 设计模式
设计模式是由软件界的前辈们总结出的一套可以反复使用的经验。它可以提高代码的可重用性,增强系统的可维护性以及解决一系列的复杂问题。设计模式是思想的体现,而非具体的实现
合理的利用设计模式,能在项目中搭建出更加合理、优秀、可扩展的项目架构,这对于项目中的灵活度、可扩展性起着非常重要的作用
设计模式是成为一名优秀开发人员、项目经理必须修炼的内功基础
6.1.1 设计模式概述和分类
随着软件行业不断发展设计模式的种类也越来越多,不同的设计模式,对于不同种类的问题也有着不同的效果
常见的设计模式有以下类别:
创建模式(单例模式、工厂模式、抽象工厂模式、生成器模式、原型模式)
结构模式(适配器模式、桥接模式、组成模式、装饰模式、外观模式、享元模式、代理模式)
行为模式(中介者模式、命令模式、备忘录模式、状态模式、策略模式、解释器模式、迭代器模式、观察者模式、访问者模式、模板方法模式)
6.1.2 单列模式介绍
单例模式(Singleton)是对象的创建模式。单例模式确保某一个类只有一个实例,而且自行实例化,并向整个系统提供这个实例,这个类称为单例类 单例模式的要点有以下 3 个 单例类只能有一个实例。 单例类必须自行创建唯一的实例。 单例类必须向所有对象提供这一实例。
6.1.3 单例模式的实现
单例模式具体的实现步骤
1、私有化构造方法
public class Singleton{
private Singleton(){
//第一步:构造方法私有化
}
}
构造方法私有化的目的是不让当前类范围以外的地方实例化对象
2、在当前类中实例化本类对象
// 创建一个静态对象
private static Singleton instance = new Singleton();
当前类以外不能实例化,但是当前类自己可以实例化,保证只实例化了一次, 外界都使用这一个对象即可。
3、提供给外界一个获取当前类对象的机会,该方法必须public static,这样外界通过类名可以调用该方法
// 创建一个获取静态对象的共有静态方法
public static Singleton getInstance() {
return instance;
}
第二步创建当前类对象时使用了private,目的是保护它,然后该类中提供公共静态方法对其进行访问获取
示列: 使用单例设计模式实现类的单例控制
public class Singleton {
// 创建一个静态对象
private static Singleton instance = new Singleton();
// 私有化构造方法
private Singleton() {
}
// 创建一个获取静态对象的共有静态方法
public static Singleton getInstance() {
return instance;}
}
public static void main(String[] args) {
// 创建 3 个 Singleton 对象
Singleton instance01 = Singleton.getInstance();
Singleton instance02 = Singleton.getInstance();
Singleton instance03 = Singleton.getInstance();
System.out.println(instance01);
System.out.println(instance02);
System.out.println(instance03);}
6.1.4 实践练习
6.2 单例模式的应用
6.2.1 单例模式应用场景
在一个系统中,有时会要求一个类有且仅有一个对象,如果存在多个对象就会出现“不良反应”,可以采用单例模式(Singleton)来解决这个问题
- 在整个项目中,需要一个共享访问点或共享数据,保证不同用户不同时间访问的都是同一个数据
- 创建对象需要消耗的资源过多,而该对象每次使用时功能均一样,没必要重复创建
- 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式
示列:某公司内只有一台打印机,供所有员工使用,使用单例模式模拟该打印机的单例。
public class CompanyPrinter {
// 私有化构造方法
private CompanyPrinter() {
}
// 创建静态内部类,该内部类的实例与外部类的实例没有绑定关系,该内部类只有被调用时才可加载,从而实现了延迟加载
private static class PrinterHolder {
// 创建 Printer 静态实例
private static CompanyPrinter printer = new CompanyPrinter();
}
// 返回静态内部类中创建的静态私有对象
public static CompanyPrinter getInstance() {return PrinterHolder.printer;}
}
public class Employee {
public static void main(String[] args) {
CompanyPrinter printer01 = CompanyPrinter.getInstance();
System.out.println(" 员工 1 使用打印机:" + printer01);
CompanyPrinter printer02 = CompanyPrinter.getInstance();
System.out.println(" 员工 2 使用打印机:" + printer02);
CompanyPrinter printer03 = CompanyPrinter.getInstance();
System.out.println(" 员工 3 使用打印机:" + printer03);}
}
6.2.2 单例模式的优缺点分析
单例模式也并非是完美的,也存在一些优点和缺点
优点:
- 项目中只有一个实例,减少了内存开支
- 单例模式只生成一个实例,所以减少了系统的性能开销
- 单例模式可以避免对资源的多重占用,比如读一个文件时,保证其他程序无法写入等
缺点:
- 单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码
- 单例模式对测试是不利的
- 单例模式与单一职责原则有冲突
6.2.3 实践练习
6.3 简单工厂模式
6.3.1 简单工厂模式的介绍
简单工厂模式的目的在于不知道创建对象的细节,而能根据需要得到所对应的对象
简单工厂模式是类的创建模式,这个模式的一般性结构如下图所示
简单工厂模式涉及到工厂(Creator)、抽象产品(Product)以及具体产品(ConcreteProduct),各个角色的职责
工厂:这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。工厂类必须能够被外界调用,创建所需要的产品对象
抽象产品:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口
具体产品:简单工厂所创建的具体实例对象,这些具体产品的类都是抽象产品的子类
示例:简单工厂实现步骤1:定义抽象产品父类
// 抽象接口
public interface Api {
// 具体方法的定义
public void operation(String s);
}
抽象产品的父类可以使用接口或者抽象类,但是需要有抽象方法
示例:简单工厂实现步骤2:定义具体子类产品
// 接口的具体实现产品A
public class ImpA implements Api {
//方法重写
public void operation(String s) {
System.out.println(" 实现接口 Api 的具体类 ImpA:" + s);
}
// 接口的具体实现产品B
public class ImpB implements Api {
//方法重写
public void operation(String s) {
System.out.println(" 实现接口 Api 的具体类 ImpB:" + s);
}
现在有两个具体的产品类都是抽象产品的子类:A产品和B产品,当然还可以有更多。
示例:简单工厂实现步骤3:定义简单工厂返回具体对象
// 工厂类
public class Factory {
// 创建 Api 对象的方法
public static Api createApi(int condition) {
Api api = null;
// 根据传来的条件选择创建哪个对象
if (condition == 1) {api = new ImpA();}
else if (condition == 2) {api = new ImpB(); }
return api; }
}
示例:简单工厂实现步骤4:使用者调用测试
public class Client {
public static void main(String[] args) {
Api api = Factory.createApi(2);
api.operation(" 正在使用简单工厂 ");
}
}
使用者可以传入条件,拿到自己想要的对象,具体如何创建的对象,则无需使用者关心,使用者只知道自己拿到对象可以使用即可。
6.3.2 实践练习
6.4 简单工厂模式的应用
6.4.1 简单工厂模式的使用场景
简单工厂的目的在于隐藏创建对象的过程,让调用者无需关心对象的创建过程,而是直接拿到可以使用的对象,提高项目对象获取的灵活性,建议在以下场景时选择简单工厂模式
- 想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂模式
- 想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制
示例:
- 假设一个场景:魅族、VIVO 和 OPPO 都是有名的国产智能手机品牌,有一家手机代工厂的主营业务,是为魅族、VIVO 和 OPPO 这三家公司生产手机
- 当魅族公司的订单到来时,工厂就要生产魅族手机;当 VIVO 公司的订单到来时,工厂就要生产 VIVO 手机;
- 当 OPPO 公司的订单到来时,工厂就要生产 OPPO 手机 工厂要生产什么品牌的手机,完全由订单来决定。那该如何用程序来模拟这个场景?
可以发现该场景有 3 个角色,分别是手机代工厂、手机订单和各个品牌的手机订单,可以使用简单工厂的 3 个角色来表示。手机代工厂是工厂,订单是抽象产品,各个公司下发的订单就是具体产品
6.4.2 简单工厂的优缺点分析
简单工厂虽然对于单一产品的创建,在灵活性方面提高了灵活度,但是在复杂产品集方面的扩展性仍然有很多不足
优点:
- 简单工厂模式虽然很简单,但是非常友好地帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程
- 通过简单工厂模式,实现了客户端和具体实现类的解耦
缺点
- 客户必须了解参数对应产品的关系,增加客户端使用的难度,也暴露了内部逻辑的实现过程
- 每当添加一个具体产品类时,都需要修改工厂角色类,增加了工作量
6.4.3 实践练习
总结:
- 设计模式是软件界的前辈们总结出的一套可以反复使用的经验,它可以提高代码的可重用性,增强系统的可维护性,还能解决一系列的复杂问题
- 单例模式是保证项目中某个类永远只存在一个对象的设计模式,可以降低某些只需要加载一次的重量级对象创建过程,避免多次创建引起的不必要开销
- 简单工厂模式的目的是对于使用者完全不必知道创建对象的细节,而能根据需要得到所对应的对象的过程,提高了获取对象的灵活性
- Java中常用的设计模式有23种,掌握常用的设计模式对于我们成为优秀的开发人员和项目经理又进了一步