1、我们通常说的 23 中经典设计模式可以通过下表一目了然:
分类 设计模式
工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、
建造者模式(Builder)、原型模式(Prototype)、单例模式(Singleton)
适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、
装饰器模式(Decorator)、门面模式(Facade)、享元模式(Flyweight)、
代理模式(Proxy)
解释器模式(Interpreter)、模板方法模式(Template Method)、
责任链模式(Chain of Responsibility)、命令模式(Command)、
迭代器模式(Iterator)、调解者模式(Mediator)、备忘录模式(Memento)、
观察者模式(Observer)、状态模式(State)、策略模式(Strategy)、
访问者模式(Visitor)
通常来说,设计模式都是混合使用,不会独立应用。利用穷举法充分理解设计模式的应用场景。在平时
的应用中,不是用设计模式去生搬硬套,而是根据具体业务问题需要时借鉴。
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现
一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的
效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原
则中说,任何基类可以出现的地方,子类一定可以出现。 LSP 是继承复用的基石,只有当衍生类可以
替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增
加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而
基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,
从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。
所以上文中多次出现:降低依赖,降低耦合。
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能
模块相对独立。
原则是尽量使用合成/聚合的方式,而不是使用继承。
应用场景:又叫做静态工厂方法(StaticFactory Method)模式,但不属于 23 种设计模式之一。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 Bean 对象,但
是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
应用场景:通常由应用程序直接使用 new 创建新的对象,为了将对象的创建和使用相分离,采用工厂模
式,即应用程序将对象的创建及初始化职责交给工厂对象。
一般情况下,应用程序有自己的工厂对象来创建 Bean.如果将应用程序自己的工厂对象交给 Spring 管
理,那么 Spring 管理的就不是普通的 Bean,而是工厂 Bean。
/**
* 牛奶接口
*/
public interface Milk {
//获取牛奶名
String getName();
}
/**
* 伊利牛奶
*/
public class YiliMalk implements Milk {
public String getName() {
return "伊利牛奶";
}
}
public class MengNiuMilk implements Milk {
public String getName() {
return "蒙牛牛奶";
}
}
/**
* 简单牛奶工厂方法
*/
public class SimpleFactoryMail {
/**
* 根据牛奶名称获取对应牛奶
* @param name 牛奶名称
* @return 牛奶
*/
public Milk getMilk(String name){
if ("伊利".equals(name)){
return new YiliMalk();
}else if ("蒙牛".equals(name)){
return new MengNiuMilk();
}else {
System.out.println("你所输入的牛奶名称,没有对应的牛奶");
return null;
}
}
}
public class SimpleFactoryMailTest {
@Test
public void getMilk() {
//这个new的过程实际上一个比较复杂的过程
//有人民币及不需要自己new了
// System.out.println(new Telunsu().getName());
//小作坊式的生产模式
//用户本身不再关心生产的过程,而只需要关心这个结果
//假如:特仑苏、伊利、蒙牛
//成分配比都是不一样的
SimpleFactoryMail factory = new SimpleFactoryMail();
//把用户的需求告诉工厂
//创建产品的过程隐藏了,对于用户而且完全不清楚是怎么产生的
System.out.println(factory.getMilk("伊利"));
System.out.println(factory.getMilk("蒙牛"));
System.out.println(factory.getMilk("三鹿"));
/**
* 输出:
* com.wondersgroup.jg.sscl.factory.YiliMalk@694f9431
* com.wondersgroup.jg.sscl.factory.MengNiuMilk@f2a0b8e
* 你所输入的牛奶名称,没有对应的牛奶
* null
*/
//知其然,知其所以然,知其所必然
}
}
创建一个工厂模型有统一的产品出口,其他产品工厂实现这个模型,使用产品工厂生产各自的产品
/**
* 工厂模型
*/
public interface Factory {
//工厂必然具有生产产品技能,统一的产品出口
Milk getMilk();
}
/**
* 伊利工厂
*/
public class YiliFactory implements Factory {
public Milk getMilk() {
return new YiliMalk();
}
}
public class MengniuFactory implements Factory {
public Milk getMilk() {
return new MengNiuMilk();
}
}
public class FactoryTest {
@Test
public void getMilk() {
//System.out.println(new Factory().getMilk(););
//货比三家
//不知道谁好谁好谁坏
//配置,可能会配置错
Factory factory = new YiliFactory();
System.out.println(factory.getMilk());
}
}
抽象工厂是用户的主入口在Spring中应用得最为广泛的一种设计模式 易于扩展
定义一个抽象工厂模型,里面提供各个产品的抽象获取方法,工厂模型的子类来实现这些方法,易于扩展,便于统一管理,控制产品的类型生成
/**
* 抽象工厂是用户的主入口
* 在Spring中应用得最为广泛的一种设计模式
* 易于扩展
*/
public abstract class AbstractFactory {
//公共的逻辑
//方便于统一管理
/**
* 获得一个蒙牛品牌的牛奶
* @return
*/
public abstract Milk getMengniu();
/**
* 获得一个伊利品牌的牛奶
* @return
*/
public abstract Milk getYili();
/**
* 获得一个特仑苏品牌的牛奶
* @return
*/
public abstract Milk getTelunsu();
public abstract Milk getSanlu();
}
public class MilkFactory extends AbstractFactory {
public Milk getMengniu() {
// 实现方法一,可以直接返回产品,这里只使用了抽象工厂模式
return new MengNiuMilk();
}
public Milk getYili() {
// 实现方法二:使用工厂方法生成的产品返回,这里使用了抽象工厂和工厂方法的组合,在实际工作中,这种使用较多
return new YiliFactory().getMilk();
}
public Milk getTelunsu() {
// 扩展代码不在演示
return null;
}
public Milk getSanlu() {
// 扩展代码不在演示
return null;
}
}
public class MilkFactoryTest {
@Test
public void getMengniu() {
MilkFactory factory = new MilkFactory();
//对于用户而言,更加简单了
//用户只有选择的权利了,保证了程序的健壮性
System.out.println(factory.getMengniu());
/**
* 输出:
* com.wondersgroup.jg.sscl.factory.MengNiuMilk@694f9431
*/
}
}