设计模式浅析
Contents
what is design pattern?
设计模式Design Pattern是一套代码设计经验的总结
代码中合理的运用设计模式可以解决很多问题
设计模式的三大类:
-
创建型模式(Creational Pattern):在软件设计中对象的创建和对象的使用是分开的,因为对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。
单例、工厂方法、抽象工厂、建造者、原型
-
结构型模式(Structural Pattern):在解决了对象的创建问题之后,对象的组成以及对象之间的依赖关系就成了开发人员关注的焦点,因为如何设计对象的结构、继承和依赖关系会影响到后续程序的维护性、代码的健壮性、耦合性等。
适配器、桥接、组合、装饰、外观、享元、代理
-
行为型模式(Behavioral Pattern):类和对象如何交互&划分责任
访问者、模板、策略、状态、观察者、备忘录、中介者、迭代器、解释器、命令、责任链
设计原则:
- 开闭:开放扩展,关闭修改
- 里氏替换:任何地方子类都能替换父类
- 依赖倒置:高层低层都依赖于抽象
- 单一职责:一个类只负责一项职责
- 接口隔离:使用多个专门的接口比使用单一的总接口要好
- 迪米特:将模块间的依赖和相互影响降到最低
- 合成复用:能用关联就别用继承
Creational Patterns
Simple Factory
- 实质:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例
- 包含的角色&职责:
- 工厂(Creator):负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象
- 抽象产品(Product):所有具体产品类的父类,它负责描述所有实例所共有的公共接口
- 具体产品(Concrete Product):该模式的创建目标,创建的具体实例对象
- 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
public interface Digital { void use(); } public class PadDigital implements Digital { @Override public void use() { System.out.println("product pad..."); } } public class PhoneDigital implements Digital { @Override public void use() { System.out.println("product phone..."); } } public class Factory { public Digital product(String name){ switch (name){ case "pad": return new PadDigital(); case "phone": return new PhoneDigital(); default: return null; } } } public class TestMain { public static void main(String[] args) { Factory factory = new Factory(); Digital pad = factory.product("pad"); Digital phone = factory.product("phone"); pad.use(); phone.use(); } }
- 适用场景:
- 工厂类创建的对象较少,种类比较固定的场景
- 客户端对具体创建的对象没有特殊要求,只需要使用对象的场景
- 对象创建仅需要一两个参数,依赖关系较简单的场景
- 存在一对一的对应关系,一个参数对应一个具体产品的场景
- 将来可能增加对象的概率较低,新增对象也较少的场景
Factory
- 实质:定义一个创建产品对象的工厂接口,将实际创建工作推迟到子工厂类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统不修改具体工厂角色的情况下引进新的产品。
- 包含的角色&职责:
- 抽象工厂(Creator):核心,任何具体工厂类都必须实现这个接口
- 具体工厂(Concrete Creator):抽象工厂的一个实现,负责实例化产品对象
- 抽象产品(Product):所有具体产品类的父类,它负责描述所有实例所共有的公共接口
- 具体产品(Concrete Product):创建的具体实例对象
- 代码实现;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
public interface Digital { void use(); } public class PadDigital implements Digital { @Override public void use() { System.out.println("product pad..."); } } public class PhoneDigital implements Digital { @Override public void use() { System.out.println("product phone..."); } } public interface Factory { Digital product(); } public class PadFactory implements Factory { @Override public Digital product() { System.out.println("product pad..."); return new PadDigital(); } } public class PhoneFactory implements Factory{ @Override public Digital product() { System.out.println("product phone..."); return new PhoneDigital(); } } public class TestMain { public static void main(String[] args) { Factory factory = new PadFactory(); Digital pad = factory.product(); factory = new PhoneFactory(); Digital phone = factory.product(); pad.use(); phone.use(); } }
- 适用场景:
- 适用于创建对象种类较多的场景。通过定义多个工厂子类来创建不同的对象,更易扩展
- 可以有更加复杂的判断逻辑来决定创建何种具体产品。可以根据复杂的参数或配置来决定具体创建的产品类型
- 通过定义抽象工厂类和多个具体工厂子类,很容易增加新的具体工厂和产品来扩展系统
- 对比:
- 简单工厂模式适用于产品种类较少、创建逻辑简单、对扩展性要求不高的场景。用户可以直接使用,无需知晓具体产品信息
- 工厂方法模式更加灵活和扩展性强,可以根据复杂的判断逻辑来创建不同的产品对象。适用于产品种类较多且需要灵活扩展的场景。用户一般需要知晓具体的产品和工厂类型
Abstract Factory
- 实质:工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类
- 包含的角色&职责:
- 抽象工厂(Creator):核心,任何具体工厂类都必须实现这个接口
- 具体工厂(Concrete Creator):某个产品族抽象工厂的一个实现,负责实例化产品对象
- 抽象产品(Product):所有具体产品类的父类,它负责描述所有实例所共有的公共接口
- 具体产品(Concrete Product):不同产品族下的具体实例对象
- 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
public interface Pad { void use(); } public interface Phone { void use(); } public class HuaweiPad implements Pad{ @Override public void use() { System.out.println("use huawei pad"); } } public class XiaomiPad implements Pad{ @Override public void use() { System.out.println("use xiaomi pad"); } } public class HuaweiPhone implements Phone{ @Override public void use() { System.out.println("use huawei phone"); } } public class XiaomiPhone implements Phone{ @Override public void use() { System.out.println("use xiaomi phone"); } } public interface Factory { Pad productPad(); Phone productPhone(); } public class HuaweiFactory implements Factory{ @Override public Pad productPad() { System.out.println("product huawei pad..."); return new HuaweiPad(); } @Override public Phone productPhone() { System.out.println("product huawei phone..."); return new HuaweiPhone(); } } public class XiaomiFactory implements Factory{ @Override public Pad productPad() { System.out.println("product xiaomi pad..."); return new XiaomiPad(); } @Override public Phone productPhone() { System.out.println("product xiaomi phone..."); return new XiaomiPhone(); } } public class TestMain { public static void main(String[] args) { Factory huaweiFactory = new HuaweiFactory(); Factory xiaomiFactory = new XiaomiFactory(); huaweiFactory.productPad().use(); huaweiFactory.productPhone().use(); xiaomiFactory.productPad().use(); xiaomiFactory.productPhone().use(); } }
- 适用场景:
- 如果系统中有多个产品族,而每个产品族都有多个产品,如果需要扩展新的产品族和产品时
- 对比:
- 工厂方法模式:创建同属一个产品族但等级不同的产品实例。客户需要知道具体的工厂类,才能得到所需要的产品。
- 抽象工厂模式:创建不同产品族之间相关联的产品实例。客户只需要知道抽象工厂类,即可得到一组相关产品。
Singleton
- 实质:保证一个类仅有一个实例,并提供一个访问该实例的全局访问点
- 包含的角色&职责:
- 代码实现:
- 适用场景:
- 对比:
Builder
- 实质:
- 包含的角色&职责:
- 代码实现:
- 适用场景:
- 对比:
ProtoType
- 实质:
- 包含的角色&职责:
- 代码实现:
- 适用场景:
- 对比: