设计模式--创建者模式
目录创建者模式
-
单例模式:
/** * @author strind * @version 1.0 * @description 饿汉式 + 静态成员变量 * @date 2024/2/3 11:31 */ public class ex1 { private static ex1 instance = new ex1(); // 私有构造方法 private ex1() { } // 供外界获取实列 public static ex1 getInstance(){ return instance; } }
/** * @author strind * @version 1.0 * @description 饿汉式 + 静态代码块 * @date 2024/2/3 11:31 */ public class ex2 { private static ex2 instance; static { instance = new ex2(); } // 私有构造方法 private ex2() { } // 供外界获取实列 public static ex2 getInstance(){ return instance; } }
/** * @author strind * @version 1.0 * @description 懒汉式 * @date 2024/2/3 11:31 */ public class ex3 { private static ex3 instance; // 私有构造方法 private ex3() { } // 供外界获取实列(线程不安全,方法上可以加 synchronized 关键字) public static ex3 getInstance(){ if (Objects.isNull(instance)){ instance = new ex3(); } return instance; } }
/** * @author strind * @version 1.0 * @description 懒汉式 + double-check * @date 2024/2/3 11:31 */ public class ex4 { private static ex4 instance; //private volatile static ex4 instance; // 私有构造方法 private ex4() {} // 供外界获取实列(线程安全) public static ex4 getInstance(){ // 第一次检查 if (Objects.isNull(instance)){ // 多线程时,初次访问时,可能有多个线程走到这里,但只有一个会进去, // 此后,其余线程在第一次检查时便会失败,走不到这里 synchronized (ex4.class){ // 第二次检查,同一时间只有一个线程在这里,对象只会被创建一次 // 之后的线程无法进入if代码块里 if (Objects.isNull(instance)){ instance = new ex4(); } } } return instance; } /* 注意: 上面的代码依旧存在问题,在多线程情况下,有可能出现空指针问题, 原因是:JVM的指令重排序 解决方法:在instance变量上加volatile关键字,避免JVM指令重排 */ }
/** * @author strind * @version 1.0 * @description 懒汉式 + 静态内部类 * @date 2024/2/3 11:31 */ public class ex5 { // 私有构造方法 private ex5() { } private static class ex5Holder{ private static final ex5 INSTANCE = new ex5(); } public static ex5 getInstance(){ return ex5Holder.INSTANCE; } /* 由于JVM在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会加载,并初始化器静态属性。静态属性被static修饰,只会被实例化一次。 */ }
/** * @author strind * @version 1.0 * @description 枚举(饿汉式) * @date 2024/2/3 11:31 */ public enum ex7 { INSTANCE; }
破坏单例模式的方法(对枚举方式创建的无效):
- 序列化和反序列化
- 反射
解决方法:
-
对于序列化和反序列化(添加 readResolve( )方法)
public class ex5 { // 私有构造方法 private ex5() { } private static class ex5Holder{ private static final ex5 INSTANCE = new ex5(); } public static ex5 getInstance(){ return ex5Holder.INSTANCE; } // 当进行反序列化时,会自动调用该方法,将该方法的返回值直接返回 public Object readResolve(){ return ex5Holder.INSTANCE; } }
-
对于反射
public class ex5 { private static boolean flag = false; // 私有构造方法 private ex5() { // 在这里解决 synchronized (ex5.class){ if (flag){ throw new RuntimeException("你犯规了"); } flag = true; } } private static class ex5Holder{ private static final ex5 INSTANCE = new ex5(); } public static ex5 getInstance(){ return ex5Holder.INSTANCE; } }
-
工厂模式:
-
简单/静态 工厂,(不属于设计模式,且违背了“开闭原则”)
-
工厂方法模式
/** * @author strind * @version 1.0 * @description 工厂方法模式 * @date 2024/2/4 10:17 */ public class factory_method { public static void main(String[] args) { // 生产美式咖啡 CoffeeStore coffeeStore = new CoffeeStore(); coffeeStore.setFactory(new AmercianCoffeeFactory()); String coffee = coffeeStore.orderCoffee().getCoffee(); System.out.println(coffee); } } abstract class Coffee{ abstract String getCoffee(); } class AmercianCoffee extends Coffee{ @Override String getCoffee() { return "美式咖啡"; } } class LatteCoffee extends Coffee{ @Override String getCoffee() { return "拿铁咖啡"; } } class CoffeeStore{ private CoffeeFactory factory; public void setFactory(CoffeeFactory factory){ this.factory = factory; } public Coffee orderCoffee(){ return factory.createCoffee(); } } interface CoffeeFactory{ Coffee createCoffee(); } class AmercianCoffeeFactory implements CoffeeFactory{ @Override public Coffee createCoffee() { return new AmercianCoffee(); } } class LatteCoffeeFactory implements CoffeeFactory{ @Override public Coffee createCoffee() { return new LatteCoffee(); } } /* 为什么没有违背“开闭原则”: 当我们需要添加新的咖啡时,只需要在继承Coffee编写新的咖啡类,和实现CoffeeFactory接口,写新的工厂即可。CoffeeStore类,没有任何更改。对拓展开发,对修改关闭 */
缺点:拓展时,添加的类较多,增加系统的复杂度,
原因:工厂类功能唯一
-
抽象工厂模式
/** * @author strind * @version 1.0 * @description 抽象工厂 * @date 2024/2/4 10:41 */ public class Abstract_factory { public static void main(String[] args) { // 美式风味 //AmercianFoodFactory factory = new AmercianFoodFactory(); // 拿铁风味 LatteFoodFactory factory = new LatteFoodFactory(); Coffee coffee = factory.createCoffee(); Dessert dessert = factory.createDessert(); System.out.println(coffee.getCoffee() + " " + dessert.getDessert()); } } abstract class Coffee{ abstract String getCoffee(); } abstract class Dessert{ abstract String getDessert(); } class AmercianCoffee extends Coffee{ @Override String getCoffee() { return "美式咖啡"; } } class LatteCoffee extends Coffee{ @Override String getCoffee() { return "拿铁咖啡"; } } class Trimisu extends Dessert{ @Override String getDessert() { return "提拉米苏"; } } class MatchMousse extends Dessert{ @Override String getDessert() { return "抹茶慕斯"; } } interface FoodFactory{ Coffee createCoffee(); Dessert createDessert(); } class AmercianFoodFactory implements FoodFactory{ @Override public Coffee createCoffee() { return new AmercianCoffee(); } @Override public Dessert createDessert() { return new Trimisu(); } } class LatteFoodFactory implements FoodFactory{ @Override public Coffee createCoffee() { return new LatteCoffee(); } @Override public Dessert createDessert() { return new MatchMousse(); } } /* 现在一个具体工厂生产的是同一族的产品(例如苹果公司,既有电脑,也有手机,还有paid等。上一个例子则是,只能生产手机或电脑) */
缺点:当同一族产品变更时(新增/减少),修改代价较大(工厂都要改变)
-
拓展:简单工厂+配置文件
/** * @author strind * @version 1.0 * @description 静态工厂 + 配置文件 * @date 2024/2/4 11:08 */ public class Config_factory { public static void main(String[] args) { Coffee coffee = CoffeeFactory.createCoffee("latte"); System.out.println(coffee.getCoffee()); } } abstract class Coffee{ abstract String getCoffee(); } class AmercianCoffee extends Coffee{ @Override String getCoffee() { return "美式咖啡"; } } class LatteCoffee extends Coffee{ @Override String getCoffee() { return "拿铁咖啡"; } } class CoffeeFactory{ // 加载配置文件 private static Map<String,Coffee> map = new HashMap<>(); static { Properties properties = new Properties(); InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties"); try { properties.load(is); Set<Object> keys = properties.keySet(); for (Object key : keys) { String className = properties.getProperty((String) key); // 反射创建对象 Class<?> clazz = Class.forName(className); Coffee coffee = (Coffee) clazz.newInstance(); map.put((String) key,coffee); } } catch (Exception e) { throw new RuntimeException(e); } } public static Coffee createCoffee(String type){ return map.get(type); } } 配置文件: american=pattern.factory.AmercianCoffee latte=pattern.factory.LatteCoffee /** 添加新的咖啡,只需要在配置文件中添加即可,没有修改代码,符合“开闭原则” */
-
-
原型模式:理解成克隆就行(注意是浅克隆还是深克隆)
使用场景
- 对象的创建非常复杂。
- 性能和安全要求比较高
-
建造者模式:用于较为复杂的对象的构建
角色:
- 抽象建造者(Builder):这个接口规定要实行复杂对象的哪些部分的创建,并不涉及具体的部件的创建
- 具体建造者类(ConcreteBuilder):实现Builder接口,完成复杂产品的各个部件的具体创建方法。在创建过程完成后,提供产品实例
- 产品类(Product):要创建的复杂对象
- 指挥者类(Director):调用具体的创建者来创建复杂对象的各个部分,在指挥者种不涉及具体产品的信息,只负责保证对象的各部分完整创建或按某种顺序创建。
/** * @author strind * @version 1.0 * @description 建造者模式 构建自行车 * @date 2024/2/4 12:00 */ public class Bike_build { public static void main(String[] args) { Director director = new Director(new MoBikeBuilder()); Bike bike = director.construct(); System.out.println(bike.getFrame() + " " + bike.getSeat()); } } class Bike{ private String frame; // 车架 private String seat; // 车座 public String getFrame() { return frame; } public void setFrame(String frame) { this.frame = frame; } public String getSeat() { return seat; } public void setSeat(String seat) { this.seat = seat; } } // 建造者 abstract class Builder{ protected Bike bike = new Bike(); public abstract void buildFrame(); public abstract void buildSeat(); public abstract Bike createBike(); } class MoBikeBuilder extends Builder{ @Override public void buildFrame() { bike.setFrame("碳纤维"); } @Override public void buildSeat() { bike.setSeat("真皮"); } @Override public Bike createBike() { return bike; } } class ofoBuilder extends Builder{ @Override public void buildFrame() { bike.setFrame("铝合金"); } @Override public void buildSeat() { bike.setSeat("橡胶"); } @Override public Bike createBike() { return bike; } } // 指挥者 class Director{ private Builder builder; public Director(Builder builder) { this.builder = builder; } public Bike construct(){ builder.buildFrame(); builder.buildSeat(); return builder.createBike(); } } // 简化 将指挥者融入到建造者里 abstract class Builder{ protected Bike bike = new Bike(); public abstract void buildFrame(); public abstract void buildSeat(); public abstract Bike createBike(); public Bike construct(){ builder.buildFrame(); builder.buildSeat(); return builder.createBike(); } }