1. 程式人生 > >java 設計模式 常用21種

java 設計模式 常用21種

1.創造型:抽象工廠

package com.seezoon.建立型.抽象工廠;

/**
 * 抽象工廠
 * @author DF
 *工廠方法模式有一個問題就是,類的建立依賴工廠類,也就是說,如果想要拓展程式,
 *必須對工廠類進行修改,這違背了閉包原則,所以,從設計角度考慮,有一定的問題,如何解決?
 *就用到抽象工廠模式,建立多個工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,
 *不需要修改之前的程式碼
 */
public class AbstractFactory {
	public static void main(String[] args) {
		IFactory factory = new ProductAFactory();
		IProduct product = factory.produce();
		product.productMethod();
	}
}
interface IFactory {
	public IProduct produce();
}
class ProductAFactory implements IFactory{
	@Override
	public IProduct produce() {
		return new ProductA();
	}
}
class ProductBFactory implements IFactory{
	@Override
	public IProduct produce() {
		return new ProductB();
	}
}
interface IProduct {
	public void productMethod();
}

class ProductA implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductA");
	}
}

class ProductB implements IProduct {

	@Override
	public void productMethod() {
		System.out.println("ProdectB");
	}
}

2.創造型:單例
package com.seezoon.建立型.單例;

import jdk.internal.dynalink.beans.StaticClass;

/**
 * 簡單單例模式(嚴格的單例模式一般情況不適用可自行科普。) 
 * @author DF
 *  單例模式(Singleton)
          單例物件(Singleton)是一種常用的設計模式。在Java應用中,單例物件能保證在一個JVM中,
          該物件只有一個例項存在。這樣的模式有幾個好處:
    1、某些類建立比較頻繁,對於一些大型的物件,這是一筆很大的系統開銷。
    2、省去了new操作符,降低了系統記憶體的使用頻率,減輕GC壓力。
    3、有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以建立多個的話,系統完全亂了。
       (比如一個軍隊出現了多個司令員同時指揮,肯定會亂成一團),所以只有使用單例模式,才能保證核心交易伺服器獨立控制整個流程。
       
   Singleton是一種建立型模式,指某個類採用Singleton模式,則在這個類被建立後,只可能產生一個例項供外部訪問,並且提供一個全域性的訪問點。
核心知識點如下:
(1) 將採用單例設計模式的類的構造方法私有化(採用private修飾)。
(2) 在其內部產生該類的例項化物件,並將其封裝成private static型別。
(3) 定義一個靜態方法返回該類的例項。    
 */

/**
 * 1.單例模式的實現:飽漢式,非執行緒安全
 * 優點是:寫起來比較簡單,當類SingletonTest被載入的時候,靜態變數static的instance未被建立並分配記憶體空間,
 * 當getInstance方法第一次被呼叫時,初始化instance變數,並分配記憶體,因此在某些特定條件下會節約了記憶體;
缺點是:併發環境下很可能出現多個SingletonTest例項。
 * @author HP
 *
 */
public class Singleton {

	/* 持有私有靜態例項,防止被引用,此處賦值為null,目的是實現延遲載入 */  
    private static Singleton instance = null;  
    /* 私有構造方法,防止被例項化 */  
    private Singleton() {  
    }  
    /* 靜態工程方法,建立例項 */  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

/**
 * 2.單例模式的實現:餓漢式,執行緒安全 但效率比較低 
 * 優點是:寫起來比較簡單,而且不存在多執行緒同步問題,避免了synchronized所造成的效能問題;
缺點是:當類SingletonTest被載入的時候,會初始化static的instance,靜態變數被建立並分配記憶體空間,
從這以後,這個static的instance物件便一直佔著這段記憶體(即便你還沒有用到這個例項),
當類被解除安裝時,靜態變數被摧毀,並釋放所佔有的記憶體,因此在某些特定條件下會耗費記憶體。
 */

/**public*/ class SingletonTest {  

    // 定義一個私有的構造方法
    private SingletonTest() {  
    }  

    // 將自身的例項物件設定為一個屬性,並加上Static和final修飾符
    private static final SingletonTest instance = new SingletonTest();  

    // 靜態方法返回該類的例項
    public static SingletonTest getInstancei() {  
        return instance;  
    }  
  
}
3.建立型.:工廠方法.多個工廠方法
package com.seezoon.建立型.工廠方法.多個工廠方法;


/**
 * 多個工廠方法模式
 * 是對普通工廠方法模式的改進,在普通工廠方法模式中,
 * 如果傳遞的字串出錯,則不能正確建立物件,而多個工廠方法模式是提供多個工廠方法,分別建立物件
 * @author DF
 *
 */
public class MutiFactoryMethod {
	public static void main(String[] args) {
		MutiFactory factory = new MutiFactory();
		IProduct product = factory.produceA();
		product.productMethod();
	}
}
class MutiFactory{
	public IProduct produceA(){
		return new ProductA();
	}
	public IProduct produceB(){
		return new ProductB();
	}
}

interface IProduct {
	public void productMethod();
}

class ProductA implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductA");
	}
}

