概念
工厂模式:创建型模式。根据定义一个工厂父类来定义创建对象的公共接口,而子类负责生成特定对象。
工厂模式主要分为普通工厂模式(又叫简单工厂模式)、工厂方法模式和抽象工厂模式这三种模式。
普通工厂模式(简单工厂模式):
普通工厂模式也叫简单工厂模式,简单的说它就是创建了一个公共的接口工厂类,然后其他类都实现这个接口。 在该模式中,工厂类是整个模式的关键。它有着一个必要的判断逻辑,能够根据你的需要来创建所需要的实例。使用者使用的时候无需知道这些对象是怎么样创建的,也不用去关心这些。这有利于整个软件系统的优化构架。
但是他也有缺点,因为工厂类含有所有实例的创建逻辑,所以它不适合“高内聚”。还有当系统中特定产品类的数量增加时,可能需要工厂类也同样做出调整,因此它的可伸缩性和扩展性不好。
代码:
1、创建一个公用的接口类
public interface SendMsg {
public void sendMsg();
}
实现这个接口
public class SendMsg1 implements SendMsg {
@Override
public void sendMsg() {
System.out.println("this is SendMsg1 !");
}
}
public class SendMsg2 implements SendMsg {
@Override
public void sendMsg() {
System.out.println("this is SendMsg2!");
}
}
为这两个类创建工厂类,使用户能够通过该方法输入目标类的参数直接构建对象,而不需要记住很多类似但不同名字的类了。
public class SendFactory {
public SendMsg produce(String type) {
if ("sendMsg1".equals(type)) {
return new SendMsg1();
} else if ("sendMsg2".equals(type)) {
return new SendMsg2();
} else {
System.out.println("正在开发中!");
return null;
}
}
}
在简单工厂模式中只提供一个工厂类,该工厂类处于对产品类进行实例化的中心位置,它需要知道每一个产品对象的创建细节,并决定何时实例化哪一个产品类。简单工厂模式最大的缺点是当有新产品要加入到系统中时,必须修改工厂类,需要在其中加入必要的业务逻辑,这违背了“开闭原则”。此外,在简单工厂模式中,所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。
————————————————
版权声明:本文为CSDN博主「梦之归途」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lwzhang1101/article/details/88566756
工厂方法模式
在工厂方法模式结构图中包含如下几个角色:
- Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
- ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
- Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
- ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。
在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延续到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。
与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂可以是接口,也可以是抽象类或者具体类
抽象工厂类代码:
interface Factory {
public Product factoryMethod();
}
具体类实现抽象工厂类代码
class ConcreteFactory implements Factory {
public Product factoryMethod() {
return new ConcreteProduct();
}
}
demo
问题:现有电脑产品windows和apple,请试用工厂模式描述该场景。
思路:根据描述,我们可以先创建两个产品类:Windows类和Apple类,然后定义一个产品接口,让这两个类实现接口方法表示类已经创建。
product代码:
public interface Product {
public void run();
}
public class Windows implements Product {
@Override
public void run() {
System.out.println("product windows run!");
}
}
public class Apple implements Product{
@Override
public void run() {
System.out.println("product apple run!");
}
}
工厂代码
public interface MyFactory {
public Product createProduct();
}
public class WindowsFactory implements MyFactory{
@Override
public Product createProduct() {
// TODO Auto-generated method stub
return new Windows();
}
}
public class AppleFactory implements MyFactory{
@Override
public Product createProduct() {
// TODO Auto-generated method stub
return new Apple();
}
}
抽象工厂模式
抽象工厂模式乃是一个工厂生产多种产品。例如生产carA,carB,truckA,truckB。那么可以把A和B堪称两个工厂,分别生成carA、truckA和carB、truckB。
构造代码块,构造方法和静态代码块
1. 区分:
首先构造代码块和构造方法都是为了构造,所以在每次创建对象时都会执行。不同点在于构造代码块是默认执行的,对所有创建的对像都一样。而构造方法是针对特定的对象传入值的。例如下面的代码实例。对于对象stu1和对象stu2,其area都会被赋值为"北京”。静态代码块就是静态数据,只在第一次创建时执行,为所有对象公用。
代码来自java构造代码块的使用
public class day16 {
public static void main(String[] args) {
System.out.println("****创建第一个学生****");
Student stu1=new Student("小明");
System.out.println(stu1.area);
System.out.println();
System.out.println("****创建第二个学生****");
Student stu2=new Student(13);
System.out.println(stu1.area);
}
}
class Student{
String area;
String name;
int age;
{
area="北京";
System.out.println("所在地区:"+area);
}
Student(String name){
this.name=name;
System.out.println("姓名:"+this.name);
}
Student(int age){
this.age=age;
System.out.println("年龄:"+this.age);
}
}
执行结果:
****创建第一个学生****
所在地区:北京
姓名:小明
北京
****创建第二个学生****
所在地区:北京
年龄:13
北京
2.执行顺序:
构造代码块和构造方法是创建对象的,当然每次创建对象都会使用,且固定顺序为先代码块,后构造方法。所以如果再在构造方法中将属性area赋值为上海,那么对象的属性也会变成上海。静态代码块只在第一次创建对象时执行,由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
例子:A和B中都有构造代码块,构造方法和静态代码块。且B继承A
代码在这
创建3次A对象。静态方法执行一次,且最先执行。之后是构造代码块先执行,后执行构造方法。
创建B对象,代码执行顺序如下:发现静态代码块一定是最先执行的。之后是构造代码块和构造方法捆绑执行。