創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
策略模式:定義了算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。
PS:即將對象的行爲抽象出來成一個接口,用一組類來實現接口的行爲,然後在對象類中使用接口來引用行爲類。
Duck類
package headfirst.strategy;
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public void swim() {
System.out.println("Duck can swim!");
}
public void performQuack() {
quackBehavior.quack();
}
public void performFly() {
flyBehavior.fly();;
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
接口行爲
package headfirst.strategy;
public interface QuackBehavior {
void quack();
}
package headfirst.strategy;
public interface FlyBehavior {
void fly();
}
接口行爲實現
package headfirst.strategy;
public class FlyWithSwing implements FlyBehavior{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("fly");
}
}
package headfirst.strategy;
public class Squack implements QuackBehavior{
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("zhi zhi zhi");
}
}
package headfirst.strategy;
public class Quack implements QuackBehavior{
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("gagaga");
}
}
實現的鴨子
package headfirst.strategy;
public class WhiteDuck extends Duck{
public WhiteDuck() {
flyBehavior = new FlyWithSwing();
quackBehavior = new Quack();
}
public static void main(String[] args) {
Duck model = new WhiteDuck();
model.performFly();
model.performQuack();
model.setQuackBehavior(new MuteQuack());
model.performQuack();
}
}
被觀察對象 observer
鬆耦合 出版者 + 訂閱者
觀察者模式:定義了對象之間一對多依賴,這樣一來,當一個對象狀態改變時,他的所有依賴者都會收到通知並更新。
PS:出版者發生信息變化的時候會通知所有訂閱者,訂閱者和第三方類可以退訂或者訂購出版者的消息。
Subject接口 Observer接口
registerObserver(); update();
removeObserver(); 需要保存出版者的引用
notifyObserver(); 方便退訂操作
實現類中有一個List<Observer>
當信息改變時,循環調用所有Observer
的update();
java內置的 Observable 類 Observer接口
update(Observable obs,Object arg);
這裏可以自定義用obs來get想要的數據
這裏繼承後可以設置
一個changd=false
當狀態改變到一定時
設置true並調用update
接口 可以在Subject中設置一個flag 然後當數據變化到一定變化時再設置爲true執行
package headfirst.observer;
public interface Observer {
void update(double temple,double dryrate);//推數據
void update(Subject subject,Object arg);//拉數據,可觀察者自定義拉所需要的數據
}
package headfirst.observer;
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObserver();
}
實現類
package headfirst.observer;
import java.util.LinkedList;
import java.util.List;
/**
* Created by Alen on 2018/9/28.
*/
public class WeatherData implements Subject{
private double temple;
private double dryrate;
private List<Observer> observers ;
WeatherData(){
observers = new LinkedList<Observer>();
}
public double getTemple() {
return temple;
}
public double getDryrate() {
return dryrate;
}
public void measureChanged(){
notifyObserver();
}
public void setMeasure(double temple,double dryrate){
this.dryrate = dryrate;
this.temple = temple;
measureChanged();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i =observers.indexOf(o);
if(i>=0){
observers.remove(i);
}
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update( temple, dryrate);
}
}
}
package headfirst.observer;
/**
* Created by Alen on 2018/9/28.
*/
public class Display implements Observer {
Subject subject;
private double temple;
private double dryrate;
Display( Subject subject){
this.subject=subject;
subject.registerObserver(this);
}
@Override
public void update(double temple,double dryrate) {
this.dryrate = dryrate;
this.temple = temple;
display();
}
public void display(){
System.out.println("this"+dryrate+","+temple);
}
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Display display= new Display(weatherData);
weatherData.setMeasure(20,20);
}
}
利用Java Util包的實現
package headfirst.observer.useutil;
import java.util.Observable;
/**
* Created by Alen on 2018/9/28.
*/
public class WeatherData extends Observable{
private double temple;
private double dryrate;
WeatherData(){
}
public void measureChanged(){
setChanged();
notifyObservers();
}
public void setMeasure(double temple,double dryrate){
this.dryrate = dryrate;
this.temple = temple;
measureChanged();
}
public double getTemple() {
return temple;
}
public double getDryrate() {
return dryrate;
}
}
package headfirst.observer.useutil;
import java.util.Observable;
import java.util.Observer;
/**
* Created by Alen on 2018/9/28.
*/
public class Display implements Observer {
private double temple;
private double dryrate;
Observable observable;
Display(Observable observable){
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable observable, Object arg) {
if (observable instanceof Observable){
WeatherData weatherData = (WeatherData) observable;
this.dryrate = weatherData.getDryrate();
this.temple = weatherData.getTemple();
display();
}
}
public void display(){
System.out.println("this"+dryrate+","+temple);
}
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Display display = new Display(weatherData);
weatherData.setMeasure(1,1);
}
}
裝飾者模式:動態地將責任附加到對象上,若需要擴展功能,裝飾者提供了比繼承更有彈性的替代方案
基礎類
package headfirst.decorator;
//飲料類
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
咖啡類
package headfirst.decorator;
//濃咖啡
public class Espresso extends Beverage {
public Espresso(){
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
package headfirst.decorator;
//另外一種飲料
public class HouseBlend extends Beverage {
public HouseBlend(){
description = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
裝飾器類
package headfirst.decorator;
//調料裝飾者
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
package headfirst.decorator;
/**
* Created by Alen on 2018/9/28.
*/
public class Moka extends CondimentDecorator {
Beverage beverage ;
public Moka (Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Moka";
}
@Override
public double cost() {
return 0.2+beverage.cost();
}
public static void main(String[] args) {
HouseBlend houseBlend = new HouseBlend();
Moka moka = new Moka(houseBlend);
System.out.println(moka.getDescription()+""+moka.cost());
Espresso espresso =new Espresso();
Moka moka1 = new Moka(espresso );
System.out.println(moka1.getDescription()+""+moka1.cost());
//double moka
Moka moka2 =new Moka(moka1);
System.out.println(moka2.getDescription()+""+moka2.cost());
}
}
簡單工廠(Simple Factory)又叫做靜態工廠方法(Static Factory Method) 有一個產品接口沒有工廠接口
package com.wenniuwuren.simplefactory;
/**
* 工廠(Creator)角色 :簡單工廠模式的核心,它負責實現創建所有實例的內部邏輯。
* 工廠類可以被外界直接調用,創建所需的產品對象。
*
*/
public class SomethingCreator {
// 靜態工廠 這就是爲什麼簡單工廠又叫靜態工廠方法
public static Tree factory(String fruitType) throws Exception{
if(fruitType.equals("Lemon")){
return new LemonTree();
}else if(fruitType.equals("Apple")){
return new AppleTree();
}else{
throw new Exception("暫時不支持生產該類型產品");
}
}
}
工廠方法模式:定義了一個創建對象的接口,但是由子類決定要實例化哪一個類,工廠方法把讓類實例化推遲到子類。
抽象工廠模式:提供了一個接口,用於創建相關或依賴對象的家族,而不需要指定具體類
工廠方法模式:
一個抽象產品類,可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類只能創建一個具體產品類的實例。
抽象工廠模式:
多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類可以創建多個具體產品類的實例,也就是創建的是一個產品線下的多個產品。
區別:
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。
工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個。
工廠方法創建 "一種" 產品,他的着重點在於"怎麼創建",也就是說如果你開發,你的大量代碼很可能圍繞着這種產品的構造,初始化這些細節上面。也因爲如此,類似的產品之間有很多可以複用的特徵,所以會和模版方法相隨。
抽象工廠需要創建一些列產品,着重點在於"創建哪些"產品上,也就是說,如果你開發,你的主要任務是劃分不同差異的產品線,並且儘量保持每條產品線接口一致,從而可以從同一個抽象工廠繼承。
單例模式:確保一個類只有一個實例,並且提供全局訪問點
// 1.延遲初始化
private volatile Resource resource;
public Resource getResource() {
if (resource == null) {
synchronized (this) {
if (resource == null) {
resource = new Resource();
}
}
}
return resource;
}
// 2.快速初始化
public static Resource getResource() {//initialized 三個狀態 ,其他檢測到字段wei
return InstanceHolder.re; //第二個,就釋放鎖,掛起等待喚醒
}
private static class InstanceHolder {
public static Resource re = new Resource(); //會使用 Class對象初始化鎖 和 state字段
} //其中狀態有noInitialization initializing
// 3.同步初始化,性能差
public synchronized Resource getResource(){
if(null==resource){
resource = new Resource();
}
}
命令模式:將請求封裝成對象,以便使用不同的請求,隊列或者日誌來參數化其他對象。命令模式也支持可撤銷的 操作。
PS:分隔開“發出請求的對象”與“接受和執行這些請求的對象”
服務員 Command
takeroder setCommand
orderup 客戶端
廚師 execute
顧客 Receiver
package headfirst.command;
public interface Command {
public void execute();
public void undo();
}
package headfirst.command;
public class CommandController {
Command oncommand;
Command offcommand;
public void setCommand(Command oncommand,Command offcommand) {
this.offcommand = offcommand;
this.oncommand = oncommand;
}
public void onButtonWasPressed(){
oncommand.execute();
}
public void offButtonWasPressed(){
offcommand.execute();
}
}
package headfirst.command;
public class LigthOnCommand implements Command {
Light light;
LigthOnCommand(Light light){
this.light=light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
package headfirst.command;
public class Light {
void on() {
System.out.println("on");
}
void off() {
System.out.println("off");
}
}
public class test {
public static void main(String[] args) {
CommandController controller = new CommandController();
LigthOnCommand ligthOnCommand = new LigthOnCommand(new Light());
controller.setCommand(ligthOnCommand,ligthOnCommand);
controller.onButtonWasPressed();
}
}
適配器模式:將一個類的接口轉換成客戶期望的另外一個接口,適配器讓原本接口不兼容的類可以合作無間
對象適配器:通過實現接口,然後使用 組合 關聯。
類適配器:通過繼承被適配對象,實現目標接口
// 對象適配器
// 適配器類,直接關聯被適配類,同時實現標準接口
class Adapter implements Target{
// 直接關聯被適配類
private Adaptee adaptee;
// 可以通過構造函數傳入具體需要適配的被適配類對象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
// 這裏是使用委託的方式完成特殊功能
this.adaptee.specificRequest();
}
}
// 測試類
public class Client {
public static void main(String[] args) {
// 使用普通功能類
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能類,即適配類,
// 需要先創建一個被適配類的對象作爲參數
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}
---------------------
類適配器
// 已存在的、具有特殊功能、但不符合我們既有的標準接口的類
class Adaptee {
public void specificRequest() {
System.out.println("被適配類 具有特殊功能...");
}
}
// 目標接口,或稱爲標準接口
interface Target {
public void request();
}
// 具體目標類,只提供普通功能
class ConcreteTarget implements Target {
public void request() {
System.out.println("普通類 具有普通功能...");
}
}
// 適配器類,繼承了被適配類,同時實現標準接口
class Adapter extends Adaptee implements Target{
public void request() {
super.specificRequest();
}
}
// 測試類
public class Client {
public static void main(String[] args) {
// 使用普通功能類
Target concreteTarget = new ConcreteTarget();//實例化一個普通類
concreteTarget.request();
// 使用特殊功能類,即適配類
Target adapter = new Adapter();
adapter.request();
}
}
外觀模式:提供了一個統一的接口,用來訪問子系統中的一羣接口,外觀定義了一個高層接口,讓子系統更容易使用
class HealthOffice implements Executive{
@Override
public void approve() {
System.out.println("衛生局通過審批");
}
}
class RevenueOffice implements Executive{
@Override
public void approve() {
System.out.println("稅務局完成登記,定時回去收稅");
}
}
class SaicOffice implements Executive{
@Override
public void approve() {
System.out.println("工商局完成審覈,辦法營業執照");
}
}
class ApproveFacade {
public ApproveFacade() {
}
public void wholeApprove() {
new HealthOffice().approve();
new RevenueOffice().approve();
new SaicOffice().approve();
}
}
public class FacadeTest {
public static void main(String[] args) {
System.out.println("開始辦理行政手續...");
ApproveFacade af = new ApproveFacade();
af.wholeApprove();
System.out.println("行政手續終於辦完了");
}
}
//避免了在main中
// new HealthOffice().approve();
// new RevenueOffice().approve();
// new SaicOffice().approve();
模版方法模式:在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中來實現,模版方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。
public abstract CaffeineBeverage{
void prepare(){ //模版方法
boilWater();
brew();
pourInCup();
addCondiments();
hook(); //鉤子,子類看情況要不要覆蓋實現
}
void void boilWater(){
dosth("");
}
void pourInCup(){
dosth("");
}
abstract void brew();//由子類實現
abstract void addCondiments();//由子類實現
void hook(){
//do nothing!!!!
}
}
鉤子:1.可以讓子類實現算法中可選的部分
2.讓子類對模版方法中即將發生的方法做出反應