简单工厂:用一个工厂类创建对象,kind=1创建 类1对象,kind=2创建 类2对象
工厂方法:一个工厂一个类,factory1创建 类1对象,factory2 创建 类2对象
抽象工厂:将CPU,SSD等组合起来,是工厂方法的组合
解决的问题
解决创建对象
简单工厂模式
两个类集成同一个接口,他们的实现不同。Factory类根据不同的方法或者参数不同来区别创建不同的类。同样Factory创建对象的方法可以有静态和非静态两种选择。
实现:见com.haiwei.create.simplefactory
分析:Client依赖的是Factory类,而不是接口,违反依赖倒置原则,导致扩展困难。
扩展:如果新增一种类,ImageSender,那么这时候就需要修SenderFactory,或者增加方法getImageSender,或者给createSender方法增加一个参数。这样违背了开闭原则。
优化:(工厂方法模式)
public class Main1 {
public static void main(String[] args) {
SenderFactory factory = new SenderFactory();
factory.getMailSender().Send();
factory.getSmsSender().Send();
SenderFactory2 factory2 = new SenderFactory2();
factory2.createSender("sms").Send();
factory2.createSender("mail").Send();
factory2.createSender("email").Send();
}
}
public class SenderFactory {
public Sender getMailSender(){
return new MailSender();
}
public Sender getSmsSender(){
return new SmsSender();
}
}
public class SenderFactory2 {
public Sender createSender(String kind){
switch (kind) {
case "mail":
return new MailSender();
case "sms":
return new SmsSender();
default:
throw new RuntimeException("Invalid kind:"+kind);
}
}
}
工厂方法模式
工厂:每个类都有自己的一个工厂类,赋值不同的工厂,创建的对象也不同。
实现:com.haiwei.create.factorymethod
分析:
- Client依赖的是Factory接口,Factory依赖的是Sender接口。而不是具体类
- 再次扩展时,只需要新建一个**Sender implement Sender,以及**Factory implement Factory接口即可。
public class Main2 {
public static void main(String[] args) {
Factory f1 = new MailSenderFactory();
f1.produce().Send();
f1 = new SmsSenderFactory();
f1.produce().Send();
}
}
抽象工厂模式
定义:提供一个创建一系列的相关的或者依赖的对象的接口,无需指定它们的具体实现类,具体的时间分别在子类工厂中产生。
示例:小米手机,红米5,红米6,两款手机,每款手机都包括:处理器,显示屏等。那么现在需要生产一个红米5,是不是需要生产:CPU5,Screen5等一系列对象, 这些零件对象聚合成了红米5。
| CPU | 显示屏 |
红米5 | CPU5 | Screen5 |
红米6 | CPU6 | Screen6 |
类图:
实现:com.haiwei.create.abstractfactory
public class main3 {
public static void main(String[] args) {
RedmiNoteFactory factory = new RedmiNote5Factory();
factory.print();
factory = new RedmiNote6Factory();
factory.print();
}
}
public class RedmiNote5Factory implements RedmiNoteFactory {
@Override
public CPU getCpu() {
return new CPU5();
}
@Override
public Screen getScreen() {
return new Screen5();
}
@Override
public void print() {
this.getCpu().value();
this.getScreen().name();
}
}