设计模式常常分为如下三类:
创建型:创建对象时,不在直接实例化对象;而是根据特定场景,由应用程序来确定创建对象的方式,从而保证更高的性能,更好的架构优势。创建型模式主要有简单工厂模式、工厂方法、抽象工厂模式、单列模式、生成器和原型模式。
结构型:用于帮助多个对象组织成更大的结构。结构型模式主要有适配器模式、桥接模式、组合器模式、装饰器模式、门面模式、享元模式和代理模式。
行为型:用于帮助系统间各对象的通信,以及如何控制复杂系统中的流程。行为型模式主要有命令模式、解释器模式、迭代模式、中介者模式、备忘录模式、状态模式、策略模式、模板模式、访问这模式。
1、单列模式
有些时候,运行自由创建某个类实例没有意义,还有可能造成系统性能下降(因为创建对象所带来的系统开销问题)。
主要点:
1)将构造器用private修饰
2)提供一个public static方法,供获取该类对象
3)该类需缓存一个已经创建的对象,否则该类无法知道是否已经创建对象。
示例如下:
class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
2、简单工厂模式
将多个对象交给工厂来生成的设计方式被称为简单工厂模式。
例如A类依赖于B类。对于A类而言,它并不关心B对象的实现、创建过程。考虑B类实现一个IB接口,而A类只需要与IB接口耦合——A类并不直接使用new关键字来创建B实例,而是重定义一个工厂类:IBFactory,由该工厂来负责创建IB实现,而A类通过调用IBFactory工厂的方法来得到IB的实例。
下面一个简单的实例来说明简单工厂模式:假设有个Computer对象需要依赖一个输出设备(Printer对象)。让Computer类依赖output属性,将computer类与printer类实现分离,Computer对象只需面向output接口编程即可。computer对象具体依赖哪个实现类完全透明。
public class Computer{
private Output out;
public Computer (Output out){
this.out = out;
}
public void keyIn(String msg){
out.getData(msg);
}
public void print(){
out.out();
}
public static void main(String[] args){
outputFactory of =new outputFactory ();
Computer c = new Computer(of.getOutput());
c.keyIn("轻量级java“);
c.print();
}
}
以上代码可以看出computer类与printer类已经分离了,只是与该接口耦合。而且Computer不再负责创建output对象,系统将提供一个Output工厂类负责生成output对象,outputFactory工厂类如下:
public class OutputFactory{
public Output getOutput(){
return new Printer();
}
}
以上类提供一个getOutput()方法,该方法返回一个output实例,该方法负责创建output实例,具体创建哪一个实现类的对象,则由该方法决定。
程序清单: Printer.java代码如下:
public class Printer{
private String[] printData = new String[MAX_CACHE_LINE);
//用以记录当前需打印的页数
private int dataNum=0;
public void out(){
//z只要有作业,继续打印
System.out.println("打印机打印:” + printData[0];
//把作业队列整体前移一位,并将剩下的作业数减一
System.arraycopy(printData,1,printData,0,--dataNum);
}
}
public void getData(String msg){
if(dataNum >= MAX_CACHE_LINE){
System.out.println("输出队列已满,添加失败“);
}else{
printData[dataNum++] = msg;
}
}
}
上面的printer类模拟了一个简单的打印机,如果系统需要重构,需要使用BetterPrinter来代替Printer类,则需要让BetterPrinter师兄Output接口,并改下OutputFactory类的getOutput()方法。
将OutputFactory类的getOutput()方法改成如下:
return new BetterPrinter();
通过这种方式,可以把所有生成Output对象的逻辑集中在OutputFactory工厂类中管理,所有需要Output对象的类需要与Output接口耦合,而不是与具体的实现类耦合,即使系统中有很多类依赖Printer对象,只需要修改OutputFactory类的getOutput()方法,返回BetterPrinter对象即可。
使用简单工厂模式的优势:让对象的调用者和对象的创建过程分离,当对象调用者需要对象时,直接向工厂请求即可,从而避免对象的调用和对象的实现类以硬编码方式耦合。以提供系统的维护性、扩展性。但工厂模式有个小缺陷:当产品修改时,对应的工厂类也需要修改。
3、抽象工厂
在简单工厂模式里,系统使用工厂类生产所有产品实例,且改工厂类决定生产哪个类的实例,即该工厂类负责所有的逻辑判断、实例创建工作。
如果不想在工厂类中进行逻辑判断,程序为不同的产品类提供不同的工厂,不同的工厂类生产不同的产品。例如为上面的Printer、BetterPrinter提供PrinterFactory和BetterFactory工厂类。
本示例将2中的outputFactory该为一个接口,并为该接口提供两个实现类:PrinterFactory和BetterPrinterFactory
OutputFactory接口代码如:
public interface OutputFactory{
Output getOutput();
}
PrinterFactory实现类如下:
public class PrinterFactory implements OutputFactory{
public Output getOutput(){
return new Printer();
}
}
BetterPrinterFactory 实现类如下:
public class BetterPrinterFactory implements OutputFactory{
public Output getOutput(){
return new BetterPrint();
}
}
修改2中的Couputer类如下:
public class Computer{
private Output out;
public Computer (Output out){
this.out = out;
}
public void keyIn(String msg){
out.getData(msg);
}
public void print(){
out.out();
}
public static void main(String[] args){
outputFactory of =new PrinterFactory ();
Computer c = new Computer(of.getOutput());
c.keyIn("轻量级java“);
c.print();
}
}
当程序需要调用Output对象的方法时,需要显示的创建不同的工厂实例。程序中创建的是PrinterFactory 实例。这种方式虽然不会修改工厂类的方法,但会带来另一种耦合,客户端代码和工厂类的耦合。
在这种模式下新增一个OutputFactoryFactory工厂类,改工厂类提供了一个getOutputFactory(String type)方法,改方法用于返回一个OutputFactory工厂示例。下面是OutputFactoryFactory的代码:
public class OutputFactoryFactory{
public static OutputFactory getOutputFactory(String type){
if(type.equalsIngnoreCase("better"){
return new BetterPrinterFactory();
}else{
return new PrinterFactory();
}
}
}
修改Computer类的Mian方法如下:
public static void main(String[] args){
outputFactory of =OutputFactoryFactory.getoutputFactory("better");
Computer c = new Computer(of.getOutput());
c.keyIn("轻量级java“);
c.print();
}
上面程序中用于产生一个OutputFactory工厂,但具体产生哪个工厂则由OutputFactoryFactory抽象工厂决定,不同的工厂生产不同的output对象,通过采用抽象工厂模式,系统可以让客户端代码与被调用对象实现类、具体的工厂类实现分离。
如果工厂直接生产被调用对象,那就是简单工厂模式,如果工厂生产了工厂对象,那就升级为抽象工厂模式。