分类目录归档:java

java入门与提高::::::演道网java专栏提供一线java研发人员在学习工作中的经验,减少大家走的弯路,大量源码可以直接使用。

CentOS 7 安装 JDK-演道网

CentOS 7 安装 JDK

我们需要一些工具

人和动物的区别是会制作和使用工具。以下所有在 CentOS 系统下的操作全部使用的是 Xshell 5 和 Xftp 4 ,之后的文章就不再唠叨了。没有使用 putty 是因为这两个工具配合使用更舒服,敲命令、传文件、修改文件一气呵成,丝毫不拖泥带水,就是长这个样子:

xshell_xftp.jpg
继续阅读CentOS 7 安装 JDK-演道网

Java this使用总结

想写一些关于Java的知识,总结一下Java的使用。这次写的是关于Java this的使用,介绍以下内容:

  1. this的概念
  2. this的各种应用
  3. 总结

this 是什么

在写一个方法的时候,如果想在方法内部获得对当前对象的引用就可以用this.this表示对“调用方法的那个对象”的引用。也就是说this指的是方法所属的类的对象的引用。根据这个定义,我们可以总结出很多关于this的用法。

  1. 当局部变量与成员变量重名的时候,可以用this表明用的是对象的成员变量。
  2. 当方法需要一个该类的对象做参数的时候,可用this代替。
  3. Android开发中,我们经常需要对事件处理写一个内部类或者匿名内部类,在内部类里用this,按照刚才的定义,指的就是内部类的对象,如果想要用外部类的对象,则要外部类名.this的形式表示外部类的对象的引用。
  4. 在构造函数中,可以用this来调用另一个构造函数。
  5. 当一个方法需要返回对当前对象的引用的时候,可以用return this。这时就可以在不断对这个对象进行多次这种方法的操作。

下面会针对每一种用法
进行说明和举例。

this的用法1

在Java程序中,如果一个方法中的参数与成员变量的名称是一样的时候,我们可以用this来指定调用的成员变量,例子如下:

/**
 * Created by byhieg on 16-4-23.
 */
public class A {

    public String s = "A";

    public A() {

    }

    public A(String s) {
        System.out.println("s的值 = " + s);
        s = "B";
        System.out.println("经过s="B"赋值后成员变量s的值");
        System.out.println("成员变量s的值 = " + this.s);
        this.s = "B";
        System.out.println("经过this.s="B"赋值后成员变量s的值");
        System.out.println("成员变量s的值 = " + this.s);
    }


    public void show() {
        System.out.println("无参构造器中成员变量s的值 = " + s);
    }

    public static void main(String[] args) {
        new A().show();
        System.out.println("调用含参构造器后");
        new A("C");
    }
}

运行结果如下:

无参构造器中成员变量s的值 = A
调用含参构造器后
s的值 = C
经过s="B"赋值后成员变量s的值
成员变量s的值 = A
经过this.s="B"赋值后成员变量s的值
成员变量s的值 = B

我们从这个程序可以看出来,当局部变量没有的时候,直接输出s不用加this,编译器也知道s指的是成员变量,当有局部变量的时候,编译器首先会用局部变量,这也就是在调用含参构造器后,直接输出s的值,s实际指的是局部变量,后续一切对s的操作,都是指的是局部变量s。这时,如果我们要对成员变量进行操作,就要用this.s表明是对对象的成员变量进行操作。
通过刚才的分析,我们已经可以看出this就是指的对当前对象的引用,所以既然是对象的引用,那么他不仅可以调用成员变量,还可以调用成员方法,一个方法中,可以通过this来调用其他方法。话虽如此,不过恐怕很多程序都是在方法中不加this直接调用,因为当前方法中this引用会自动应用于同一类中的其他方法。

this的用法2

在写一个方法的时候,如果该方法需要一个该类的对象做参数的时候,通常传入this代指该类的对象,具体的使用场景如下:

在Android开发中,我们的一些方法经常需要context作为一个参数传进去,通常我们传入的都是context的子类,即当前Activity的对象this进去。
我们可以看一下下面的代码:

/**
 * Created by byhieg on 16-4-23.
 */
class B {
    B(A a) {
        a.show();
    }
}
public class A {

    public void doB() {
        new B(this);
    }
    public void show() {
        System.out.println("我是A");
    }

    public static void main(String[] args) {
        new A().doB();
    }
}

输出我是A
这个例子虽然写的很特意,但我们可以看出this在这里面取得的作用,this作为该类的对象的引用,在这里this就是指A的对象的引用。因为this是在A类的方法中传进去的所以指的是A的对象的引用。我们可以看一下下面的有趣例子:

