创建型设计模式
创建型模式抽象了对象实例化的过程,将软件模块中对象的创建和使用分离,外界只需知道对象的接口,而无需清楚对象具体的创建过程。
工厂模式
工厂模式专门负责实例化有共同接口(父类)的实例,动态决定实例化的子类。
什么时候有用?
- 当创建一个对象,需要配置多个子对象时。
- 函数式编程,new代码整体看着不舒服,且使用一个类来创建,在修改创建类时修改的内容会少一点。
- 通过工厂模式(工厂方法得是静态的)结合XML的形式可以通过配置文件的配置参数直接创建类,这就是application.yaml的原理。
简单工厂模式、方法工厂、抽象工厂模式这三者并没有什么高级低级之分,按需选择即可,个人推荐简单工厂和抽象工厂,简单工厂是简单且好用啊。更多的是一种抽象创建对象的思想,不要形成思维定势。
简单工厂模式:又称为静态工厂方法模式,根据静态方法中的参数来返回不同类的实例。
public class PhoneSimpleFactory { private static Map<String, Phone> cache; private static PhoneSimpleFactory factory; //单例模式 static { cache = new HashMap<>(); cache.put("apple", new IPhone()); cache.put("galaxy", new GalaxyPhone()); factory = new PhoneSimpleFactory(); } public static PhoneSimpleFactory build() { return factory; } public Phone get(String key) { if (key.equalsIgnoreCase("apple")) { return cache.get("apple"); } else if (key.equalsIgnoreCase("galaxy")) { return cache.get("galaxy"); } throw new NoSuchElementException("this key not exist!"); } }
缺点: 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。
模式拓展:父类实现了静态工厂方法,父类本身就是工厂类。
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。【子类多】
理一下逻辑,大概就是客户获取子类方法工厂,再由工厂方法生成对应的实例对象。因此,工厂方法模式可以通过不断的拓展子类的个数来创建各种不同的对象,缺点也就很明显了,但子类数量繁多时,工厂类也会变得很多。
public abstract class MethodPhoneFactory { //由子类实现真正地创建逻辑 public abstract Phone createPhone(); //子类不再需要重复写复杂运行逻辑 public Phone salePhone() { Phone phone = createPhone(); phone.ring(); return phone; } }
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。【方法多】
理一下逻辑,就是通过在工厂接口中,通过添加接口方法的方式创建对象。这样就不再需要使用违反开闭原则的简单工厂模式了,同时也不再需要使用子类繁多的方法工厂模式,仅需增加抽象工厂类的抽象方法即可。
//按钮接口:抽象产品 interface Button { public void display(); } //Spring按钮类:具体产品 class SpringButton implements Button { public void display() { System.out.println("显示浅绿色按钮。"); } } //Summer按钮类:具体产品 class SummerButton implements Button { public void display() { System.out.println("显示浅蓝色按钮。"); } } //文本框接口:抽象产品 interface TextField { public void display(); } //Spring文本框类:具体产品 class SpringTextField implements TextField { public void display() { System.out.println("显示绿色边框文本框。"); } } //Summer文本框类:具体产品 class SummerTextField implements TextField { public void display() { System.out.println("显示蓝色边框文本框。"); } } //组合框接口:抽象产品 interface ComboBox { public void display(); } //Spring组合框类:具体产品 class SpringComboBox implements ComboBox { public void display() { System.out.println("显示绿色边框组合框。"); } } //Summer组合框类:具体产品 class SummerComboBox implements ComboBox { public void display() {ystem.out.println("显示蓝色边框组合框。"); } } //界面皮肤工厂接口:抽象工厂 interface SkinFactory { public Button createButton(); public TextField createTextField(); public ComboBox createComboBox(); } //Spring皮肤工厂:具体工厂 class SpringSkinFactory implements SkinFactory { public Button createButton() { return new SpringButton(); } public TextField createTextField() { return new SpringTextField(); } public ComboBox createComboBox() { return new SpringComboBox(); } } //Summer皮肤工厂:具体工厂 class SummerSkinFactory implements SkinFactory { public Button createButton() { return new SummerButton(); } public TextField createTextField() { return new SummerTextField(); } public ComboBox createComboBox() { return new SummerComboBox(); } }
单例模式
保证一个类有且仅有一个实例,提供一个全局访问点。
实现方法有私有静态域、双检锁懒加载及静态内部类(原理是,类在被使用时才会被装载,实现懒加载)。
Builder模式
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
使用Buider模式可以使客户端不必知道产品内部组成的细节。对构造过程进行更加精细的控制。
public abstract class House //定义一个房屋抽象类 { } public abstract class Builder //这一部分是易变的 { public abstract void BuildFloor(); //地板 public abstract void BuildDoor(); //门 public abstract void BuildWindows(); //窗户 public abstract void BuildWall(); //墙壁 public abstract void BuildHouseCeiling() //天花板 public abstract House GetHouse(); } public class RomanHouseBuilder : Builder { public override void BuildDoor() { } public override void BuildFloor() { } public override void BuildWindows() { } public override void BuildWall() { } public override void BuildHouseCeiling() { } public override House GetHouse() { } } public abstract class GameManager { public static House CreateHouse(Builder builder) { builder.BuildFloor(); builder.BuildDoor(); builder.Buildwall(); builder.BuildWindows(); builder.BuildHouseCeiling(); return builder.GetHouse(); } }
Lombok也有个builder,大致都差不多,都是通过builder类一步步构造出需要的对象,最后再调用build方法返回需要的对象。