1. 程式人生 > >設計模式 建立型模式

設計模式 建立型模式

設計模式主要分為建立性模式、行為模式、結構模式。

建立類模式包括單例模式、工廠模式、建造者模式、原型模式

單例模式

單例模式的核心就是一個類只有一個物件,java簡單實現如下。
package mode.create;

/**
 * 單例設計模式
 */
public class Singleton {

    private static Singleton instance;

    private  Singleton(){}

    public static Singleton getInstance(){
        if(instance !=
null){ return instance; }else { instance = new Singleton(); return instance; } } public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println
(s1 == s2);// true } }

工廠模式

工廠模式有抽象工廠模式和簡單工廠模式,java程式碼如下。

簡單工廠模式:

package mode.create;
public class StaticFactory {
    private StaticFactory() {
    }

    public static Food getMeat() {
        return new Meat();
    }
    public static Food getMilk() {
        return new Milk();
    }
public static Food getApple() { return new Apple(); } } interface Food { } class Meat implements Food { } class Milk implements Food { } class Apple implements Food { }

抽象工廠:

package mode.create;

public class AbstractFactory {
    public static void main(String[] args) {
        Car car = new CarFactory1().createCar();
        car = new CarFactory2().createCar();
        car = new CarFactory3().createCar();
    }
}

class CarFactory1 implements CarFactory {

    @Override
    public Car createCar() {
        return new Car1();
    }
}

class CarFactory3 implements CarFactory {

    @Override
    public Car createCar() {
        return new Car3();
    }
}

class CarFactory2 implements CarFactory {

    @Override
    public Car createCar() {
        return new Car2();
    }
}

interface CarFactory {
    Car createCar();
}

interface Car {
}

class Car1 implements Car {
}

class Car2 implements Car {
}

class Car3 implements Car {
}

工廠模式都是通過工廠建立物件,不需要知道物件是怎麼建立的,簡單工廠的弊端是如果產品種類增多的話,必須要修改工廠類,優點是一個工廠可以產生很多很多類產品;

抽象工廠可以理解成工廠的工廠,在抽象工廠中,工廠是一個介面或者是一個抽象類,每一個工廠的實現都只生產某一類產品,這當產品種類增多的時候,不用修改已經存在的工廠類和產品類,這也是優點之一,需要增加一個產品類和一個生產該產品的工廠類,弊端就是會成對的增加產品類和工廠類。

Spring IOC容器是一個抽象工廠,既可以管理Bean例項,還可以管理工廠例項。ApplicationContext.xml可以看作是系統的訂單,容器根據這個訂單生產相應的Bean。

建造者模式

功能:將一個複雜物件的構建與表示分離,使得同樣的構建過程可以建立不同的表示。

優點: 客戶端不必知道產品內部組成的細節,將產品本身與產品的建立過程解耦,使得相同的建立過程可以建立不同的產品物件。

每一個具體建造者都獨立,因此可以方便地替換具體建造者或增加新的具體建造者, 使用者使用不同的具體建造者即可得到不同的產品物件 。

可以更加精細地控制產品的建立過程 。將複雜產品的建立步驟分解在不同的方法中,使得建立過程更加清晰,也更方便使用程式來控制建立過程。
增加新的具體建造者無須修改原有類庫的程式碼,指揮者類針對抽象建造者類程式設計,系統擴充套件方便,符合“開閉”。

缺點: 建造者模式所建立的產品一般具有較多的共同點,其組成部分相似,若產品之間的差異性很大,則不適合使用該模式,因此其使用範圍受到一定限制。

若產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。

模式應用:
  很多遊戲軟體中,地圖包括天空、地面、背景等組成部分,人物角色包括人體、服裝、裝備等組成部分,可以使用建造者模式對其進行設計,通過不同的具體建造者建立不同型別的地圖或人物

public class Person{
    private String name;
    private String address;
    private int age;
    private int sex;
    private int height;
    private int weight;
    public void setName(String name) {this.name = name;}
    public String getName() {return name;}
    public void setAddress(String address) {this.address = address;}
    public String getAddress() {return address;}
    public void setAge(int age) {this.age = age;}
    public int getAge() {return age;}
    public void setSex(int sex) {this.sex = sex;}
    public int getSex() {return sex;}
    public void setHeight(int height) {this.height = height;}
    public int getHeight() {return height;}
    public void setWeight(int weight) {this.weight = weight;}
    public int getWeight() {return weight;}
}
class PersonBuilder{
    private Person person;
    public PersonBuilder(){
        this.person = new Person();
    }
    public PersonBuilder name(String name){
        this.person.setName(name);
        return this;
    }
    public PersonBuilder address(String address){
        this.person.setAddress(address);
        return this;
    }
    public PersonBuilder age(int age){
        this.person.setAge(age);
        return this;
    }
    public PersonBuilder sex(int sex){
        this.person.setSex(sex);
        return this;
    }
    public PersonBuilder height(int height){
        this.person.setHeight(height);
        return this;
    }
    public PersonBuilder weight(int weight){
        this.person.setWeight(weight);
        return this;
    }
}
public class TestBuilder {
    public test(){
        PersonBuilder builder = new PersonBuilder();
        Person person = builder.name("lion")
                .address("america")
                .age(18)
                .sex(2)
                .height(180)
                .weight(150);
    }
}

原型模式

定義:用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件,類似於淺拷貝的樣子。

適用:當要例項化的類是在執行時刻指定時;或者需要建立多個物件並且這些物件內部狀態相差不大。

class Car implements Cloneable{
    private int id;
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}

    public Car clone(){
        try {
            return (Car)super.clone();
        }catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}
class Prototype implements Cloneable{
    private int id;
    private Car car;
    public Car getCar() {return car;}
    public void setCar(Car car) {this.car = car;}
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
    public Object clone(){
        try {
            boolean deep = true;
            if (deep){
                /**
                 * 深複製,複製出了兩輛車
                 * */
                Prototype prototype = (Prototype)super.clone();
                prototype.setCar((Car)this.car.clone());
                // 繼續複製其他引用物件
                return prototype;

            }else{
                /**
                 * 淺複製 ,是同一輛車
                 * */
                return super.clone();
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}
public class TestPrototype {
    public void test(){
        Prototype p1 = new Prototype();
        p1.setCar(new Car());
        p1.setId(1);
        // 複製
        Prototype p2 = (Prototype)p1.clone();
        p2.setId(2);
    }
}

Java中任何實現了Cloneable介面的類都可以通過呼叫clone()方法來複制一份自身然後傳給呼叫者。一般而言,clone()方法滿足:
(1) 對任何的物件x,都有x.clone() !=x,即克隆物件與原物件不是同一個物件。
(2) 對任何的物件x,都有x.clone().getClass()==x.getClass(),即克隆物件與原物件的型別一樣。
(3) 如果物件x的equals()方法定義恰當,那麼x.clone().equals(x)應該成立。
(4) 淺拷貝只拷貝物件本身,不拷貝物件裡面的引用物件。深拷貝是全部都拷貝。