(说明:本内容由网上视频教程整理,主要是方便自用,仅做参考。若是有错欢迎指出!) java
简单工厂模式属于类的建立型模式,又叫作静态工厂方法模式。经过专门定义一个类来负责建立其余类的实例,被建立的实例一般都具备共同的父类。 安全
简介: app
和简单工厂模式差很少,都是“工厂模式”。 性能
工厂方法模式一样属于类的建立型模式又被称为多态工厂模式。工厂方法模式的意义是定义一个建立产品对象的工厂接口,将实际建立工做推迟到子类当中。核心工厂类再也不负责产品的建立,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可使系统在不修改具体工厂角色的状况下引进新的产品。 ui
“开放和封闭原则” spa
开放:系统无限扩展; 线程
封闭:不要修改既有代码。 code
简单工厂模式破坏了“开放和封闭原则”,好比,若是FruitFactory类是这样写: orm
public class FruitFactory { // 简单工厂,获取类实例的方法二: // 这个方法的好处是参数名能够不分大小写(并且获取参数能够随便处理) // 缺点是增长水果的时候要增长if...else...不易扩展。 public static FruitInter getFruit2(String type){ if(type.equalsIgnoreCase("apple")){ return new Apple(); //return Apple.class.newInstance() }else if(type.equalsIgnoreCase("banana")){ return new Banana(); //return Banana.class.newInstance(); }else{ System.out.println("no such class!"); return null; } }
那么,若是增长一个水果类(如Pear.java)的话,就须要增长一个else…的分支语句来处理,这就破坏了“开放和封闭原则”。 视频
使用工厂方法模式:建立一个抽象工厂(或者说接口)FruitFactory.java,内部声明一个方法getFruit()方法;而后为每一个水果类分别建立本身的工厂类,如AppleFactory.java,并实现FruitFactory接口,在实现的getFruit()方法中完成类的实例操做。
【具体作法:】
首先,Apple.java、Banana.java、Fruit.java三个类都和简单工厂类相同:
public interface Fruit { public void get(); } public class Apple implements Fruit { public void get(){ System.out.println("Collect apple."); } } public class Banana implements Fruit{ public void get() { System.out.println("Collect banana."); } }
其次,增长抽象工厂类(接口):
public interface FruitFactory { public Fruit getFruit(); }
而后,为Apple.java、Banana.jav a提供工厂类:
public class AppleFactory implements FruitFactory { public Fruit getFruit() { return new Apple(); } } public class BananaFactory implements FruitFactory { public Fruit getFruit() { return new Banana(); } }
main方法中这么写:
public class MainClass { public static void main(String[] args) { // Apple FruitFactory fruitFactory1 = new AppleFactory(); Fruit apple = fruitFactory1.getFruit(); apple.get(); // Banana FruitFactory fruitFactory2 = new BananaFactory(); Fruit banana = fruitFactory2.getFruit(); banana.get(); } }
通常的思惟是,直接在main方法中实现全部的业务,以下所示:
public class Main { public static void main(String[]args){ System.out.println("---Caculation Program---"); System.out.print("Input the first num: "); Scanner scanner = new Scanner(System.in); String num1 = scanner.nextLine(); System.out.print("Input the operation: "); String oper = scanner.nextLine(); System.out.println("Input the second num: "); String num2 = scanner.nextLine(); double num1d = Double.parseDouble(num1); double num2d = Double.parseDouble(num2); double result = 0; if(oper.equals("+")){ result = num1d + num2d; }else if(oper.equals("-")){ result = num1d - num2d; }else{ System.out.println("ERROR!"); System.exit(0); } System.out.println("Result is: "+result); } }
这样的代码冗余、可扩展性很差!
下面使用工厂模式实现。
即便用专用的类(工厂类)来获取操做类(Operation类,用来实现各自的不一样的四则运算)
增长抽象工厂(接口):
单例模式是一种对象建立型模式,使用单例模式,能够保证为一个类只生成惟一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
其实,GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
在应用系统开发中,咱们经常有如下需求:
l 在多个线程之间,好比servlet环境,共享同一个资源或者操做同一个对象;
l 在整个程序空间使用全局变量,共享资源;
l 大规模系统中,为了性能的考虑,须要节省对象的建立时间等等。
由于Singleton模式能够保证为一个类只生成惟一的实例对象,因此这些状况,Singleton模式就派上用场了。
像上面定义的类,外面的获取到的Person对象只会有一个。
在懒汉式中,咱们将Synchronized加在了整个方法前,因此一个线程会守住整个方法,这样就影响了效率,咱们是但愿person只被实例化一次,能够将Synchronized加在实例化前:
这里还有个问题,就是当两个线程同时进入if的话,那么还会建立两个对象,下面加上两重循环:
以上就是“双重检查”!
双重检查比懒汉式的效率更高:由于若是有多个线程同时执行的时候,不会让其余线程等待(仅第一次执行的时候可能会等待,之后都不会等待)!
对于饿汉式,饿汉式优势是简单且线程永远安全,可是比较耗费资源,由于只要类被加载就对象就被建立。
Prototype模式是一种对象建立型模式,它采起复制原型对象的方法来建立对象的实例。使用Prototype模式建立的实例,具备与原型同样的数据。
1) 由原型对象自身建立目标对象。也就是说,对象建立这一动做发自原型对象自己;
2) 目标对象是原型对象的一个克隆。也就是说,经过Prototype模式建立的对象,不只仅与原型对象具备相同的结构,还与原型对象具备相同的值;
3) 根据对象克隆深度层次的不一样,有浅度克隆与深度克隆;
4) 要想类可以被克隆,就必须让类实现Cloneable接口(其实仅仅是作一个声明而已!)。
假如,Person类里有属性:List<String>friends,即:
由于person1的属性friends持有的是另一个对象的引用,因此在main方法中克隆的时候,(在栈中)person2克隆的也是一个引用,且指向同一个对象:
这就是“浅拷贝”,要想friends指向的也是全新的对象,那么就要手动添加(即“深拷贝”):