JAVA设计模式之工厂模式

设计模式

设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

六大原则:

单一职责原则:
不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分

里氏替换原则(Liskov Substitution Principle):
子类可以扩展父类的功能,但不能改变父类原有的功能。父类能出现的地方都可以用子类来代替,而且换成子类也不会出现任何错误或异常,而使用者也无需知道是父类还是子类,但反过来则不成立。总之,就是抽象。

依赖倒转原则(Dependence Inversion Principle):
面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互

接口隔离原则(Interface Segregation Principle):
每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

迪米特法则(最少知道原则)(Demeter Principle):
一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

合成复用原则(Composite Reuse Principle):
尽量首先使用合成/聚合的方式,而不是使用继承。

工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。工厂模式有两种,一种是单一工厂,即用一个工厂就可以根据业务创建出不同的产品对象,又称简单工厂模式;另一种是多个工厂,每个工厂对应一个产品对象,又称工厂方法模式。

简单工厂模式

思想:根据业务需求,将所需要的产品‘告诉’工厂,由工厂去创建对象。

 产品接口
public interface Phone {
    public void getColor();
}
具体产品
public class Honor implements Phone {
    @Override
    public void getColor() {
        System.out.println("White");
    }
}
public class Huawei implements Phone {
    @Override
    public void getColor() {
        System.out.println("Black");
    }
}
产品工厂
public class PhoneFactory {
    public static Phone getPhone(String kind) {
        switch (kind) {
            case "Huawei":
                return new Huawei();
            case "Honor":
                return new Honor();
            default:
                return null;
        }
    }
}
测试
    public static void main(String[] args) {
        PhoneFactory factory = new PhoneFactory();
        Phone huawei = factory.getPhone("Huawei");
        huawei.getColor();
        Phone honor = factory.getPhone("Honor");
        honor.getColor();
    }
  • 优点:调用者只需要调用一个工厂对象,把创建对象的动作交给工厂,调用者不需要关心创建过程,只需要根据不同需求传递产品类型就创建出不同产品,降低了系统的耦合性。
  • 缺点:工厂管理所有对象的创建,每次新增一个产品,都需要改动工厂对象,长此以往工厂对象里管理的产品会越来越多越来越臃肿。

工厂方法模式

 思想:创建多个工厂对象,每个工厂对象对应一个产品。

产品接口
public interface Phone {
    public void getColor();
}
具体产品
public class Huawei implements Phone {
    @Override
    public void getColor() {
        System.out.println("Black");
    }
}
public class Honor implements Phone {
    @Override
    public void getColor() {
        System.out.println("White");
    }
}
产品工厂接口
public interface PhoneFactory {
    public Phone getPhone();
}
具体工厂
public class HuaweiFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        return new Huawei();
    }
}
public class HonorFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        return new Honor();
    }
}
测试
    public static void main(String[] args) {
        PhoneFactory huaweiFactory = new HuaweiFactory();
        Phone huawei = huaweiFactory.getPhone();
        huawei.getColor();
        PhoneFactory honorFactory = new HonorFactory();
        Phone honor = honorFactory.getPhone();
        honor.getColor();
    }
  • 优点:在简单工厂的基础上提高了扩展性,新增产品时不要改原来的代码,只需创建产品和和产品工厂。
  • 缺点:工厂和产品的耦合性高这就导致新增产品时就必须得新增产品工厂,增加了系统的复杂性。

抽象工厂模式

抽象工厂是对工厂方法模式的扩展,属于技术方面的升级。将工厂进行抽象化,让每个工厂只负责一个’系列‘的产品对象的创建,大大提高了系统的扩展性和实用性,同时也提高了复杂性!

产品接口

产品一:手机

public interface Phone {
    public void getColor();
}

产品二:电脑

public interface Computer {
    public void getPrice();
}
具体产品

产品一:手机

public class Huawei implements Phone {
    @Override
    public void getColor() {
        System.out.println("Black Huawei");
    }
}
public class Honor implements Phone {
    @Override
    public void getColor() {
        System.out.println("White Honor");
    }
}

产品二:电脑

public class MacBook implements Computer {
    @Override
    public void getPrice() {
        System.out.println("MacBook 15999");
    }
}
public class MateBook implements Computer {
    @Override
    public void getPrice() {
        System.out.println("MateBook 11999");
    }
}
工厂接口
public interface AbstractFactory {
    public Phone getPhone(String phone);
    public Computer getComputer(String computer);
}
具体工厂

工厂一:手机工厂

public class PhoneFactory implements AbstractFactory {
    @Override
    public Phone getPhone(String phone) {
        switch (phone) {
            case "huawei":
                return new Huawei();
            case "honor":
                return new Honor();
            default:
                return null;
        }
    }

    @Override
    public Computer getComputer(String computer) {
        return null;
    }
}

工厂二:电脑工厂

public class ComputerFactory implements AbstractFactory {
    @Override
    public Phone getPhone(String phone) {
        return null;
    }

    @Override
    public Computer getComputer(String computer) {
        switch (computer) {
            case "mac":
                return new MacBook();
            case "mate":
                return new MateBook();
            default:
                return null;
        }
    }
}
工厂选择器(这一步可有可无,实际业务中也可以直接创建工厂对象)
public class FactorySelector {
    AbstractFactory getFactory(String factory) {
        switch (factory) {
            case "phone":
                return new PhoneFactory();
            case "computer":
                return new ComputerFactory();
            default:
                return null;
        }
    }
}
测试
    public static void main(String[] args) {
        FactorySelector factorySelector = new FactorySelector();
        
        AbstractFactory phoneFactory = factorySelector.getFactory("phone");
        Phone huawei = phoneFactory.getPhone("huawei");
        huawei.getColor();
        Phone honor = phoneFactory.getPhone("honor");
        honor.getColor();
        
        AbstractFactory computerFactory = factorySelector.getFactory("computer");
        Computer macBook = computerFactory.getComputer("mac");
        macBook.getPrice();
        Computer mateBook = computerFactory.getComputer("mate");
        mateBook.getPrice();
    }
  • 优点:把工厂抽象化可以进一步的减少调用者和产品对象的耦合性,用户只需要根据需求去调用指定的工厂即可。
  • 缺点:从代码量上也可以看出来,系统更加复杂了,增加代码维护的困难性。

补充:看起来抽象工厂好像比工厂方法增加了很多代码,好像只是把生产工厂给包一层,有点画蛇添足。实际上要考虑到实际业务场景:很多产品不仅仅只有一个属性或者一个方法,有个对象会有很多功能,甚至涉及到其他对象,那么在设计项目框架时如果可以把相同属性的产品对象归属到一个系列,然后指定一个工厂去管理这个系列,这样就可以更好的去实现相应的业务。然后再把工厂给抽象化,让特定的需求去调用特定的工厂,这样无论是自己写代码还是别人根据代码去分析功能时都会思路非常清晰。

总结:

虽然说简单工厂模式是工厂模式的初版,工厂方法和抽象工厂模式对简单工厂都有了一定的扩展和加强,但是并不是说抽象工厂模式就是最好的,三者都有优缺点。代码是死的,人是活的,要根据实际业务场景去选择最匹配的模式!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值