class ProductB implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductB");
	}
}
4.創造型:靜態工廠
package com.seezoon.建立型.工廠方法.靜態工廠;


/**
 * 靜態工廠方法模式
 * 將多個工廠方法模式裡的方法置為靜態的,不需要建立例項,直接呼叫即可
 * @author DF
 *
 */
public class StaticiFactoryMethod {
	public static void main(String[] args) {
		IProduct product = StaticFactory.produceA();
		product.productMethod();
	}
}
class StaticFactory{
	public static IProduct produceA(){
		return new ProductA();
	}
	public static IProduct produceB(){
		return new ProductB();
	}
}
interface IProduct {
	public void productMethod();
}

class ProductA implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductA");
	}
}

class ProductB implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductB");
	}
}
5.創造型:普通工廠方法
package com.seezoon.建立型.工廠方法.普通工廠模式;

/**
 * 普通工廠方法比較常用
 * @author DF
 *
 */
public class NormalFactoryMethod {

	
	public static void main(String[] args) {
		Factory factory= new Factory();
		IProduct product = factory.produce("A");
		product.productMethod();
	}
}
class Factory{
	/**
	 * 一般可以做成配置 比如xml 
	 * @param product
	 * @return
	 */
	public IProduct produce(String product){
		if ("A".equals(product)) {
			return new ProductA();
		} else if ("B".equals(product)) {
			return new ProductB();
		} else {
			return null;
		}
	}
}
interface IProduct {
	public void productMethod();
}

class ProductA implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductA");
	}
}

class ProductB implements IProduct {
	@Override
	public void productMethod() {
		System.out.println("ProductB");
	}
}

6.創造型:建造者
package com.seezoon.建立型.建造者;


/**
 * 建造者模式
 * @author DF
 * 工廠模式關注的是建立單個產品,而建造者模式則關注建立符合物件
 */
public class Builder {
	 public static void main(String []args){
	        Director dir = new Director();
	        dir.getProduct1().showProduct();
	        dir.getProduct2().showProduct();
	    }
}
class Director {
    private AbsBuild build = new Build();
    public Product getProduct1(){
        build.setProd("df",15);
        return build.getProduct();
    }
    public Product getProduct2(){
        build.setProd("df",20);
        return build.getProduct();
    }
}


abstract class AbsBuild {
    public abstract void setProd(String name,int num);
    public abstract Product getProduct();
}
class Build extends AbsBuild {
    Product product = new Product();
    @Override
    public void setProd(String name, int num) {
        //To change body of implemented methods use File | Settings | File Templates.
        product.setName(name);
        product.setNum(num);
    }

    @Override
    public Product getProduct() {
        return product;
    }
}

class Product {
    private String name;
    private int num;

    public void showProduct(){
        System.out.println("name :"+name);
        System.out.println("age:"+num);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

7.創造型:原型
package com.seezoon.建立型.原型;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 
 * @author DF
 *原型模式雖然是建立型的模式,但是與工程模式沒有關係,從名字即可看出,
 *該模式的思想就是將一個物件作為原型,對其進行復制、克隆,產生一個和原物件類似的新物件。
 *在Java中,複製物件是通過clone()實現的
 */
public class Prototype implements Cloneable,Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public void print(){
		System.out.println("hello Prototype !!!!!");
	}
	/**
	 * 該做法為淺複製
	 * 淺複製:將一個物件複製後,基本資料型別的變數都會重新建立,而引用型別,指向的還是原物件所指向的。
	 */
	public Prototype clone() throws CloneNotSupportedException {  
        Prototype proto = (Prototype) super.clone();  
        return proto;  
    }  
	/**
	 * 深複製
	 * 深複製:將一個物件複製後,不論是基本資料型別還有引用型別,都是重新建立的。
	 * 簡單來說,就是深複製進行了完全徹底的複製,而淺複製不徹底
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
    public Prototype deepClone() throws IOException, ClassNotFoundException {  
  
        /* 寫入當前物件的二進位制流 */  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        ObjectOutputStream oos = new ObjectOutputStream(bos);  
        oos.writeObject(this);  
        /* 讀出二進位制流產生的新物件 */  
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
        ObjectInputStream ois = new ObjectInputStream(bis);  
        Prototype prototype = (Prototype) ois.readObject();  
        ois.close();
        bis.close();
        oos.close();
        bos.close();
        return prototype;
    }  
    public static void main(String[] args) throws Exception {
    	Prototype prototype = new Prototype();
    	Prototype prototypeClone = prototype.clone();
    	Prototype prototypeDeepClone = prototype.deepClone();
    	prototypeClone.print();
    	prototypeDeepClone.print();
	}
}

