一.设计模式的作用
设计模式是软件从业人员长期总结出来用于解决特定问题的通用性框架,它提高了代码的可维护性、可扩展性、可读性以及复用性。
二.设计模式
1.工厂模式
工厂模式提供了创建对象的接口,而无需制定创建对象的具体类,工厂类封装了具体类的创建过程,客户端无需知道具体实现类只需要知道工厂类,通过工厂类来创建具体实现的类。
1).优缺点
优点:
(1).松耦合:无需知道子类具体创建过程,只需要关注工厂类。
(2).可扩展性:扩展性高,如果想增加一个产品,只需要增加子类对应的工厂类即可。
缺点:
每增加一个产品,就需要增加一个具体的类和对应的工厂类,可维护性并不高,增加了代码复杂性。
2).应用场景
使用数据库连接工厂类连接不同的数据库,比如达梦、崖山等
3).类图
4).具体实现过程
(1).创建一个接口
(2).创建实体类
(3).创建工厂类
(4).根据类型调用工厂类连接数据库
2.抽象工厂模式
抽象工厂模式是围绕一个超级工厂创建其他工厂,此超级工厂又称为其他工厂的工厂,抽象工厂模式提供了一个接口,通过此接口及其具体实现类,可以将对象的创建与客户端代码分离,从而实现系统的松耦合。
1).优缺点
优点:
(1).保证产品族一致性:抽象工厂模式创建的产品族类都是同一类产品,客户端使用此族类的产品的时候也都是使用此族类的产品。
(2).实现松耦合:客户端代码只需要通过抽象工厂接口创建产品无需知道产品具体实现代码。
(3).有利于扩展:增加新的产品族类,只需要添加新的具体工厂和产品类即可。
缺点:
每次增加产品族类都要添加一个此族类的工厂代码,还要添加此工厂的具体实现代码,系统和代码复杂性变高。
2).应用场景
比如格力和美的电器都会生产很多产品,空调、洗衣机、冰箱、热水器等,这些都是产品族类。
3).组成
抽象工厂:一般为接口,声明了创建产品对象的方法;
具体工厂:实现了抽象工厂,用于创建产品对象的具体类;
抽象产品:一般为接口或抽象类,声明实现产品的公共方法,具体产品必须要实现此方法;
具体产品:实现了抽象产品;
4).类图
5).具体实现
(1).创建一个接口
(2).创建接口的实体类
(3).创建抽象工厂类
(4).创建抽象工厂类的扩展实现类
(5).创建生成器
(5).使用
3.单例模式
单例模式确保一个类只有一个实例,单例模式还需要提供一个全局访问方法
1).优缺点
优点:
(1).避免一个全局使用的类频繁地创建与销毁
(2).保证了全局状态的一致性
缺点:
(1).过度使用单例可能导致全局状态不可控
2).应用场景
获取打印机去打印图纸,可以使用单例模式去创建打印机;IP访问次数计数等;
3).具体实现
public class Singleton {
//实例私有
private static Singleton instance;
//构造方法私有
private Singleton() {
}
//创建实例的方法公开,如果没创建就创建实例,如果创建了就不在创建
public static Singleton getInstance() {
if (instance == null) {
// 如果实例为空,则创建一个新实例
instance = new Singleton();
}
return instance;
}
}
4.建造者模式
建造者模式提供了一种允许用户逐步设置各种属性来构建对象的方式,很多参数对于一个对象来说可能是可选的,开发者无需传递所有参数去创建对象,对于可选的参数如果用户未传就要去除,所以我们就可以将构建复杂组件的步骤与运用组件构建对象分离,使用builder模式建立。
1).优缺点
优点:
(1).分离构建过程和表示,使得构建过程更加灵活
(2).隐藏具体构建细节,提高封装性
(3).提供代码复用性
缺点:
(1).增加代码复杂性,对于步骤简单的对象没必要使用此模式
2).应用场景
需要生成的对象具有复杂的内部结构,创建者创建对象的步骤和参数过多而且需要更加灵活
3).具体实现
比如一个用户,姓名、电话、性别是必选的,但是住址、年龄、邮箱是可选的,有些用户可能输入年龄,有些用户可能给了地址等;这里通过UserBuilder去实现根据不同的参数创建User对象;
(1).创建User类和UserBuilder类型
public class User {
//名称 必填
private String name;
//性别 必填
private String sex;
//电话 必填
private String phone;
//年龄 可选
private Integer age;
//住址 可选
private String address;
//住址 可选
private String email;
public User(UserBuilder userBuilder) {
this.name = userBuilder.name;
this.sex = userBuilder.sex;
this.phone = userBuilder.phone;
this.age = userBuilder.age;
this.address = userBuilder.address;
this.email = userBuilder.email;
}
public static UserBuilder builder(String name, String sex, String phone){
return new UserBuilder(name,sex,phone);
}
public static class UserBuilder {
//名称
private String name;
//性别
private String sex;
//电话
private String phone;
//年龄
private Integer age;
//住址
private String address;
//住址
private String email;
//构造器
public UserBuilder(String name, String sex, String phone) {
this.name = name;
this.sex = sex;
this.phone = phone;
}
public UserBuilder age(Integer age) {
this.age = age;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
public UserBuilder email(String email) {
this.email = email;
return this;
}
public User build(){
return new User(this);
}
}
}
(2).使用UserBuilder创建user
5.原型模式
原型模式通过复制现有对象来创建新对象,也就是拷贝现有的实例对象来创建对象,而不需重头创建对象。
1).优缺点
优点:
(1).提高创建对象的效率,减少创建对象成本
(2).无需知道构造函数内部逻辑,降低了耦合度
缺点:
(1).对于对象内部的引用有循环接口或者对象内部有不支持序列化的引用对象就不支持拷贝
2).应用场景
当类初始化比较复杂、比较耗时耗性能、需要获取权限等的时候需要使用原型模式
3).深拷贝和浅拷贝
(1).浅拷贝:拷贝一个对象后,基本数据类型的变量会重新创建,引用类型指向的还是原对象所指向的
(2).深拷贝:拷贝一个对象后,基本数据类型还有引用对象都是重新创建的,比如clone方法就是深拷贝
4).具体实现
(1).实体类继承Cloneable ,复写clone方法
public class User implements Cloneable {
//名称 必填
private String name;
//性别 必填
private String sex;
//电话 必填
private String phone;
//年龄 可选
private Integer age;
//住址 可选
private String address;
//住址 可选
private String email;
@Override
public User clone() {
try {
return (User) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
(2).使用
6.适配器模式
通过一个适配器类将一个接口转换成另一个接口,使得两个不兼容的对象能够协同工作,从而消除不兼容问题
1).优缺点
优点:
(1).将不同的系统、库、组件适配在一起,而无需修改太多的代码,提高代码的复用性
(2).拥有更高的灵活性
缺点:
(1).过多的适配器会导致代码混乱降低维护性
2).类图
Mp4PlayerImpl专门用于播放MP4文件,Mp3PlayerImpl专门用于播放MP3,如果Mp4PlayerImpl想播放MP3文件那么就需要一个适配器Mp4PlayerAdapter去适配Mp3PlayerImpl的接口,去代理播放MP3文件。
3).具体实现
(1).实现MP4播放功能
(2).实现MP3播放功能
(3).实现MP4的适配器
(4).使用