java基础之设计模式
1 設置模式之單例設計模式
概念:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
(1)餓漢式:
/*** @Description 餓漢式* @author refuel* @version v1.0*/ public class TestSingleton{public static void main(String[] args) {Singleton sing = Singleton.getInstance(); sing.show();} } class Singleton { //1、將構造器私有化private Singleton() {}//2、定義創建一個私有對象 private static Singleton Sing = new Singleton();//3、定義公共靜態方法返回該類類型的對象 public static Singleton getInstance() {return Sing;} }(2)飽漢式,線程不安全
/*** @Description 飽漢式,線程不安全* @author refuel* @version v1.0*/ public class TestSingleton{public static void main(String[] args) {Singleton sing = Singleton.getInstance(); sing.show();} } class Singleton { //1、將構造器私有化private Singleton() {}//2、定義創建一個私有對象 private static Singleton Sing;//3、定義公共靜態方法返回該類類型的對象 public static Singleton getSingleton() {if(Sing == null) {Sing = new Singleton();}return Sing;} }?
2?設置模式之工廠模式
2.1 簡單工廠
簡單工廠模式其實不是一個設計模式,反而比較像一種編程習慣。主要我們定義一個非常簡單的類主要負責幫我們生產不同的產品。例子如下:
/*** @Description 簡單工廠* @author refuel* @version v1.0*/ public class SimpleFactory {//④使用工廠方法,通過傳遞類型信息來獲取實體類的對象public static void main(String[] args) {Factory1 w = new Factory1();//獲取Student1Work的對象,并調用他的doWork方法Product1 product = w.getExamples("Student1Work");product.show();//獲取Teacher1Work的對象,并調用他的doWork方法Product1 product1 = w.getExamples("Teacher1Work");product1.show();//獲取Worker1Work的對象,并調用他的doWork方法Product1 product2 = w.getExamples("Worker1Work");product2.show();}}//①創建一個 Product接口 interface Product1{void show(); } // ②實現Product 接口的實體類 class Student1 implements Product1 {@Overridepublic void show() {System.out.println("學生學習");} } class Teacher1 implements Product1 {@Overridepublic void show() {System.out.println("老師教書育人");} } class Worker1 implements Product1 {@Overridepublic void show() {System.out.println("工人建高樓大廈");} } //③定義工廠類 生成基于給定信息的實體類的對象 class Factory1 {//使用getExamples方法獲取工作性質類型的對象public Product1 getExamples(String workType) {if(workType ==null) {return null;}if(workType.equalsIgnoreCase("Student1Work")) {return new Student1();}else if(workType.equalsIgnoreCase("Teacher1Work")) {return new Teacher1();}else if(workType.equalsIgnoreCase("Worker1Work")) {return new Worker1();}return null;} }2.2 工廠方法模式
簡單工廠模式有一個缺點是不同的產品需要不同的額外參數的時候,是不支持的,而且如果使用時傳遞的type、Class出錯,將不能得到正確的對象,容錯率不高。而多方法的工廠模式為不同產品,提供不同的生產方法,使用時 需要哪種產品就調用該種產品的方法,使用方便、容錯率高。
工廠方法模式概念:定義一個用于創建對象的接口,但是讓子類決定將哪一個類實例化。工廠父類負責定義創建產品對象的公共接口,而工廠子類則負責生成具體的產品對象,目的是將產品類的實例化操作延遲到工廠子類中完成,即通過工廠子類來確定究竟應該實例化哪一個具體產品類
何時使用:主要解決接口選擇的問題,我們明確地計劃不同條件下創建不同實例時。
/*** @Description 工廠模式* @author refuel* @version v1.0*/ public class FactoryPattern {public static void main(String[] args) {Factory2 s = new StudentFactory2();s.getExamples().show();Factory2 t = new TeacherFactory2();t.getExamples().show();Factory2 w = new WorkerFactory2();w.getExamples().show();}}//①創建一個 Product接口 interface Product2{void show(); } // ②實現Product 接口的實體類 class Student2 implements Product2 {@Overridepublic void show() {System.out.println("學生學習");} } class Teacher2 implements Product2 {@Overridepublic void show() {System.out.println("老師教書育人");} } class Worker2 implements Product2 {@Overridepublic void show() {System.out.println("工人建高樓大廈");} } //③定義一個工廠接口 interface Factory2 {Product2 getExamples(); } //④定義一個學生工廠接口 class StudentFactory2 implements Factory2 {public Product2 getExamples() {return new Student2();} } //⑤定義一個老師工廠接口 class TeacherFactory2 implements Factory2 {public Product2 getExamples() {return new Teacher2();} } //⑥定義一個工人工廠接口 class WorkerFactory2 implements Factory2 {public Product2 getExamples() {return new Worker2();} }2.3 抽象工廠模式
為創建一組相關或相互依賴的對象提供一個接口,而且無需指定他們的具體類。
抽象工廠模式,他用來創建一組相關或者相互依賴的對象。他與工廠方法模式的區別就在于,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構。通常一個產品結構,表現為一個接口或者抽象類,也就是說,工廠方法模式提供的所有產品都是衍生自同一個接口或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的接口或抽象類。
/*** @Description 抽象工廠模式* @author refuel* @version v1.0*/ public class AbstractFactoryPattern {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {AbstractFactory sbstractFactory = SuperFactory.getFactory("com.refuel.factory.StudentFactory");Product SmallStudent = sbstractFactory.getExamples("com.refuel.factory.SmallStudent");SmallStudent.show();}}//最高級抽象產品,用于抽象工廠的建造方法的返回值 abstract class Product{abstract void show(); } //學生產品類 abstract class StudentProduct extends Product{} //小學生產品 class SmallStudent extends StudentProduct{public void show() {System.out.println("小學生");} }//中學生產品 class MiddleStudent extends StudentProduct{public void show() {System.out.println("小學生");} } //老師產品類 abstract class TeacherProduct extends Product{} //數學老師產品 class MathTeacher extends TeacherProduct{public void show() {System.out.println("數學老師");} }//歷史老師產品 class HistoryTeacher extends TeacherProduct{public void show() {System.out.println("歷史老師");} }//超級工廠類 class SuperFactory {public static AbstractFactory getFactory(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class cl = Class.forName(type);System.out.println("創建工廠" + type);return (AbstractFactory) cl.newInstance();} } //抽象工廠類 abstract class AbstractFactory {protected abstract Product getExamples(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException; }//學生工廠類,覆蓋所有學生的生產方法 class StudentFactory extends AbstractFactory{public Product getExamples(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class cl = Class.forName(type);return (StudentProduct)cl.newInstance();} } //老師工廠類,覆蓋所有老師的生產方法 class TeacherFactory extends AbstractFactory{public Product getExamples(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class cl = Class.forName(type);return (TeacherProduct)cl.newInstance();} }2.4 簡單工廠模式,工廠模式與抽象工廠模式的比較
簡單工廠模式:(1)優點:工廠類中包含了必要的邏輯判斷,根據客戶端的選擇條件動態實例化相關的類,對于客戶端來說,去除了與具體產品的依賴。(2)缺點:沒有遵守開放—封閉原則(開放接口,封閉修改)。如果將來需要添加一個產品,那么,在簡單工廠模式中,就必須在簡單工廠類中添加相應的判斷語句,這對程序的擴展本身就不利。
工廠模式:(1)優點:?1、一個調用者想創建一個對象,只要知道其名稱就可以了。 2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以。 3、屏蔽產品的具體實現,調用者只關心產品的接口。(2)缺點:每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的復雜度,同時也增加了系統具體類的依賴。這并不是什么好事。
抽象工廠模式:(1)優點:能夠從多個產品族的多個產品中,簡潔的獲取想要的具體產品。解決了工廠模式中的不符合開閉原則的問題(增加新的產品時候,不修改工廠,而是增加工廠)。(2)缺點:產品族擴展比較困難,要增加一個系列的某一產品,要增加具體的產品類,還要增加對應的工廠類(或者修改對應產品族的工廠類)。產品族難擴展,產品等級易擴展。】
?
3 代理模式
提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操作,即擴展目標對象的功能。如果需改別人寫好的代碼時,可以通過代理的方式來擴展該方法。
3.1 靜態代理
靜態代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現相同的接口或者是繼承相同父類。
/*** @Description 靜態代理* @author refuel* @version v1.0*/ public class TestProxy {public static void main(String[] args) {//客戶租房子,找代理ProcyObject proxy = new ProcyObject(new SubjectImpl());proxy.action();} } //接口 interface Subject{void action(); } //中介(代理) class ProcyObject implements Subject {//中介和業主有關系,所以定義關聯關系SubjectImpl subject = null;public ProcyObject(SubjectImpl subject) {this.subject = subject;}@Overridepublic void action() {//調用業主的方法,自己沒有subject.action();}} //業主 class SubjectImpl implements Subject{@Overridepublic void action() {System.out.println("業主的房子");}}?
3.2 動態代理
動態代理也叫做:JDK代理,接口代理。代理對象不需要實現接口,但是目標對象一定要實現接口。代理對象的生成,是利用JDK的API,動態的在內存中構建代理對象(需要我們指定創建代理對象/目標對象實現的接口的類型)。
代理類所在包:java.lang.reflect.Proxy,JDK代理使用newProxyInstance方法。
/*** @Description 動態代理* @author refuel* @version v1.0*/ public class DynamicProxy {public static void main(String[] args) {//目標對象Subject1 s = new SubjectImpl1();//給目標對象創建代理對象,內存中動態生成的代理對象Subject1 proxy = (Subject1)new ProxyFactory(s).getProxyInstance();proxy.action();} }interface Subject1 {void action(); }/*** @Description 業主類* @author refuel* @version v1.0*/ class SubjectImpl1 implements Subject1 {@Overridepublic void action() {System.out.println("業主的房子");}}/*** @Description 代理工廠類* @author refuel* @version v1.0*/ class ProxyFactory {// 中介和業主有關系,所以定義關聯關系,來維護一個目標對象Object subject = null;public ProxyFactory(Object subject) {this.subject = subject;}// 給目標對象生成一個代理對象public Object getProxyInstance() {// ClassLoader loader:指定當前對象使用類加載器,獲取類加載器的方法是固定的// Class<?>[] interfaces:目標對象實現的接口類型,使用泛型方式確認// InvocationHandler h:事件處理,執行目標對象時,會觸發事件處理器的方法,會把當前執行的目標對象作為的方法作為參數傳入return Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("開始事務");// 執行目標對象方法Object invokeValue = method.invoke(subject, args);System.out.println("提交事務");return invokeValue;}});} }?
3.3 Cglib代理
Cglib代理,也叫作子類代理,它是在內存中構建一個子類對象從而實現對目標對象功能的擴展。靜態代理和動態代理模式都是要求目標對象實現一個接口,但是有時候目標對象只是一個單獨的對象,并沒有實現任何的接口,這個時候就可以使用以目標對象子類的方式類實現代理,這種方法就叫做:Cglib代理。
/*** @Description Cglib類* @author refuel* @version v1.0*/ public class CglibProxy {public static void main(String[] args) {//目標對象SubjectImpl2 target = new SubjectImpl2();//代理對象SubjectImpl2 proxy = (SubjectImpl2)new ProxyFactory(target).getProxyInstance();//執行代理對象的方法proxy.action();} } /*** @Description 業主類,目標對象,沒有實現任何接口* @author refuel* @version v1.0*/ class SubjectImpl2 {public void action() {System.out.println("業主的房子");} } /*** @Description Cglib子類代理工廠,對SubjectImpl2在內存中動態創建一個子類對象* @author refuel* @version v1.0*/ class ProxyFactory implements MethodInterceptor{// 中介和代理有關系,所以定義關聯關系,來維護一個目標對象Object subject = null;public ProxyFactory(Object subject) {this.subject = subject;}// 給目標對象創建一個代理對象public Object getProxyInstance() {//1.工具類Enhancer en = new Enhancer();//2.設置父類en.setSuperclass(subject.getClass());//3.設置回調函數en.setCallback(this);//4.創建子類(代理對象)return en.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("開始");//執行目標對象的方法Object returnValue = method.invoke(subject, args);System.out.println("提交");return returnValue;}}2.4 靜態代理,動態代理,Cglib代理的比較
靜態代理:(1)優點:可以做到在不修改目標對象的功能前提下,對目標功能擴展.。(2)缺點:因為目標對象要與代理對象實現一樣的接口,所以會產生很多的代理類,導致類太多。接口增加方法,目標對象與代理對象都要進行維護。
動態代理:(1)優點:由于java封裝了newProxyInstance這個方法的實現細節,所以使用起來非常方便。(2)缺點:靜態代理和JDK代理有一個共同的缺點,就是目標對象必須實現一個或多個接口
Cglib代理:(1)優點:目標對象與代理對象都不用實現接口。(2)缺點:因為沒有使用接口,所以系統的耦合性沒有使用JDK的動態代理好。
在Spring的AOP編程中,如果加入容器的目標對象有實現接口,用JDK代理,如果目標對象沒有實現接口,用Cglib代理
?
4 策略模式(Strategy Pattern)
4.1 什么是策略模式
針對一組算法,將每一種算法(策略類)都封裝到具有共同接口的獨立類中,從而他們可以相互替換,可以在不影響客戶端的情況下發生改變,從而改變不同的功能。
一個類的行為或其算法可以在運行時更改。這種類型的設計模式屬于行為型模式。
特點:封裝變化的概念;面向接口編程(編程中使用接口而不是使用具體的實現類)。
組成部分:(1)抽象策略角色:是抽象的角色,一般使用接口或抽象類實現,如Comparator接口;
(2)具體策略角色:包裝了具體的算法和行為,如一組實現了Comparator接口的實現類;
(3)環境角色:內部有一個抽象角色的引用,給客戶端調用,如TreeSet類,內部一定有一個策略類的一個成員變量,這樣在創建TreeSet對象的時候可以接收向它傳遞的具體的策略類。
4.2 為什么使用策略模式
在有多種算法相似的情況下,使用 if...else 所帶來的復雜和難以維護。算法可以自由切換,擴展良好;不過策略類會增多,還要對外暴露。
4.3 什么情況下可以使用
(1)如果一個系統中有很多的類,他們之間的區別是他們的行為不同,就可以用策略模式讓一個對象在那么多的行為中選擇一種;
(2)一個系統需要動態的在幾種算法中實現一種。
如果一個系統的策略多于四個,就需要考慮使用混合模式,解決策略類膨脹的問題。
4.4 案例
實現List集合增刪查的功能
編寫步驟:(1)定義抽象策略角色(定義一個策略對象的公共接口);(2)編寫具體策略角色(實現抽象策略角色這個公共接口);(3)定義環境變量(內部一定要持有一個策略類的引用)。
(1)?定義抽象策略角色:
/*** @Description 定義抽象策略角色* @author refuel* @version v1.0*/ public interface AbstarctStrategy<T> {//實現對List集合的操作public Boolean handle(List<T> list,T t); }(2)編寫具體策略角色
/*** @Description 定義增加策略* @author refuel* @version v1.0*/ public class AddStrategy<T> implements AbstarctStrategy<T> {//實現handle方法,完成增加元素操作@Overridepublic Boolean handle(List<T> list, T t) {return list.add(t);}}/*** @Description 定義刪除策略* @author refuel* @version v1.0*/ public class RemoveStrategy<T> implements AbstarctStrategy<T> {//實現handle方法,完成刪除元素操作@Overridepublic Boolean handle(List<T> list, T t) {return list.remove(t);}}/*** @Description 定義查詢策略* @author refuel* @version v1.0*/ public class QueryStrategy<T> implements AbstarctStrategy<T> {//實現handle方法,完成查看元素是否存在操作@Overridepublic Boolean handle(List<T> list, T t) {return list.contains(t);}}(3)定義環境變量
/*** @Description 環境角色* @author refuel* @version v1.0*/ public class Environment<T> {//策略類的引用private AbstarctStrategy<T> strategy;public Environment(AbstarctStrategy<T> strategy) {this.strategy = strategy;}public Boolean handleList(List<T> list,T t) {return strategy.handle(list, t);} }(4)測試
/*** @Description 測試類* @author refuel* @version v1.0*/ public class Test {public static void main(String[] args) {Environment<Integer> en = new Environment<>(new AddStrategy<Integer>());List<Integer> arrList = Arrays.asList(10,20,30,40,50);List<Integer> list = new ArrayList<>(arrList);en.handleList(list, 60);for (Integer i : list) {System.out.print(i + " "); //運行結果 10 20 30 40 50 60 }} }?
?
總結
以上是生活随笔為你收集整理的java基础之设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux历史追溯
- 下一篇: asp.net ajax控件工具集 Au