/**
 * Created by byhieg on 16-4-23.
 */
class B {
    public B() {
        System.out.println("这里的this是" + this.getClass().getSimpleName());
    }

    public void Bshow() {
        System.out.println("这里的this是" + this.getClass().getSimpleName());
    }
}
public class A extends B {
    public A() {
    }
    public static void main(String[] args) {
        new A();
        new B().Bshow();
    }
}

结果很值得讨论,结果如下:

这里的this是A
这里的this是B
这里的this是B

明明是this出现B的构造器内,按照刚才说的不是应该指的是B吗?其实,注意刚才说的是this是指从那个方法中传进去那个类的对象。jvm在执行编译的时候,在成员方法中,会默认隐藏的传递一个参数,这个参数就是当前调用的对象本身。换句话说,虽然new A()的时候会先执行父类的默认构造函数,但此时已经把JVM已经秘密的传入的A的对象,所以我们可以看出输出的this是A。而在new B()的时候,传入的当然就是B的对象,所以输出的this就是B。

this的用法3

在Android开发中,我们经常需要对事件处理写一个内部类或者匿名内部类,在内部类里用this,按照刚才的定义,指的就是内部类的对象,如果想要用外部类的对象,则要外部类名.this的形式表示外部类的对象的引用。这个没什么细说的,直接看下面的例子算了

/**
 * Created by byhieg on 16-4-23.
 */
public class A {
    int i = 1;

    public A() {
        Thread thread = new Thread() {
            public void run() {
                for (int j = 0;j < 2;j++) {
                    //调用外部类的方法
                    A.this.run();
                }
            }
        };
        thread.start();
    }

    public void run() {
        System.out.println("i = " + i);
        i++;
    }

    public static void main(String[] args) throws Exception {
        new A();
    }
}

这里run方法和内部类里面的run重复了,如果想要调用A的run方法就需要A的对象→this,但如果直接在内部类里面用this,则this就指的是内部类的对象,所以我们需要加上外部类的名字。A.this来明确表明这是A的对象。

this的用法4

在构造函数中,可以用this来调用另一个构造函数。这是this比较独特的用法,即在构造器中,如果为this添加了参数列表,那么这将产生对符合参数列表的某个构造器的明确调用。这样我们就可以在构造器中调用其他构造器,但书写上有所限制,必须将构造器的调用置于最初始处,而且只能用一次。
例子如下:

/**
 * Created by byhieg on 16-4-23.
 */
public class A {
    int a ,b;
    public A(int a) {
        this.a = a;
        System.out.println(this.a);
    }
    public A(int a, int b) {
        this(a);
        this.b = b;
        System.out.println(this.a + " " + this.b);
    }
    public static void main(String[] args) {
        new A(2);
        new A(2, 3);
    }
}

具体的用法就如上面所示,我们可以打开调试器看一看里面的信息,如下图

调试器内部图

我们可以看出this作为当前的对象,里面存放这该类的三个成员变量,我们可以很容易验证,无论this调用什么方法,内存中永远存放这个类的成员变量,所以才可以通过this对成员变量进行修改。

this的用法5

当一个方法需要返回对当前对象的引用的时候,可以用return this。这时就可以在不断对这个对象进行多次这种方法的操作。
这是一个很神奇的操作,因为这个方法的返回值是当前对象的引用,因此你可以用这个引用继续调用其他方法,很容易一行语句执行多次操作,就像python的一行语法一样。
我们看一个好玩的例子

/**
 * Created by byhieg on 16-4-23.
 */
public class A {
    int  i = 0;
    public A add() {
        i ++;
        return this;
    }
    public A show() {
        System.out.println(i);
        return this;
    }
    public void end() {
        System.out.println("到此为止");
    }

    public static void main(String[] args) {
        new A().add().show().add().show().add().show().add().show().add().show().end();
    }
}

输出结果显而易见,我就不放出来了。

总结

我们这里讨论了this的五种用法,但是都是根据this的定义引申出在不同情况下的用法。this只能在方法内部使用,当调用方法中含有this的时候,this就指的调用该方法的对象的引用,当方法参数中需要传入一个类的对象的时候,用this代指这个传入类的对象。当用构造方法初始化成员变量的时候,JVM会默认传入当前对象来初始化成员变量。

Java线程中生产者与消费者的问题

