适配器模式包含以下主要角色。
1. 已经存在的、具备完备功能的类 Adaptee(适配者)。
2. 当前系统业务所期待的接口(Target),但与现Adaptee不兼容,它可以是抽象类或接口。
3. 适配器类(Adapter)。通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
实例:
现有一个两孔插座,能对外提供220v稳定电压,但现业务需要,需要提供三孔插座,同样输出220v稳定电压,这就需要一个适配器来进行转换。
代码结构及详细:
package net.mosang.adapter; public interface ThreeSocket { public void threeSocket220v();//期望三孔输出220v电压的插线板 }
package net.mosang.adapter; public class TwoSocket { public void twoSocket220v() {//现有两孔可输出220v电压的插线板 System.out.println("220v电压持续输出中。。。。。"); } }
package net.mosang.adapter; public class Adaptor implements ThreeSocket { private TwoSocket two; @Override public void threeSocket220v() { //对外提供了三孔220v电压功能线板 two.twoSocket220v();//实际依然是经过两孔输出 } public TwoSocket getTwo() { return two; } public void setTwo(TwoSocket two) { this.two = two; } public Adaptor(TwoSocket two) { super(); this.two = two; } }
package net.mosang.adapter; public class Client { public static void main(String[] args) { TwoSocket two = new TwoSocket(); Adaptor adaptor = new Adaptor(two); adaptor.threeSocket220v(); // 输出"220v电压持续输出中。。。。。" } }
UML关系图:
用一个已经创建的实例作为原型,克隆(clone)该原型对象来创建一个和原型相同或相似的新对象,免去创建对象的复杂过程和细节。原型模式分浅拷贝与深拷贝两种。
浅拷贝实现方式:
1.原型类实现CLoneable接口
2.拷贝对象通过原型的clone方法获得新的实例
深拷贝实现方式:
1.原型类实现CLoneable接口
2.原型类重写clone方法,并在克隆对象同时也克隆响应的引用类型成员变量。
————————————–
以下通过国宝熊猫的克隆来理解浅拷贝与深拷贝:
熊猫类包含两个成员属性:熊猫名字与饲养员。熊猫名字为普通字符串对象,饲养员为引用对象。以下分别通过浅拷贝和深拷贝两种方式克隆熊猫对象:
浅拷贝方式:
package net.mosang.prototype; import java.util.Date; /** * * @author heiry * */ public class Panda implements Cloneable { private String name; private Feeder feeder; //重写clone方法 @Override protected Object clone() throws CloneNotSupportedException { Panda panda = (Panda) super.clone(); return panda; } //setter、getter public String getName() { return name; } public void setName(String name) { this.name = name; } public Feeder getFeeder() { return feeder; } public void setFeeder(Feeder feeder) { this.feeder = feeder; } //构造方法 public Panda(String name, Feeder feeder) { super(); this.name = name; this.feeder = feeder; } }
package net.mosang.prototype; public class Feeder { public String name; public void feed() { System.out.println("feed panda...."); } public Feeder(String name) { super(); this.name = name; } }
package net.mosang.prototype;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Feeder feeder = new Feed犀利士
er("张大胖");
Panda p1 = new Panda("pangpang",feeder);
Panda p2 = (Panda) p1.clone();
System.out.println(p1);
System.out.println(p2);
feeder.name = "张小胖";
System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name);
System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name);
}
}
运行结果:
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张小胖
可见浅拷贝方式,虽然获得了一个与原型对象一样的新对象,但是对于引用类型成员变量feeder,拷贝的是地址而不是对象本身,换句话说,两个对象的feeder指向的是同一个Feeder对象。
深拷贝方式:
重点在于重写原型类的clone方法:
package net.mosang.prototype; /** * * @author heiry * */ public class Panda implements Cloneable{ private String name; private Feeder feeder; //重写clone方法,并将引用成员变量feeder同时克隆 @Override protected Object clone() throws CloneNotSupportedException { Object obj = super.clone(); Panda panda = (Panda) obj ; panda.feeder = (Feeder)this.feeder.clone(); return panda; } //setter、getter public String getName() { return name; } public void setName(String name) { this.name = name; } public Feeder getFeeder() { return feeder; } public void setFeeder(Feeder feeder) { this.feeder = feeder; } //构造方法 public Panda(String name, Feeder feeder) { super(); this.name = name; this.feeder = feeder; } }
package net.mosang.prototype; public class Feeder implements Cloneable{ public String name; public void feed() { System.out.println("feed panda...."); } public Feeder(String name) { super(); this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
package net.mosang.prototype; public class Client { public static void main(String[] args) throws CloneNotSupportedException { Feeder feeder = new Feeder("张大胖"); Panda p1 = new Panda("pangpang",feeder); Panda p2 = (Panda) p1.clone(); System.out.println(p1); System.out.println(p2); feeder.name = "张小胖"; System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name); System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name); } }
运行结果:
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖
可以看到,深拷贝的引用类型成员变量也是各自独立的。
建造者(Builder)模式的主要模块如下:
1. 建造者接口:负责建造各个组件
2.装配者接口:负责将组件组装成产品
3.产品类:成员变量为各组件对象
4.各个组件类
5. 建造者实现类:实现建造者接口
6.装配者实现类:实现装配者接口
7.客户端调用类
这里以建造超级计算机为例,演示构建者模式原理:
假设计算机由CPU/主板/内存三个部件组成,现在要生产一台陌桑超级计算机,CPU为AMD的CPU,主板为华硕主板,内存为256G容量内存。类关系图如下:
使用建造者模式具体做法:
package net.mosang.builder; /** * 具体产品类 * @author heiry * */ public class Computer { private CPU cpu; private Mainboard mainboard; private Memory memory; public CPU getCpu() { return cpu; } public void setCpu(CPU cpu) { this.cpu = cpu; } public Mainboard getMainboard() { return mainboard; } public void setMainboard(Mainboard mainboard) { this.mainboard = mainboard; } public Memory getMemory() { return memory; } public void setMemory(Memory memory) { this.memory = memory; } }
package net.mosang.builder; /** * 构建子组件接口 * @author heiry * */ public interface ComputerBuilder { public CPU buildCPU(); public Mainboard buildMainboard(); public Memory buildMemory(); }
package net.mosang.builder; /** * 装配者接口 * @author heiry * */ public interface ComputerDirector { public abstract Computer directComputer(); }
package net.mosang.builder; /** * 构建者实现类 * 构建陌桑超级计算机部件 * @author wuah * */ public class MosangSuperComputer implements ComputerBuilder { @Override public CPU buildCPU() { System.out.println("陌桑超算使用的是AMD的CPU"); return new CPU("AMD"); } @Override public Mainboard buildMainboard() { System.out.println("陌桑超算使用的是华硕主板"); return new Mainboard("华硕"); } @Override public Memory buildMemory() { System.out.println("陌桑超算使用的是256G内存"); return new Memory(256); } }
package net.mosang.builder; /** * 装配者实现类:返回具体产品实例 * 陌桑超算由富士康代工装配 * @author heiry * */ public class FoxconnDirector implements ComputerDirector { private ComputerBuilder builder; @Override public Computer directComputer() { CPU cpu = builder.buildCPU(); Mainboard mainboard = builder.buildMainboard(); Memory memory = builder.buildMemory(); Computer c = new Computer(); c.setCpu(cpu); c.setMainboard(mainboard); c.setMemory(memory); return c; } public FoxconnDirector(ComputerBuilder builder) { super(); this.builder = builder; } }
package net.mosang.builder; /** * 具体部件类:CPU * @author heiry * */ public class CPU { private String brands; public String getBrands() { return brands; } public void setBrands(String brands) { this.brands = brands; } public CPU(String brands) { super(); this.brands = brands; } }
package net.mosang.builder; /** * 具体部件类:内存 * @author heiry * */ public class Memory { private int capacity; public Memory(int capacity) { super(); this.capacity = capacity; } public int getCapacity() { return capacity; } public void setCapacity(int capacity) { this.capacity = capacity; } }
package net.mosang.builder; /** * 具体部件类:主板 * @author heiry * */ public class Mainboard { private String producer; public String getProducer() { return producer; } public void setProducer(String producer) { this.producer = producer; } public Mainboard(String producer) { super(); this.producer = producer; } }
package net.mosang.builder; /** * 客户端调用类 * @author heiry * */ public class Client { public static void main(String[] args) { MosangSuperComputer msc = new MosangSuperComputer(); FoxconnDirector fd = new FoxconnDirector(msc); Computer myComputer = fd.directComputer(); System.out.println(myComputer); } }
输出结果
陌桑超算使用的是AMD的CPU 陌桑超算使用的是华硕主板 陌桑超算使用的是256G内存 net.mosang.builder.Computer@15db9742
核心点:
—— 单例类只有一个实例对象;
—— 该单例对象必须由单例类自行创建;
—— 单例类对外提供一个访问该单例的全局访问点;
实现方式:
1.构造方法私有
2.提供类自身定义一个静态私有实例
3.向外提供一个静态的公有方法用于创建或获取该静态私有实例,该方法是对外唯一提供的创建实例途径。
主要分类:
——饿汉式:类一旦加载就创建实例,保证在调用静态方法之前单例已经存在了,特点是线程安全。
——懒汉式:只有在第一次调用的时候才会创建,非线程安全,需要考虑线程同步。
package net.mosang.singleton; /** * 饿汉式单例模式 * @author heiry * */ public class HungrySingLeton { private static HungrySingLeton instance = new HungrySingLeton(); private HungrySingLeton() {//私有构造方法 } public static HungrySingLeton getInstance() { //对外提供唯一的获取实例方法 return instance; } }
package net.mosang.singleton; /** * 懒汉式单例模式 * @author heiry * */ public class LazySingLeton { private static LazySingLeton instance =null; private LazySingLeton() {//私有构造方法 } public static synchronized LazySingLeton getInstance() { //synchronized线程同步,避免并发创建多个对象 if(instance==null) { instance = new LazySingLeton(); } return instance; } }
静态工厂方法只有一个工厂类,且如果要增加产品,则需要修改工厂类代码,违背了开闭原则。工厂方法模式则将工厂类颗粒化,为每一种产品单独设立一个工厂类。
package staticfactory; public interface Computer { public abstract void cal(); }
package net.mosang.factory; public class Mac implements Computer { @Override public void cal() { System.out.println("苹果电脑启动。。。。"); } }
package net.mosang.factory; public class HP implements Computer { @Override public void cal() { System.out.println("惠普电脑启动。。。。"); } }
package net.mosang.factory; public interface ComputerFactoryBasic { public abstract Computer CreateComputer(); }
package net.mosang.factory; public class MacFactory implements ComputerFactoryBasic { @Override public Computer CreateComputer() { return new Mac(); } }
package net.mosang.factory; public class HPFactory implements ComputerFactoryBasic { @Override public Computer CreateComputer() { return new HP(); } }
package net.mosang.factory; public class Client { public static void main(String[] args) { Computer computer = new MacFactory().CreateComputer(); Computer computer2 = new HPFactory().CreateComputer(); computer.cal(); computer2.cal(); } }
输出结果
苹果电脑启动。。。。 惠普电脑启动。。。。