设计模式之创建型模式
设计模式基于六大原则:
- 开闭原则:对修改封闭,对扩展开放
- 单一职责原则:一个类只做一件事
- 里氏替换原则:继承时子类只扩展新功能,不破坏父类原有功能
- 依赖倒置原则:细节依赖于抽象。抽象层放在程序设计的高层,程序细节的变化有底层的实现层来完成。
- 迪米特法则:一个类不应知道自己操作的类的细节。
- 接口隔离原则:客户端不应依赖它不需要的接口。让实现类只需依赖自己需要的接口方法。
创建型模式
关注于如何创建对象,将对象的创建与使用分离,降低耦合度。
1. 单例模式(Singleton)
一个类只有一个实例,且只有该类能自行创建这个实例,同时提供全局的指针访问这个实例。
优点
- 内存中只有一个实例,减少内存开销
- 避免对资源的多重占用(如写文件)
缺点
- 没有接口,扩展困难
应用场景
- 类需要频繁实例化又频繁销毁,如多线程的线程池等。
- 对象需要被共享的场合,如数据库连接池。
代码实例
为了不让其他类创建该类的对象,那么只要让构造函数私有化,并且创建自定义的静态私有实例,并向外提供创建或者获取改静态私有实例的方法就行。
public class SingleObject {
private static SingleObject INSTANCE = new SingleObject();
//构造函数私有化
private SingleObject() {
}
//对外提供获取实例的方法
public static SingleObject getInstance() {
return INSTANCE;
}
}
线程安全的单例模式(双重校验锁)
public class ThreadSafeDoubleCheckLocking {
private static volatile ThreadSafeDoubleCheckLocking INSTANCE;
private ThreadSafeDoubleCheckLocking() {
if (INSTANCE != null) {
throw new IllegalStateException("Already initialized.");
}
}
public static ThreadSafeDoubleCheckLocking getInstance() {
var result = INSTANCE;
if (result == null) {
synchronized (ThreadSafeDoubleCheckLocking.class) {
result = INSTANCE;
if (result == null) {
INSTANCE = result = new ThreadSafeDoubleCheckLocking();
}
}
}
return result;
}
}
线程安全的单例模式(懒加载)
public class ThreadSafeLazy {
private static volatile ThreadSafeLazy INSTANCE;
private ThreadSafeLazy() {
if (INSTANCE != null) {
throw new IllegalStateException("Already initialized.");
}
}
public static synchronized ThreadSafeLazy getInstance() {
if (result == null) {
INSTANCE = new ThreadSafeDoubleCheckLocking();
}
return result;
}
}
还有可以用枚举实现(推荐)
public enum SingleObject {
INSTANCE
}
var demo1=SingleObject.INSTANCE;
var demo2=SingleObject.INSTANCE;
2. 工厂模式(Factory, Simple Factory, Static Factory Method)
使用工厂(静态方法)封装类,隐藏实现细节,对外提供对象。
优点
- 一个调用者想创建一个对象,只要知道其名称就可以了
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
- 屏蔽产品的具体实现,调用者只关心产品的接口
缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度
应用场景
根据不同入参获得不同对象。
代码实例
食品工厂生产多种食品。
public interface Food{
void produce();
}
public class Baozi implements Food {
public void produce() {
//生产包子
}
}
public class Dumpling implements Food{
public void produce() {
// 生产饺子
}
}
public class FoodFactory {
public static Food getFood(String food) {
if ("baozi".equals(food)) {
new Baozi();
} else if ("dumpling".equals(food)) {
new Dumpling();
}
}
}
public class App{
public static void main(String[] args) {
FoodFactory.getFood("baozi");
FoodFactory.getFood("dumpling");
}
}
3. 抽象工厂模式(Abstract Factory)
抽象工厂模式就是对工厂模式的抽象。可能存在多种相似的工厂,提取这些工厂的特性。
优点
适用于横向拓展。(比如实例里面是食品工厂,那么可以加很多类似的可以生产食品的工厂)
缺点
不适合新增功能,比如抽象接口FoodFactory要新增接口,那么所有的具体工厂都需要实现
应用场景
不同操作系统的UI工具
代码实例
存在精灵王国与矮人王国,都存在国王、军队、城堡,实例化都是通过各自的工厂模式,因此可以进行抽象。
public interface Army {
String print();
}
public interface King {
String print();
}
public interface Castle {
String print();
}
public class ElfArmy implements Army {
// 具体实现
}
public class ElfKing implements King {
// 具体实现
}
public class ElfCastle implements Castle {
// 具体实现
}
对王国的抽象
public interface KingdomFactory {
Castle createCastle();
King createKing();
Army createArmy();
}
public class ElfKingdomFactory implements KingdomFactory {
// 具体实现
}
4. 建造者模式(Builder)
用于创建过程稳定,但配置多变的对象
优点
建造者独立,易扩展
缺点
产品需要有共同点
应用场景
一个复杂对象(由多个子对象组合而成)的创建
代码实例
RPG游戏创建角色
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HariColor hariColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
}
public class App{
public static void main(String[] args) {
var mage = new Hero.Builder(Profession.MAGE, "Riobard")
.withHairColor(HairColor.BLACK)
.withWeapon(Weapon.DAGGER)
.build();
}
}
5. 原型模式(Prototype)
需要创建大量相同或者相似对象
优点
- 比重新new一个对象性能高
缺点
- 需要为每个类都配置一个clone方法
应用场景
很少单独出现,一般是结合工厂方法模式一起使用。
代码实例
Java提供了clone方法,只要类实现Cloneable就行了,非常简单(Java自带的方法是浅拷贝,只拷贝基本类型的参数,非基本类型的对象不拷贝。深拷贝需要实现Serializable)
public class RealizeType implements Cloneable { public RealizeType() { System.out.println("具体原型创建成功"); } @Override protected RealizeType clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功"); return (RealizeType) super.clone(); } }
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { RealizeType realizetype=new RealizeType(); //拷贝 RealizeType clone = realizetype.clone(); } }