国际惯例,扯闲篇
今天阴天,很开心,前几天的大太阳晒得我更黑了~~~
面向对象设计的基本原则
OCP(开闭原则):一个软件的实体应当对扩展开发,对修改关闭。对于已完成的类,尽可能地不要去修改其内容
DIP(依赖倒转原则):要针对接口编程,不要针对实现编程。这样会让代码更易读,不会经常写着写着就晕头转向
Lod(迪米特法则):只与你直接的朋友通信,避免和陌生人通信。
设计模式也好,基本原则也罢,都应该揉进平时的工作中去思考,用它们来指导完成代码的设计,书写
核心本质
- 实例化对象,用工厂方法代替new操作
- 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
工厂模式分类
-
简单工厂模式:用来修改同一等级结构中的产品(对于增加新的产品,需要修改已有代码)
-
工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)
-
抽象工厂模式:用来生产不同产品族的全部产品(对于增加新的产品无能无力,支持增加新的产品族)
Talk is cheap,show me the code!!!
简单工厂模式
遵循前面介绍的基本原则,我们先新建一个Car接口,给一个run方法
public interface Car {
void run();
}
接着,新建两个实现该接口的类:Audi,Benz
public class Audi implements Car {
@Override
public void run() {
Log.d("", "奥迪run: ");
}
}
public class Benzi implements Car {
@Override
public void run() {
Log.d("", "奔驰run: ");
}
}
现在,再创建一个调用者Client,来调用它们的run方法。
在没有使用简单工厂模式的情况下,这样写:
public class Client {
Car myCar = new Audi();
private void test() {
myCar.run();
}
}
这样写显然没有什么错,清晰明了,但是,我们的调用者Client却需要知道Audi这个类名,还需要知道它的构造方法去new出这个对象,当Audi这个类的构造方法比较复杂的时候,就要传很多参数,对我们的调用者来说,显然是十分麻烦的,我们只是想调用一下run方法而已。
那么,当使用了简单工厂模式后,写法如下:
public class CarFactory {
private Car createCar(String type) {
switch (type) {
case "奥迪":
return new Audi();
//就别break了,都return了
case "奔驰":
return new Benzi();
default:
break;
}
return null;
}
}
此时,当我们再想调用Audi的run方法,只需跟CarFactory打交道即可,至于CarFactory内部,到底经历多复杂的过程,才把这个Audi构造出来,我们调用者不想管,也不用管。
缺点
或许你已经注意到了,简单工厂方法模式显然违反了一开始就提到的OCP开闭原则,当我们想要创建一个比亚迪呢?显然是要在createCar方法里进行修改,再加一个case “比亚迪”:
case "比亚迪"
return new BYD();
简单工厂模式也被称为静态工厂模式,因为工厂类一般是使用静态方法,方便调用。当然了,上面只是示意写法,看懂意思就好,别较真。
工厂方法模式
上面提到了简单工厂模式,违背了开闭原则,使用工厂方法模式就可以解决掉这个问题(尽管如此,还是简单工厂模式用的最多)
怎么写呢?
Audi还是那个Audi,Benz还是那个Benz,Car还是那个Car,具体写法如下(以调Audi的run为例):
/**
* 新增一个CarFactory
*/
public interface CarFactory {
Car createCar();
}
当我们想调Audi的run的时候,就新增一个AudiFactory,实现CarFactory接口:
public class AudiFactory implements CarFactory{
@Override
public Car createCar() {
return new Audi();
}
}
那么调用者的写法就变成了:
public class Client {
private void test() {
Car audi = new AudiFactory().createCar();
audi.run();
}
}
此时,我们再想增加一个比亚迪的话,就再写一个BYDFactory类,而不用去修改已有的代码了。
虽然工厂方法模式贴合了开闭原则,却多写了很多个类,每增加一个新的产品就要多一个Factory。
选择:
理论上,工厂方法模式占优,实际上,选择简单工厂模式居多。
抽象工厂模式
- 用来生产不用产品族的产品
- 工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式生产需要的对象是一种非常好的解决方式
场景模拟:
在上文中,我们只创建一个Car接口,需求是生产该接口下的实现类对象,如果现在的接口变多了,需求变成生产多个接口下的子类对象呢?
定义一个Engine接口,两个实现该接口不同类:GoodEngine,BadEngine
public interface Engine {
void run();
void start();
}
//好发动机
class GoodEngine implements Engine {
@Override
public void run() {
Log.d("", "转得快");
}
@Override
public void start() {
Log.d("", "启动快 ");
}
}
//差发动机
class BadEngine implements Engine{
@Override
public void run() {
Log.d("", "转得慢");
}
@Override
public void start() {
Log.d("", "启动慢");
}
}
再定义一个Seat接口,两个实现该接口的不同类:GoodSeat,BadSeat
public interface Seat {
void massage();
}
class GoodSeat implements Seat{
@Override
public void massage() {
Log.d("", "可以按摩");
}
}
class BadSeat implements Seat{
@Override
public void massage() {
Log.d("", "不能按摩");
}
}
定义一个CarFactory接口
public interface CarFactory {
Engine createEngine();
Seat createSeat();
}
定义两个实现该接口的不同工厂类,来生产不同的产品族
public class BadCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new BadEngine();
}
@Override
public Seat createSeat() {
return new BadSeat();
}
}
public class GoodCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new GoodEngine();
}
@Override
public Seat createSeat() {
return new GoodSeat();
}
}
结语:
上一次的文章,回过头来看,好短小,与我本人不贴切,所以这次的文章,夹杂了不少自己的废话,万望海涵,错误的地方还请大家帮忙指正,多谢!!!拜拜~~