Java實現23種設計模式教程(作者原創)
總結:主要依靠if elseif 在一個大的工廠類中根據不同的傳參來new不同的對象,這個大的工廠必須要是一個品類,比如手機工廠和電腦工廠要分開,后面的抽象工廠模式才能通過一個品牌分類,這里簡單工廠和工廠方法只能一個種類的工廠(但是可以寫多個工廠類)
實體類要提供一個類型的接口,工廠模式返回對象需要多態,所以要有接口或者父類
public interface phone { //使用接口來實現多態寫法 String getPhoneName(); }
public class iphone implements phone { /** * 蘋果手機 */ private String id; private String name; private double price; public iphone() { } public iphone(String id, String name, double price) { this.id = id; this.name = name; this.price = price; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "iphone{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}'; } @Override public String getPhoneName() { return this.name; } }
public class xiaomiPhone implements phone { /** * 小米手機 */ private String id; private String name; private double price; public xiaomiPhone() { } public xiaomiPhone(String id, String name, double price) { this.id = id; this.name = name; this.price = price; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "xiaomiPhone{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}'; } @Override public String getPhoneName() { return this.name; } }
簡單工廠(核心代碼實現)
public class phoneFactory { /** * 簡單工廠模式 * 缺點:不滿足設計模式原則-開閉原則(對擴展性開,對修改關閉) */ //簡單工廠根據傳參去判斷new哪個對象,因為這里要使用多態寫法,所以下面要定義一個接口,哪怕空接口都行,extends也行 public static phone getPhone(String name){ if(name==null||name.equals("")) return null; if(name.equals("小米")) return new xiaomiPhone("mi-001","小米11",4999.0); else if(name.equals("蘋果")) return new iphone("iphone-888","iPhone12 Pro max",10999.0); return null; } }
測試
class phoneFactoryMain{ public static void main(String[] args) { //通過工廠就可以獲得對象 phone p1 = phoneFactory.getPhone(""); phone p2 = phoneFactory.getPhone("小米"); phone p3 = phoneFactory.getPhone("蘋果"); System.out.println(p1); System.out.println(p2.getPhoneName()); System.out.println(p3.getPhoneName()); } }
null 小米11 iPhone12 Pro max
試想,當我們需要添加一款手機的時候,我們需要在工廠類的if else 里面添加new新手機的代碼,這樣就違反了設計模式的開閉原則了,這時候我們如果很介意這個開閉原則的話,可以使用工廠方法模式
總結:工廠方法也就是為了解決簡單工廠不滿足設計模式原則中的開閉原則,工廠方法不采用簡單工廠那種在一個大工廠(單一類型,比如手機工廠、電腦工廠要分開不同的工廠)中通過if elseif 根據不同的傳參來new不同的對象了,而是把這個大的工廠拆分。拆分成一個工廠接口,
簡單工廠是一個大的綜合一個類型的工廠,而工廠方法模式是各自品牌類型的東西單獨建立一個工廠,這樣更符合我們日常生活的情況,比如手機里面有小米手機、蘋果手機,這樣工廠又會拆分成小米手機工廠、蘋果手機工廠
public abstract class factory { /** * 這個工廠是生產手機,所以我們要提供一個抽象方法來生產手機 */ //抽象類的獲取手機方法,一定不能指定獲取什么手機,要用多態。 abstract phone getPhoneByFactory(); }
蘋果手機工廠
public class iPhoneFactory extends factory { /** * 蘋果手機工廠 */ @Override phone getPhoneByFactory() { return new iphone("iphone-888","iPhone12 Pro max",10999.0); } }
小米手機工廠
public class xiaomiFactory extends factory{ /** * 小米手機工廠 */ @Override phone getPhoneByFactory() { return new xiaomiPhone("mi-001","小米11",4999.0); } }
蘋果手機實體類
public class iphone implements phone { /** * 蘋果手機 */ private String id; private String name; private double price; public iphone() { } public iphone(String id, String name, double price) { this.id = id; this.name = name; this.price = price; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "iphone{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}'; } }
小米手機實體類
public class xiaomiPhone implements phone{ //小米手機 private String id; private String name; private double price; public xiaomiPhone() { } public xiaomiPhone(String id, String name, double price) { this.id = id; this.name = name; this.price = price; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "xiaomiPhone{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}'; } }
手機接口:
public interface phone { }
利用各自的手機工廠創建手機對象
public class factoryMethodMain { public static void main(String[] args) { factory xiaomiFactory = new xiaomiFactory(); factory iPhoneFactory = new iPhoneFactory(); System.out.println(xiaomiFactory.getPhoneByFactory()); System.out.println(iPhoneFactory.getPhoneByFactory()); } }
抽象工廠模式(很大的工廠)
總結:抽象工廠模式是生產一個品牌的任何產品(比如某一個抽象工廠,小米工廠去實現它,那么小米工廠就是抽象工廠的子類,也就是說小米工廠可以小米品牌下的所有商品,也就是說這個小米工廠可以生產小米手機、小米筆記本、小米電腦、小米耳機等等。。。),而工廠模式不可以,工廠模式只能生產同一類產品,比如就生產筆記本,但是。如果抽象工廠定義的生產產品只有一類品牌產品,那么這個抽象工廠模式就和工廠模式沒有區別了。(當且僅當抽象工廠只有一個抽象方法時)
需求:小米公司和華為公司要生產手機和電腦。
定義抽象工廠:
public abstract class abstractFactory { /** * 抽象工廠模式的抽象工廠:生產手機和電腦 * 如果是工廠方法模式的抽象工廠:只能生產手機或者只生產電腦 */ public abstract phone getPhone(); //生產手機 public abstract computer getComputer(); //生產電腦 }
定義華為品牌的工廠(生產多個類型產品)
public class huaweiFactory extends abstractFactory { @Override public phone getPhone() { return new huaweiPhone("h-05","華為Mate40 pro",5388.0); } @Override public computer getComputer() { return new huaweiComputer("h-33","華為筆記本電腦",5800.0); } }
定義小米品牌的工廠(生產多個類型產品)
public class xiaomiFactory extends abstractFactory { @Override public phone getPhone() { return new xiaomiPhone("x-01","小米11",3999.0); } @Override public computer getComputer() { return new xiaomiComputer("x-22","小米筆記本電腦",5213.0); } }
手機接口:
public interface phone { }
電腦接口:
public interface computer { }
實體類:
public class xiaomiPhone implements phone { /** * 小米手機 */ private String id; private String name; private double price; public xiaomiPhone() { } public xiaomiPhone(String id, String name, double price) { this.id = id; this.name = name; this.price = price; }
public class huaweiComputer implements computer { private String id; private String name; private double price; public huaweiComputer() { } public huaweiComputer(String id, String name, double price) { this.id = id; this.name = name; this.price = price; }
測試類:
public class abstractFactoryMain { /** * 抽象工廠模式 */ public static void main(String[] args) { //創建小米的大工廠 xiaomiFactory xiaomiFactory = new xiaomiFactory(); //創建華為的大工廠 huaweiFactory huaweiFactory = new huaweiFactory(); //從小米的大工廠中生產小米手機和小米筆記本 phone xiaomiPhone = xiaomiFactory.getPhone(); computer xiaomComputer = xiaomiFactory.getComputer(); System.out.println(xiaomiPhone); System.out.println(xiaomComputer); //從華為的大工廠中生產華為手機和華為筆記本 System.out.println("======================="); phone huaweiPhone = huaweiFactory.getPhone(); computer huaweiComputer = huaweiFactory.getComputer(); System.out.println(huaweiPhone); System.out.println(huaweiComputer); } }
建造者模式
用于創建復雜對象,比如構造方法多變的情況下使用建造者模式很好用
建造者所需角色:抽象建造者、具體建造者、指揮者(非必要,可有可無:用于拼裝建造的順序)、測試
比如有一個項目:我們要建造一臺電腦,里面有cpu、顯卡、內存條、鍵盤等等。。(使用建造者模式實現這個項目)
抽象建造者:
public abstract class builder { //抽象建造者提供建造對象所需要的方法 /* 實現鏈式編程,addCPU等方法要返回一個builder對象 */ public abstract builder addCPU(String cpu); //添加CPU public abstract builder addXianka(String xianka); //添加顯卡 public abstract builder addShubiao(String shubiao); //添加鼠標 public abstract builder addKeyboard(String keyboard);//添加鍵盤 public abstract builder addMemory(String memory); //添加內存條 public abstract computer builderComputer(); //返回構建的computer對象 }
具體建造者:
public class computerBuilder extends builder { private computer computer=new computer(); //給電腦默認屬性 public computerBuilder(){ computer.setCpu("i3"); computer.setKeyboard("聯想鍵盤"); computer.setMemory("金士頓8g內存"); computer.setShubiao("華碩鼠標"); computer.setXianka("GTX1060"); } @Override public builder addCPU(String cpu) { computer.setCpu(cpu); return this; //返回當前調用者的對象,實現鏈式編程 } @Override public builder addXianka(String xianka) { computer.setXianka(xianka); return this; } @Override public builder addShubiao(String shubiao) { computer.setShubiao(shubiao); return this; } @Override public builder addKeyboard(String keyboard) { computer.setKeyboard(keyboard); return this; } @Override public builder addMemory(String memory) { computer.setMemory(memory); return this; } @Override public computer builderComputer() { return computer; } }
public class computer { private String cpu; private String xianka; private String shubiao; private String keyboard; private String memory; //內存 public computer() { } public computer(String cpu, String xianka, String shubiao, String keyboard, String memory) { this.cpu = cpu; this.xianka = xianka; this.shubiao = shubiao; this.keyboard = keyboard; this.memory = memory; } public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public String getXianka() { return xianka; } public void setXianka(String xianka) { this.xianka = xianka; } public String getShubiao() { return shubiao; } public void setShubiao(String shubiao) { this.shubiao = shubiao; } public String getKeyboard() { return keyboard; } public void setKeyboard(String keyboard) { this.keyboard = keyboard; } public String getMemory() { return memory; } public void setMemory(String memory) { this.memory = memory; } @Override public String toString() { return "computer{" + "cpu='" + cpu + '\'' + ", xianka='" + xianka + '\'' + ", shubiao='" + shubiao + '\'' + ", keyboard='" + keyboard + '\'' + ", memory='" + memory + '\'' + '}'; } }
director(可寫可不寫):也可以直接操作具體建造者,下面會有用director和不用director的寫法:
public class director { /** * 指揮者。用來拼裝具體建造者實現的方法 */ private builder builder; // 私有化構造器,也可以不這么寫 private director(){ } public director(builder builder){ this.builder=builder; } //拼裝方法 public computer builder(){ builder.addCPU("director_cpu"); builder.addXianka("director_xianka"); return builder.builderComputer(); } }
Main測試:
public class builderMain { public static void main(String[] args) { System.out.println("不采用director類"); //不采用director類 builder builder=new computerBuilder(); computer computer = builder.builderComputer(); System.out.println(computer); computer computer1 = builder.addCPU("i5").addXianka("RTX2080").builderComputer(); System.out.println(computer1); computer computer2 = builder.addCPU("i7").addXianka("RTX2090").addMemory("金士頓32g").addShubiao("華為鼠標").builderComputer(); System.out.println(computer2); System.out.println("============="); System.out.println("采用director類"); //采用director類 director director = new director(new computerBuilder()); computer builder1 = director.builder(); System.out.println(builder1); } }
代理模式
被代理的類
public class logger implements Mylogger { /** * 靜態代理: * 當我們有個接口的實現類,其中需要對實現類的方法進行增強而不修改源代碼,我們可以用代理模式 * 需求:我們想不改變源代碼的情況下對下面 System.out.println("寫入日志。");的前面和后面加入一個輸出語句 * * 實現:我們只需要創建一個logger的代理類,并實現Mylogger接口,重寫方法即可 */ @Override public void writerLog() { System.out.println("寫入日志。"); } }
接口:
public interface Mylogger { public void writerLog(); }
代理類:
public class proxyLogger implements Mylogger { private Mylogger mylogger; public proxyLogger(Mylogger logger){ this.mylogger=logger; } @Override public void writerLog() { //增強的方法 System.out.println("logger被代理了===前"); mylogger.writerLog(); //需要增強的方法 System.out.println("logger被代理了===后"); } }
測試:
public class staticProxyMain { public static void main(String[] args) { proxyLogger proxyLogger = new proxyLogger(new logger()); proxyLogger.writerLog(); } }
結果:
logger被代理了===前 寫入日志。 logger被代理了===后
網站
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。