8.結構型:代理
package com.seezoon.結構型.代理;

/**
 * 
 * @author DF
 *其實每個模式名稱就表明了該模式的作用,代理模式就是多一個代理類出來,
 *替原物件進行一些操作,比如我們在租房子的時候回去找中介,為什麼呢?
 *因為你對該地區房屋的資訊掌握的不夠全面,希望找一個更熟悉的人去幫你做,此處的代理就是這個意思。再如我們有的時候打官司,
 *我們需要請律師,因為律師在法律方面有專長,可以替我們進行操作,表達我們的想法
 *
 *
 *代理模式的應用場景:
	如果已有的方法在使用的時候需要對原有的方法進行改進,此時有兩種辦法:
	1、修改原有的方法來適應。這樣違反了“對擴充套件開放,對修改關閉”的原則。
	2、就是採用一個代理類呼叫原有的方法,且對產生的結果進行控制。這種方法就是代理模式。
	使用代理模式,可以將功能劃分的更加清晰,有助於後期維護!
 */
public class ProxySample {
	 public static void main(String[] args) {  
	        Sourceable source = new Proxy();  
	        source.method();  
	    }  
}
interface Sourceable {  
    public void method();  
} 
class Source implements Sourceable {  
	  
    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
}  
class Proxy implements Sourceable {  
	  
    private Source source;  
    public Proxy(){  
        super();  
        this.source = new Source();  
    }  
    @Override  
    public void method() {  
        before();  
        source.method();  
        atfer();  
    }  
    private void atfer() {  
        System.out.println("after proxy!");  
    }  
    private void before() {  
        System.out.println("before proxy!");  
    }  
}  
9.結構型:橋接
package com.seezoon.結構型.橋接;

/**
 * 
 * @author DF
 *橋接模式就是把事物和其具體實現分開,使他們可以各自獨立的變化。
 *橋接的用意是:將抽象化與實現化解耦,使得二者可以獨立變化,像我們常用的JDBC橋DriverManager一樣,
 *JDBC進行連線資料庫的時候,在各個資料庫之間進行切換,基本不需要動太多的程式碼,
 *甚至絲毫不用動,原因就是JDBC提供統一介面,
 *每個資料庫提供各自的實現,用一個叫做資料庫驅動的程式來橋接就行了
 *
 *
 *
 *通過對Bridge類的呼叫,實現了對介面Sourceable的實現類SourceSub1和SourceSub2的呼叫
 */
public class BridgeSample {
	public static void main(String[] args) {  
        
        Bridge bridge = new MyBridge();  
          
        /*呼叫第一個物件*/  
        Sourceable source1 = new SourceSub1();  
        bridge.setSource(source1);  
        bridge.method();  
          
        /*呼叫第二個物件*/  
        Sourceable source2 = new SourceSub2();  
        bridge.setSource(source2);  
        bridge.method();  
    }  
}
interface Sourceable {  
    public void method();  
}  
class SourceSub1 implements Sourceable {  
	  
    @Override  
    public void method() {  
        System.out.println("this is the first sub!");  
    }  
}  
class SourceSub2 implements Sourceable {  
	  
    @Override  
    public void method() {  
        System.out.println("this is the second sub!");  
    }  
}  
abstract class Bridge {  
    private Sourceable source;  
  
    public void method(){  
        source.method();  
    }  
      
    public Sourceable getSource() {  
        return source;  
    }  
  
    public void setSource(Sourceable source) {  
        this.source = source;  
    }  
}  
class MyBridge extends Bridge {  
    public void method(){  
        getSource().method();  
    }  
}  

10.結構型:物件介面卡

package com.seezoon.結構型.介面卡.物件介面卡;

/**
 * 物件介面卡
 * @author DF
 *物件的介面卡模式:當希望將一個物件轉換成滿足另一個新介面的物件時,可以建立一個Adapter類,持有原類的一個例項,
 *在Adapter類的方法中,呼叫例項的方法就行。
 */
public class ObjectAdapter {
	public static void main(String[] args) {
		Source source = new Source();
		Adapter adapter = new Adapter(source);
		adapter.method1();
		adapter.method2();
	}
}

class Source {
	public void method1() {
		System.out.println("this is original method!");
	}
}

interface Targetable {
	/* 與原類中的方法相同 */
	public void method1();

	/* 新類的方法 */
	public void method2();
}

class Adapter implements Targetable {

	private Source source;

	public Adapter(Source source) {
		super();
		this.source = source;
	}

	@Override
	public void method2() {
		System.out.println("this is the targetable method!");
	}

	@Override
	public void method1() {
		source.method1();
	}
}