java 設計模式 常用21種
阿新 • • 發佈:2019-02-04
1.創造型:抽象工廠
2.創造型:單例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"); } }
3.建立型.:工廠方法.多個工廠方法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; } }
4.創造型:靜態工廠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"); } }
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();
}
}