首先来说下软件设计原则
- 开闭原则: 对扩展开放,对修改关闭。
- 单一职责原则: 一个类、接口、方法只做一件事。
- 依赖倒置原则: 通过抽象使各个类或者模块不相互影响,实现松耦合。
- 接口隔离原则: 尽量保证接口的纯洁性,客户端不应该依赖不需要的接口。
- 迪米特法则: 又叫最少知道原则,一个类对其所依赖的类知道得越少越好
- 里氏替换原则: 子类可以扩展父类的功能但不能改变父类原有的功能。
- 合成复用原则: 尽量使用对象组合、聚合,而不使用继承关系达到代码复用的目的。
设计模式从来都不是单独存在的, 从来都你中有我, 我中有你
工厂模式
分为 简单工厂模式, 工厂方法模式, 抽象工厂模式
简单工厂
是指由一个工厂对象决定创建出哪一种产品类的实例。
属于创建型模式,但它不属于GOF,23种设计模式。
- 使用场景: 工厂类负责创建的对象较少, 客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需 要关心
- 优点: 只需传入一个正确的参数,就可以获取你所需要的对象, 无须知道其创建的细节。
- 缺点: 工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则。不易于扩展过于复杂的产品结构。
-
public interface ICow { void color(); } public class BlackCow implements ICow { @Override public void color() { System.out.println("颜色是黑色的"); } } public class WhiteCow implements ICow { @Override public void color() { System.out.println("颜色是白色的"); } } /** * 不管白牛黑牛,只要是牛 我这里都有, 但是缺点就是职责相对过重增加新的产品时需要修改工厂类的判断逻辑,违背开闭原 * 则。不易于扩展过于复杂的产品结构。 */ public ICow create(String name) { if ("black".equals(name)) { return new BlackCow(); } else if ("white".equals(name)) { return new WhiteCow(); } return null; }
工厂方法模式 - 属于创建型设计模式
是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
- 适用场景: 创建对象需要大量重复的代码。 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。 一个类通过其子类来指定创建哪个对象。
- 优点: 用户只需关心所需产品对应的工厂,无须关心创建细节。加入新产品符合开闭原则,提高了系统的可扩展性。
- 缺点: 类的个数容易过多,增加了代码结构的复杂度。增加了系统的抽象性和理解难度。
public interface ICowFactory {
ICow create();
}
public class BlackCowFactory implements ICowFactory {
@Override
public ICow create() {
return new BlackCow();
}
}
public class WhiteCowFactory implements ICowFactory {
@Override
public ICow create() {
return new WhiteCow();
}
}
public class FactoryMethodTest {
/**
* @ TODO 怎么样保证这个方法去创建对各产品呢?
* @ TODO 1. 要做到单一职责的原则, 就是把创建一个产品的逻辑放到一个类里面, 作为一个单个工厂,
* @ TODO 2. 而这个工厂又要实现一个抽象的规则/规范,
* @ TODO 3. 所以有一个顶层的接口
*/
public static void main(String[] args) {
ICowFactory factory = new BlackCowFactory();
factory.create().color();
ICowFactory factory1 = new WhiteCowFactory();
factory1.create().color();
}
}
抽象工厂模式 - 属于创建型设计模式
是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。
- 适用场景: 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
- 优点: 具体产品在应用层代码隔离,无须关心创建细节将一个系列的产品族统一到一起创建。
- 缺点: 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。 增加了系统的抽象性和理解难度。
/**
* 最顶层的接口,
* @ TODO 要求所有的子工厂都实现这个工厂
* @ TODO 一个平台的抽象, 一个标准的抽象, 然后可以以一个标准发下 牛, 牛奶 等等, 但是你在这里加了, 他所有的实现类都需要加, 这就是他的一大缺点
*/
public interface ICowFactory {
/**
* 可以创建 Cow-牛
*
* @return ICow
*/
ICow createCow();
/**
* 也可以创建牛奶
*
* @return Milk
*/
IMilk createMilk();
/**
* TODO 需要什么加什么
*/
}
public class WhiteCowFactory implements ICowFactory {
@Override
public ICow createCow() {
return new WhiteCow();
}
@Override
public IMilk createMilk() {
return new WhiteMilk();
}
}
public class AbstractFactoryTest {
/**
* @ TODO 优点: 我们需要扩展的话, 并不需要动其他的代码, 只需要增加一个工厂实现(就是一个产品族(类), 一个方法就是一个产品等级结构 )
* @ TODO 缺点: 就是增加一个产品族实现就一定需要实现它所有的方法
* @ TODO 根据缺点来说 其他抽象工厂不符合开闭原则, 但是扩展性非常强
* @ TODO 如果你的产品经常变动(产品等级结构), 那么不适合使用抽象工厂了
*/
public static void main(String[] args) {
ICowFactory factory = new WhiteCowFactory();
// TODO 直接使用第一个对象
factory.createCow().color();
// TODO 直接使用第二个对象
factory.createMilk().create();
}
}
产品族与产品等级结构区别:
- 产品族: 理解为一个品牌, 例如: 三星, 华为, 联想,
- 产品等级结构: 可以理解为这个品牌的某一个系的产品, 如: 三星的手机, 华为的手机, 联想的手机, 或者三星的显示器, 华为的显示器, 联想的显示器, 这就是一个产品等级
区别:
简单工厂模式: 就好像杂货铺一样, 什么都能买到, 但是造成了, 很难扩展, 涉及到的东西提多了
工厂方法模式: 就好像专卖店一样, 一个店面买一个品牌, 难于管理(多).
抽象工厂模式: 就好像大型商业百货, 但是扩展麻烦