設計模式 建立型模式
設計模式主要分為建立性模式、行為模式、結構模式。
建立類模式包括單例模式、工廠模式、建造者模式、原型模式
單例模式
單例模式的核心就是一個類只有一個物件,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) 淺拷貝只拷貝物件本身,不拷貝物件裡面的引用物件。深拷貝是全部都拷貝。