工厂模式是一种“对象创建”模式。它是为了在面向接口编程时,避免new object时对具体class的紧耦合的产物。典型的对象创建模式有工厂方法Factory Method, 抽象工厂Abstract Factory, Prototype, Builder.
工厂方法 Factory Method
要点是,通过method返回new的具体对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public abstract class Product { }
public class ProductA extends Product { }
public class Creator { public static Product CreateProduct(string parameter) { if (parameter == "A") { return new ProductA(); } else { } } }
public class Program { public static void main(string[] args) { Product myProduct = Creator.CreateProduct("A"); } }
|
其实就是在使用时,不要直接new 具体的ProductA or B。那这样有什么好处呢?这个回答工厂模式的本质是什么写的不错,一般在创建过程比较复杂时使用。那什么是复杂的创建过程呢?有几个例子:
eg1:创建的对象在一个pool里,不是每次都要重新new一个全新的。比如连接池对象,线程池对象。
eg2:具体class的作者希望隐藏对象真实的的类型。
eg3:对象创建时,在不同参数下返回不同的对象。
eg4,5:对象创建时有很多参数,或者有复杂的依赖关系。简化超长构造函数。
eg6:你知道怎么创建一个对象,但是无法把控创建的时机。你需要把“如何创建”的代码塞给“负责什么时候创建”的代码。后者在适当的时机,就回调创建的函数。
eg7:构造函数不能throw exception,但是工厂方法可以呀。
读到这里,我相信聪明的你肯定已经学会了什么是工厂方法。接下来我们了解抽象工厂。
抽象工厂 Abstract Factory
话不多说,上代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public abstract class Product { }
public class ProductA extends Product { }
public abstract class AbstractCreator { public abstract Product CreateProduct(string parameter); }
public class Creator extends AbstractCreator { public Product CreateProduct(string parameter) { if (parameter == "A") { return new ProductA(); } else { } } }
public class Program { public static void main(string[] args) { AbstractCreator aCreator = new Creator(); Product myProduct = aCreator.CreateProduct("A"); } }
|
也就是说,它只是把简单的工厂方法中的工厂Creator进行了进一步的抽象。那这样有什么好处呢?
当我们突然想换个工厂,改动就少很多了!
原型模式 Prototype Pattern
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class Main implements Cloneable { @Override public Main clone() { Mail = null; try { mail = (Main)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return mail; } }
public class Client { private static int MAX_COUNT = 600; public static void main(string[] args) { Mail mail = new Mail(); for (int i = 0; i < MAX_COUNT; ++i) { Mail cloneMail = mail.clone(); cloneMail.setReiver("..."); sendMail(cloneMail); } } }
|
好处
- 性能优良 原型模式是在内存二进制流的拷贝, 要比直接new一个对象性能好很多, 特别是要在一 个循环体内产生大量的对象时, 原型模式可以更好地体现其优点。
- 逃避构造函数的约束 这既是它的优点也是缺点, 直接在内存中拷贝, 构造函数是不会执行的。 优点就是减少了约束, 缺点也是减少了约束, 需要大家在实际应用时考虑。
使用场景
资源优化场景 类初始化需要消化非常多的资源, 这个资源包括数据、 硬件资源等。
性能和安全要求的场景 通过new产生一个对象需要非常繁琐的数据准备或访问权限, 则可以使用原型模式。
一个对象多个修改者的场景 一个对象需要提供给其他对象访问, 而且各个调用者可能都需要修改其值时, 可以考虑 使用原型模式拷贝多个对象供调用者使用。
在实际项目中, 原型模式很少单独出现, 一般是和工厂方法模式一起出现, 通过clone的 方法创建一个对象, 然后由工厂方法提供给调用者。 原型模式已经与Java融为一体, 大家可 以随手拿来使用。
建造者模式
秒懂设计模式之建造者模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| public class Computer { private String cpu; private String ram; private int usbCount; private String keyboard; private String display;
public Computer(String cpu, String ram) { this.cpu = cpu; this.ram = ram; } public void setUsbCount(int usbCount) { this.usbCount = usbCount; } public void setKeyboard(String keyboard) { this.keyboard = keyboard; } public void setDisplay(String display) { this.display = display; } @Override public String toString() { return "Computer{" + "cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + ", usbCount=" + usbCount + ", keyboard='" + keyboard + '\'' + ", display='" + display + '\'' + '}'; } }
public abstract class ComputerBuilder { public abstract void setUsbCount(); public abstract void setKeyboard(); public abstract void setDisplay();
public abstract Computer getComputer(); }
public class MacComputerBuilder extends ComputerBuilder { private Computer computer; public MacComputerBuilder(String cpu, String ram) { computer = new Computer(cpu, ram); } @Override public void setUsbCount() { computer.setUsbCount(2); } @Override public void setKeyboard() { computer.setKeyboard("苹果键盘"); } @Override public void setDisplay() { computer.setDisplay("苹果显示器"); } @Override public Computer getComputer() { return computer; } }
public class LenovoComputerBuilder extends ComputerBuilder { private Computer computer; public LenovoComputerBuilder(String cpu, String ram) { computer=new Computer(cpu,ram); } @Override public void setUsbCount() { computer.setUsbCount(4); } @Override public void setKeyboard() { computer.setKeyboard("联想键盘"); } @Override public void setDisplay() { computer.setDisplay("联想显示器"); } @Override public Computer getComputer() { return computer; } }
public class ComputerDirector { public void makeComputer(ComputerBuilder builder){ builder.setUsbCount(); builder.setDisplay(); builder.setKeyboard(); } }
public static void main(String[] args) { ComputerDirector director=new ComputerDirector(); ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125"); director.makeComputer(builder); Computer macComputer=builder.getComputer(); System.out.println("mac computer:"+macComputer.toString()); ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222"); director.makeComputer(lenovoBuilder); Computer lenovoComputer=lenovoBuilder.getComputer(); System.out.println("lenovo computer:"+lenovoComputer.toString()); }
|