一、概念

  生产者与消费者问题是一个金典的多线程协作的问题.生产者负责生产产品,并将产品存放到仓库;消费者从仓库中获取产品并消费。当仓库满时,生产者必须停止生产,直到仓库有位置存放产品;当仓库空时,消费者必须停止消费,直到仓库中有产品。

  解决生产者/消费者问题主要用到如下几个技术:1.用线程模拟生产者,在run方法中不断地往仓库中存放产品。2.用线程模拟消费者,在run方法中不断地从仓库中获取产品。3.仓库类保存产品,当产品数量为0时,调用wait方法,使得当前消费者线程进入等待状态,当有新产品存入时,调用notify方法,唤醒等待的消费者线程。当仓库满时,调用wait方法,使得当前生产者线程进入等待状态,当有消费者获取产品时,调用notify方法,唤醒等待的生产者线程。

二、实例

package book.thread.product;

public class Consumer extends Thread{
  private Warehouse warehouse;//消费者获取产品的仓库
   private boolean running = false;//是否需要结束线程的标志位
   public Consumer(Warehouse warehouse,String name){
    super(name);
    this.warehouse = warehouse;
  }
  public void start(){
    this.running = true;
    super.start();
  }
  public void run(){
    Product product;
    try {
      while(running){
        //从仓库中获取产品
         product = warehouse.getProduct();
        sleep(500);
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  //停止消费者线程
   public void stopConsumer(){
    synchronized(warehouse){
      this.running = false;
      warehouse.notifyAll();//通知等待仓库的线程
     }
  }
  //消费者线程是否在运行
   public boolean isRunning(){
    return running;
  }
}

 

package book.thread.product;

public class Producer extends Thread{
   private Warehouse warehouse;//生产者存储产品的仓库
   private static int produceName = 0;//产品的名字
   private boolean running = false;//是否需要结束线程的标志位

   public Producer(Warehouse warehouse,String name){
    super(name);
    this.warehouse = warehouse;
  }
  public void start(){
    this.running = true;
    super.start();
  }
  public void run(){
    Product product;
    //生产并存储产品
     try {
    while(running){
      product = new Product((++produceName)+””);
      this.warehouse.storageProduct(product);
      sleep(300);
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  //停止生产者线程
   public void stopProducer(){
    synchronized(warehouse){
      this.running = false;
      //通知等待仓库的线程
       warehouse.notifyAll();
    }
  }
  //生产者线程是否在运行
   public boolean isRunning(){
    return running;
  }
}

 

package book.thread.product;

public class Product {
  private String name;//产品名
   public Product(String name){
    this.name = name;
  }
  public String toString(){
    return “Product-“+name;
  }
}

 

package book.thread.product;

//产品的仓库类,内部采用数组来表示循环队列,以存放产品
public class Warehouse {
  private static int CAPACITY = 11;//仓库的容量
   private Product[] products;//仓库里的产品
   //[front,rear]区间的产品未被消费
   private int front = 0;//当前仓库中第一个未被消费的产品的下标
   private int rear = 0;//仓库中最后一个未被消费的产品下标加1
  public Warehouse(){
    this.products = new Product[CAPACITY];
  }
  public Warehouse(int capacity){
    this();
    if(capacity > 0){
      CAPACITY = capacity +1;
      this.products = new Product[CAPACITY];
    }
  }

  //从仓库获取一个产品
   public Product getProduct() throws InterruptedException{
    synchronized(this){
      boolean consumerRunning = true;//标志消费者线程是否还在运行
       Thread currentThread = Thread.currentThread();//获取当前线程
       if(currentThread instanceof Consumer){
        consumerRunning = ((Consumer)currentThread).isRunning();
      }else{
        return null;//非消费者不能获取产品
       }
      //若消费者线程在运行中,但仓库中没有产品了,则消费者线程继续等待
       while((front==rear) && consumerRunning){
        wait();
        consumerRunning = ((Consumer)currentThread).isRunning();
      }
      //如果消费者线程已经停止运行,则退出该方法,取消获取产品
       if(!consumerRunning){
        return null;
      }
      //获取当前未被消费的第一个产品
       Product product = products[front];
      System.out.println(“Consumer[” + currentThread.getName()+”] getProduct:”+product);
      //将当前未被消费产品的下标后移一位,如果到了数组末尾,则移动到首部
       front = (front+1+CAPACITY)%CAPACITY;
      System.out.println(“仓库中还没有被消费的产品数量:”+(rear+CAPACITY-front)%CAPACITY);
      //通知其他等待线程
       notify();
      return product;
    }
  }
  //向仓库存储一个产品
   public void storageProduct(Product product) throws InterruptedException{
  synchronized(this){
    boolean producerRunning = true;//标志生产者线程是否在运行
     Thread currentThread = Thread.currentThread();
    if(currentThread instanceof Producer){
      producerRunning = ((Producer)currentThread).isRunning();
    }else{
      return;
    }
    //如果最后一个未被消费的产品与第一个未被消费的产品的下标紧挨着,则说明没有存储空间了。
     //如果没有存储空间了,而生产者线程还在运行,则生产者线程等待仓库释放产品
     while(((rear+1)%CAPACITY == front) && producerRunning){
      wait();
      producerRunning = ((Producer)currentThread).isRunning();
    }
    //如果生产线程已经停止运行了,则停止产品的存储
     if(!producerRunning){
      return;
    }
    //保存产品到仓库
     products[rear] = product;
    System.out.println(“Producer[” + Thread.currentThread().getName()+”] storageProduct:” + product);
    //将rear下标循环后移一位
     rear = (rear + 1)%CAPACITY;
    System.out.println(“仓库中还没有被消费的产品数量:”+(rear + CAPACITY -front)%CAPACITY);
    notify();
    }
  }
}

 

package book.thread.product;

public class TestProduct {
  public static void main(String[] args) {
    Warehouse warehouse = new Warehouse(10);//建立一个仓库,容量为10
    //建立生产者线程和消费者
     Producer producers1 = new Producer(warehouse,”producer-1″);
    Producer producers2 = new Producer(warehouse,”producer-2″);
    Producer producers3 = new Producer(warehouse,”producer-3″);
    Consumer consumer1 = new Consumer(warehouse,”consumer-1″);
    Consumer consumer2 = new Consumer(warehouse,”consumer-2″);
    Consumer consumer3 = new Consumer(warehouse,”consumer-3″);
    Consumer consumer4 = new Consumer(warehouse,”consumer-4″);
    //启动生产者线程和消费者线程
     producers1.start();
    producers2.start();
    consumer1.start();
    producers3.start();
    consumer2.start();
    consumer3.start();
    consumer4.start();
    //让生产者/消费者程序运行1600ms
    try {
      Thread.sleep(1600);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    //停止消费者线程
     producers1.stopProducer();
    consumer1.stopConsumer();
    producers2.stopProducer();
    consumer2.stopConsumer();
    producers3.stopProducer();
    consumer3.stopConsumer();
    consumer4.stopConsumer();
  }
}

输出结果:

Producer[producer-1] storageProduct:Product-1
仓库中还没有被消费的产品数量:1
Consumer[consumer-2] getProduct:Product-1
仓库中还没有被消费的产品数量:0
Producer[producer-3] storageProduct:Product-3
仓库中还没有被消费的产品数量:1
Producer[producer-2] storageProduct:Product-2
仓库中还没有被消费的产品数量:2
Consumer[consumer-3] getProduct:Product-3
仓库中还没有被消费的产品数量:1
Consumer[consumer-1] getProduct:Product-2
仓库中还没有被消费的产品数量:0
Producer[producer-1] storageProduct:Product-4
仓库中还没有被消费的产品数量:1
Consumer[consumer-4] getProduct:Product-4
仓库中还没有被消费的产品数量:0
Producer[producer-3] storageProduct:Product-6
仓库中还没有被消费的产品数量:1
Producer[producer-2] storageProduct:Product-5
仓库中还没有被消费的产品数量:2
Consumer[consumer-1] getProduct:Product-6
仓库中还没��被消费的产品数量:1
Consumer[consumer-2] getProduct:Product-5
仓库中还没有被消费的产品数量:0
Producer[producer-1] storageProduct:Product-7
仓库中还没有被消费的产品数量:1
Consumer[consumer-3] getProduct:Product-7
仓库中还没有被消费的产品数量:0
Producer[producer-3] storageProduct:Product-8
仓库中还没有被消费的产品数量:1
Producer[producer-2] storageProduct:Product-9
仓库中还没有被消费的产品数量:2
Consumer[consumer-4] getProduct:Product-8
仓库中还没有被消费的产品数量:1
Producer[producer-1] storageProduct:Product-10
仓库中还没有被消费的产品数量:2
Producer[producer-3] storageProduct:Product-11
仓库中还没有被消费的产品数量:3
Producer[producer-2] storageProduct:Product-12
仓库中还没有被消费的产品数量:4
Consumer[consumer-1] getProduct:Product-9
仓库中还没有被消费的产品数量:3
Consumer[consumer-2] getProduct:Product-10
仓库中还没有被消费的产品数量:2
Consumer[consumer-3] getProduct:Product-11
仓库中还没有被消费的产品数量:1
Producer[producer-3] storageProduct:Product-13
仓库中还没有被消费的产品数量:2
Producer[producer-1] storageProduct:Product-14
仓库中还没有被消费的产品数量:3
Producer[producer-2] storageProduct:Product-15
仓库中还没有被消费的产品数量:4
Consumer[consumer-4] getProduct:Product-12
仓库中还没有被消费的产品数量:3
Consumer[consumer-1] getProduct:Product-13
仓库中还没有被消费的产品数量:2
Consumer[consumer-2] getProduct:Product-14
仓库中还没有被消费的产品数量:1
Producer[producer-1] storageProduct:Product-16
仓库中还没有被消费的产品数量:2
Producer[producer-3] storageProduct:Product-17
仓库中还没有被消费的产品数量:3
Producer[producer-2] storageProduct:Product-18
仓库中还没有被消费的产品数量:4

分析:在main方法中建立了一个产品仓库,并未该仓库关联了3个生产者线程和4个消费者线程,启动这些线程,使生产 者/消费者模型运作起来,当程序运行1600ms时,所有的生产者停止生产产品,消费者停止消费产品。

  生产者线程Product在run方法中没300ms便生产一个产品,并存入仓库;消费者线程Consumer在run方法中没500ms便从仓库中取一个产品。

  仓库类Warehouse负责存放产品和发放产品。storageProduct方法负责存储产品,当仓库满时,当前线程进入等待状态,即如果生产者线程A在调用storageProduct方法以存储产品时,发现仓库已满,无法存储时,便会进入等待状态。当存储产品成功时,调用notify方法,唤醒等待的消费者线程。

  getProduct方法负责提前产品,当仓库空时,当前线程进入等待状态,即如果消费者线程B在调用getProduct方法以获取产品时,发现仓库空了,便会进入等待状态。当提取产品成功时,调用notify方法,唤醒等待的生产者线程。

Java的4种单例模式

Java的4种单例模式

——————————————————————————–

第一种:线程不安全,不正确的写法
class Singleton{
    private static Singleton instance;
    private Singleton(){
    }
    public static Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

——————————————————————————–

第二种:线程安全,但高并发不是很理想的写法:
class Singleton{
    private static Singleton instance;
    private Singleton(){
    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

——————————————————————————–

第三种:线程安全,性能又高,这种写法最为常见:
class Singleton{
    private static Singleton instance;
    private static byte[] lock=new byte[0];
    private Singleton(){
    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            synchronized(lock){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

——————————————————————————–

第四种:线程安全,性能又高,这种写法也最为常见:
class Singleton{
    private static Singleton instance;
    private static ReentrantLock lock=new ReentrantLock ();
    private Singleton(){
    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            lock.lock();
            if(instance==null){
                instance=new Singleton();
            }
            lock.unlock();
        }
        return instance;
    }
}

Java设计模式之简单工厂模式

近来在学习Java的设计模式,一直觉得设计模式很难,所以一直没有去接触,一则是工作比较忙没有闲工夫去学习,二来是因为自己比较懒所以也懒得动,幸亏今天在公司还挺闲的,所以找了一本书来学习下Java的设计模式。

  1. 简单工厂的定义
  2. 应用简单工厂来解决问题的思路
  3. 简单工厂的结构和说明
  4. 简单工厂代码
  5. 使用简单工厂重写示例
  6. 模式讲解
  7. 简单工厂中方法的写法
  8. 简单工厂的优缺点
  9. 思考简单工厂

1、简单工厂的定义

提供一个创建对象实例的功能,而无须关系其具体的实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。

2、应用简单工厂来解决问题的思路

简单工厂就是不能让模块外部知道模块内部的具体实现,但是模块内部还是可以知道实现类的,而且创建接口是需要知道具体的实现类的。
所以,干脆在模块内部新建一个类,在这个类里面来创建接口,然后把创建的接口返回给具体调用者,这样,外部应用就只需根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了。把这样的对象就称作简单工厂,就叫它Factory。

3、简单工厂的结构和说明

简单工厂的结果如下图所示。
简单工厂结构图

  • Api:定义客户所需的功能接口。
  • Impl:具体实现Api的实现类,可有多个,根据具体业务。
  • Factory:工厂,选择合适的实现类来创建Api接口对象。
  • Client:客户端,通过Factory来获取Api接口对象,然后面向Api接口编程。

4、简单工厂代码

(1)Api定义代码如下:

public interface Api {
    /**
     * 示意,具体功能方法的定义
     * @param s 示意,需要的参数
     */
    public void operation(String s);
}

(2)定义了接口后,实现类ImplA代码如下:

public class ImplA implements Api {
    @Override
    public void operation(String s) {
        System.out.println("ImplA s==" + s);
    }
}

实现类ImplB.java代码如下

public class ImplB implements Api {
    @Override
    public void operation(String s) {
        System.out.println("ImplB s==" + s);
    }
}

(3)简单工厂的实现。代码如下:

/**
 * 工厂类,用于穿件Api对象
 * @author veione
 */
public class Factory {
    /**
     * 具体创建Api对象的方法
     * @param condition 示意,从外部传入的选择条件
     * @return 创建好的Api对象
     */
    public static Api createApi(int condition) {
        //根据条件来创建具体实现对象
        Api api = null;
        if (condition == 1) {
            api = new ImplA();
        } else if (condition == 2) {
            api = new ImplB();
        }
        return api;
    }
}

(4)再来看下客户端的示意,代码如下:

/**
 * 客户端,使用Api接口
 * @author veione
 */
public class Client {
    public static void main(String[] args) {
        // 通过简单工厂来获取接口对象
        Api api = Factory.createApi(1);
        api.operation("使用简单工厂进行操作");
    }
}

5、使用简单工厂重写示例

要使用简单工厂来重写前面的示例,主要就是创建一个简单工厂对象,让简单工厂来负责创建接口对象。后客户端通过工厂获取接口对象,而不再由客户端自己创建接口对象了。
系统结构如下图所示:
系统结构图

(1)接口Api和实现类Impl和前面的示例一样,在此不再赘述。

(2)新创建一个简单工厂的对象。代码如下:

/**
 * 工厂类,用来创建Api对象
 */
 public class Factory{
     /**
      * 具体创建Api对象的方法
      * @return 创建好的Api对象
      */
      public static Api createApi(){
          //由于只有一个实现就无需再条件判断了
          return new Impl();
      }
 }

(3)使用简单工厂

这个时候客户端就不用再自己创建接口对象了,应该使用工厂来获取。改造后代码如下:

/**
 * 客户端:测试使用Api接口
 */
 public class Client{
     public static void main(String[] args){
        Api api=Factory.createApi();
        api.test1("Hello,World!简单那工厂");
     }
 }

模式讲解

1、简单工厂的功能

工厂就是用来生产东西的。在Java里面,通常情况下是用来创建接口的,但是也可以创造抽象类,甚至是一个具体类的实例。

2、静态工厂

使用简单工厂的时候,通常不用创建简单工厂类实例,没有创建实例的必要。因此可以把简单那工厂类实现成一个工具类,直接使用静态方法即可。也就是说简单工厂的方法通常是静态的,所以也被称为静态工厂。如果要防止客户端无谓地创造简单工厂实例,还可以把简单工厂的构造方法私有化。

3、万能工厂

一个简单工厂可以包含很多用来构造东西的方法,这些方法可以创建不同的接口、抽象类或者类实例。一个简单工厂理论上可以构造任何东西,所以又称之为“万能工厂”。
虽然上面的实例在简单工厂里面只有一个方法,但事实上,是可以有很多这样的创建方法的,这点要注意。

4、简单工厂创建对象的范围

虽然从理论上讲,简单工厂什么都能创建,但对于简单工厂可创建对象的范围,通常不要太大,建议控制在一个独立的组件级别或者一个模块级别,也就是一个组件或模块简单工厂。否则这个简单工厂类会职责不明,有点大杂烩的感觉。

5、简单工厂的调用顺序示意图

简单工厂的调用顺序示意图

uml用例图不太会使用,所以这里大家参考一下即可。

简单工厂中方法的写法

虽然说简单工厂的方法大多是用来创建接口的,但是仔细分析你会发现,真正能实现功能的是具体的实现类,这些实现类是已经做好的,并不是真的要靠简单工厂来创建出来的,简单工程的方法无外乎就是:实现了选择一个合适的实现类来使用。
所以说简单工厂方法内部主要实现的功能是选择合适的实现类来创建实例对象。既然要实现选择,那么就需要选择的条件或者是选择的参数,选择条件或是参数的来源通常又分为以下几种:

  • 来源与客户端:由Client来传入参数
  • 来源于配置文件,从配置文件获取用于判断的值
  • 来源于程序运行时期的某个值,比如从缓存中获取某个运行期的值。

简单工厂的优缺点

简单工厂有以下优点。

  • 帮助封装

    简单工厂虽然很简单,但是非常有好的帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程。

  • 解耦

    通过简单工厂实现了客户端和具体实现类的解耦。

简单工厂有以下缺点。

  • 可能增加客户端的复杂度

如果通过客户端的参数来选择具体的实现类,那么就必须让客户端理解各个参数所代表的具体功能和含义,这样会增加客户端使用的难度,也部分暴露了内部实现,这种情况可以选用可配置的方式来实现。

  • 不方便扩展子工厂

私有化简单工厂的构造方法,使用静态方法来创建接口,也就不能通过写简单工厂类的子类来改变创建接口的方法行为了。不过,通常情况下是不需要为简单工厂创建子类的。

思考简单工厂

1、简单工厂的本质

简单工厂的本质就是:选择实现

2、何时选用简单工厂

建议在以下情况中选用简单工厂。

  • 如果想要完成封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无须关系具体的实现。
  • 如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单那工厂可以创建很多的、不相关的对象,可以把

Java使用代理访问网络的方法

有些时候我们的网络不能直接连接到外网, 需要使用http或是https或是socket代理来连接到外网,这里是java使用代理连接到外网的一些方法.

方法一:

使用系统属性来完成代理设置,这种方法比较简单, 但是不能对单独的连接来设置代理: 

Properties properties=System.getProperties();

// 设置http访问要使用的代理服务器的地址     

properties.setProperty(“http.proxyHost”, “192.168.0.254”);     

// 设置http访问要使用的代理服务器的端口     

properties.setProperty(“http.proxyPort”, “8080”);     

// 设置不需要通过代理服务器访问的主机,可以使用*通配符,多个地址用|分隔     

properties.setProperty(“http.nonProxyHosts”,”localhost|192.168.0.*”);     

// 设置安全访问使用的代理服务器地址与端口     

// 它没有https.nonProxyHosts属性,它按照http.nonProxyHosts 中设置的规则访问     

properties.setProperty(“https.proxyHost”, “192.168.0.254”);     

properties.setProperty(“https.proxyPort”, “443”);     

// 使用ftp代理服务器的主机、端口以及不需要使用ftp代理服务器的主机     

properties.setProperty(“ftp.proxyHost”, “192.168.0.254”);     

properties.setProperty(“ftp.proxyPort”, “2121”);     

properties.setProperty(“ftp.nonProxyHosts”,”localhost|192.168.0.*”);     

// socks代理服务器的地址与端口     

properties.setProperty(“socksProxyHost”, “192.168.0.254”);     

properties.setProperty(“socksProxyPort”, “8000”);

// 设置登陆到代理服务器的用户名和密码     

Authenticator.setDefault(new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication(){

// TODO Auto-generated method stub

return new PasswordAuthentication(userName,password.toCharArray());

}

});

方法二:使用Proxy来对每个连接实现代理, 这种方法只能在jdk 1.5以上的版本使用(包含jdk1.5),优点是可以单独的设置每个连接的代理, 缺点是设置比较麻烦:
 try {       

  URLurl = newURL(“http://www.linuxidc.com”);           

  //创建代理服务器           

  InetSocketAddress addr = newInetSocketAddress(“192.168.0.254”,8080);           

  Proxyproxy = new Proxy(Proxy.Type.HTTP, addr); // http代理           

  //如果我们知道代理server的名字,可以直接使用         

  URLConnection conn =url.openConnection(proxy);           

  InputStream in =conn.getInputStream(); 

  String s =IOUtils.toString(in);           

  System.out.println(s);       

  } catch(Exception e){           

  e.printStackTrace();       

 }   

}

Spring总结—— IOC 和 Bean 的总结

<

div id=”content” contentScore=”6022″>一、Spring 官方文档中给出的 Spring 的整体结构。

二、我自己所理解的 Spring 整体结构图。

三、本次总结 Spring 核心部分

1.从上面图中可以看出,Beans 和 Context 和 Core 组件作为 Spring 的核心组件,它们构成了整个 Spring 的骨架。

2.从根本说来说,Spring 最终操纵的还是 Bean,所以说 Bean 是整个 Spring 核心中的核心。

3.和正常编程的思想不同,Spring 把对象之间的依赖关系转而由配置文件进行管理,也就是他的依赖注入机制。而这个注入关系在一个 IOC 容器中进行管理。

IOC 容器中包含有什么?其实就是被一个个 bean 包含的对象。IOC 容器可以看成是 beans 关系的一个集合。

4.这种设计策略完全类似于 Java 实现的 OOP 设计理念,构建一个数据结构,然后根据这个数据结构设计它的生存环境,并赋给它生命周期,使他在一定规律下

不停的运动,在不停运动的过程中完成与其他个体的交互。

5.核心组件之间如何进行协同工作的:举一个非常好的例子,如果说 Bean 是一场话剧的演员的话,那么 Context 就是舞台,而 Core 就是道具,它们三个是演话剧最基本的元素。

我们知道 Bean 包装的是一个 Object,而 Object 中存在数据,而给这些数据提供生存环境就是 Context 要解决的问题,对于 Context 而言,它要发现每个 Bean,以及 Bean 与

Bean 之间的关系,建立和维护好这种关系。所以 Context 就是 Bean 关系的集合,这个关系集合又叫 IOC 容器,而一旦建立起这个容器,Spring就可以进行工作了。那么 Core 是

用来做什么的呢?发现、建立和维护 Bean 之间的关系所需要的一系列的工具,它为 Bean 组件和 Context 组件提供了支持。

四、Bean 组件

1.Bean 组件位于 Spring 的 org.springframework.beans 包下。

而这个包下的所有类主要解决了三件事情:Bean 的定义、Bean 的创建以及对 Bean 的解析。对于使用者来说,我们只需要关注 Bean 的创建就 ok。其他两个由 Spring 完成。

2.Spring Bean 的创建是典型的工厂模式,他的顶级接口是 BeanFactory。

3.Bean 的定义主要由 BeanDefinition 描述,Bean 的定义就是描述了在 Spring Config 文件中 节点及其子节点的所有信息。

当 Spring 成功解析你定义的一个 节点后,在 Spring 内部就会转化为 BeanDefinition 对象。以后所有的操作都是由这个对象来完成。

4.Bean 的解析主要就是对 Spring 配置文件的解析,顶级接口为 BeanDefinitionReader 和 BeanDefinitionDocumentReader。

五、Context 组件

1.Context 组件位于 Spring 的 org.springframework.context 包下,它的作用就是为 Bean 提供一个运行时环境,并且维护好 Bean 之间的关系。

2.BeanFactory 作为 Context 的顶级接口。

ApplicationContext 为 Context 组件的常用接口,它除了能标识一个应用环境的基本信息外,他还继承了6个接口,他们扩展了 Context 的功能。

从上图可以看出 ApplicationContext 接口继承了 BeanFactory 接口,由此也可以看出 Spring 运行的主体是 Bean。另外间接继承了 ResourceLoader 接口,

也就可以访问到外部资源。

然后再看它的两个子接口:

(1).ConfigurableApplicationContext 表示该 Context 是可以修改的,也就是说在构建 Context 时用户可以添加或修改已有的配置。

(2).WebApplicationContext 就是为 Web 环境准备的 Context,它可以访问到 ServletContext。

对于 ApplicationContext 来说,必须要完成的几件事情:

(1)标识一个应用环境

(2)利用 BeanFactory 创建 Bean 对象

(3)保存对象关系表

(4)能够捕获各种事件

Context 作为 Spring 的 IOC 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。

六、Core 组件

1.Core 组件作为 Spring 的核心组件,它其中包含了很多关键的类,其中一个重要的组成部分就是定义了资源的访问方式。将所有资源都抽象为一个接口 Resource。

Resource 类结构图:

从上图可以看到 Resource 类封装了各种可能的资源类型,继承了 InputStreamSource 接口,对使用者来说屏蔽了资源类型的不同。所有资源都可以通过 getInputStream() 获取到。

2.Context 与 Resource 之间的关系:Context 是把资源的加载、解析和描述工作委托给 ResourcePatternResolver 类来完成,他把资源的加载、解析和资源的定义整合到了一起便于

其他组件使用。

七、IOC 容器是如何进行工作的

1.IOC 容器实际上就是结合其他两个组件共建了一个 bean 关系网。

2.如何创建 BeanFactory 工厂

3.如何创建 Bean 实例并构建 Bean 之间的关系网

4.如何对 Bean 进行扩展

八、上面内容是从宏观上对 Spring 核心的三个组件进行了介绍,其中大部分内容是借鉴的别人的,下面列出具体知识细节 

9.最后想说的是,我自己认为如果想学好 Spring 的话,必须对其思想有所深刻理解,然后以此为驱动去学习,有章法,事半功倍。

 

Spring中如何配置Hibernate事务 http://www.linuxidc.com/Linux/2013-12/93681.htm

 

Struts2整合Spring方法及原理 http://www.linuxidc.com/Linux/2013-12/93692.htm

 

基于 Spring 设计并实现 RESTful Web Services http://www.linuxidc.com/Linux/2013-10/91974.htm

 

Spring-3.2.4 + Quartz-2.2.0集成实例 http://www.linuxidc.com/Linux/2013-10/91524.htm

 

使用 Spring 进行单元测试 http://www.linuxidc.com/Linux/2013-09/89913.htm

 

运用Spring注解实现Netty服务器端UDP应用程序 http://www.linuxidc.com/Linux/2013-09/89780.htm

 

Spring 3.x 企业应用开发实战 PDF完整高清扫描版+源代码 http://www.linuxidc.com/Linux/2013-10/91357.htm

 

Spring 的详细介绍请点这里
Spring 的下载地址请点这里

 

<strong