此文全篇围绕“是什么”和“为什么”
在列举设计模式之前,我们首先要明白两个问题:
(1)什么是设计模式?
(2)为什么要用设计模式?
以下内容为详解?
1.什么是设计模式?
设计模式值软件开发人员在软件开发过程中面临的一般问题的解决方案,这些解决方案是众多软件开发人员经过相当长的的一端时间的实验和错误总结出来的。
2.为什么要用设计模式?
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码的可靠性。
3.Java 中常用的设计模式,将以下图为基准作以详细的介绍:
首先介绍工厂模式(简单工厂模式,工厂方法模式、抽象工厂模式):
(1)什么是简单工厂模式?
简单工厂模式:专门定义一个类用来创建其他类的实例化对象,被创建的实例通常都有共同的父类
思考场景1:李某想去手机商城买一步手机,此时呢,有两款手机李某比较喜欢,一部是HUAWEI,一部是XiaoMi
基于以上场景,结合简单工厂模式的设计思想,类图如下:
代码参考:
//抽象产品类
interface Mobile{
void printMobile();
}
//具体产品类HUAWEI、XiaoMi
class HUAWEI implements Computer1{
public void printComputer(){
System.out.println("this is HUAWEI");
}
}
class XiaoMi implements Mobile{
public void printComputer(){
System.out.println("this is XiaoMi");
}
}
//一个手机工厂
class MobileFactory1{
public static Computer1 getInstance(String type){
Mobile mobile=null;
if(type.equals("HUAWEI")){
mobile=new HUAWEI();
}else if(type.equals("XiaoMI")){
mobile=new XiaoMi();
}
return monile;
}
}
public class TestFactory{
public static void buy(Mobile mobile){
mobile.printComputer();
}
public static void main(String[] args) {
TestFactory testFactory=new TestFactory();
Scanner scanner=new Scanner(System.in);
System.out.println("请输入您想要的手机型号...");
String type=scanner.nextLine();
Mobile mobile= MobileFactory1.getInstance(type);
testFactory.buy(mobile);
}
}
简单工厂模式的优点:
i)简单,易于实现;ii)把类的实例化交给工厂,易于实现
缺点:添加具体产品需要修改工厂,违反了OCP开放封闭原则
(2)什么是工厂方法模式?
工厂方法模式:定义一个用来创建创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类
设计思想:针对每一个产品提供一个工厂类,在客户端中判断使用哪个工厂去创建一个对象
基于思考场景一:我们可以形象有一个总工长专门负责生产各种各样的手机,而这个工厂里边有两个子工厂:HUAWEI和XiaoMi,如果李某想要HUAWEI,就交由HUAWEI这个子工厂去生产(即创建对象),想要XiaoMi就交由XiaoMi这个子工厂去生产
设计类图:
参考代码:
interface Mobile{
void printMobile();
}
class HUAWEI implements Mobile{
public void printComputer(){
System.out.println("this is HUAWEI");
}
}
class XiaoMi implements XiaoMi{
public void printComputer(){
System.out.println("this is XiaoMi");
}
}
interface MobileFactory{
Mobile creat();
}
class HUAWEIFactory implements MobileFactory{
public Mobile creat(){
return new HUAWEI();
}
}
class XiaoMiFactory implements MobileFactory{
public Mobile creat(){
return new Surface();
}
}
public class TestFactory{
public void buyMobile(Mobile mobile){
mobile.printMObile();
}
public static void main(String[] args) {
TestFactory testFactory=new TestFactory();
MobileFactory mobileFactory=new HUAWEIFactory();
testFactory.buyMobile(mobileFactory.creat());
}
}
工厂方法模式的优点:
i)降低了代码的耦合度,对象的生成交给子类完成;
ii)实现了开放封闭原则,每次添加子产品不需要修改原来的代码;
缺点:
i)增加了代码量,每个具体产品都需要一个具体工厂
ii)当增加抽象产品也就是添加一个其他产品族,需要修改工厂,违背OCP
(3)什么是抽象工程模式?
抽象工厂模式:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们的具体类
思考场景二:某工厂要生产两款电脑:Macbook Pro/Surfacebook,这是候负责该工厂的产品经理说要生产新的一类产品操作系统Mac Os 和Windows 8。
设计类图:
参考代码:
interface Computer1{
void printComputer();
}
class MacBook implements Computer1{
public void printComputer(){
System.out.println("this is Mac");
}
}
class SurfaceBook implements Computer1{
public void printComputer(){
System.out.println("this is a surfaceBook");
}
}
interface OperatingSystem{
void printSystem();
}
class MacOsSystem implements OperatingSystem{
public void printSystem(){
System.out.println("this is a Mac os");
}
}
class Windows implements OperatingSystem{
public void printSystem() {
System.out.println("this is a windows 8");
}
}
interface productionFactory{
Computer1 createComputer();
OperatingSystem createSystem();
}
class AppleFactory implements productionFactory{
public Computer1 createComputer(){
return new MacBook();
}
public OperatingSystem createSystem(){
return new MacOsSystem();
}
}
class MsFactory implements productionFactory{
public Computer1 createComputer() {
return new SurfaceBook();
}
public OperatingSystem createSystem() {
return new Windows();
}
}
public class TestFactory{
public void buyComputer(Computer1 computer1){
computer1.printComputer();
}
public void use(OperatingSystem operatingSystem){
operatingSystem.printSystem();
}
public static void main(String[] args) {
TestFactory testFactory=new TestFactory();
productionFactory factory=new AppleFactory();
Computer1 computer1=factory.createComputer();
OperatingSystem system=factory.createSystem();
testFactory.buyComputer(computer1);
testFactory.use(system);
}
}
优点:
i)代码解耦,满足OCP开放封闭原则
ii)抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,对于复杂对象的生产相当灵活易扩展;
缺点:
抽象工厂模式是工厂方法模式的扩展,扩展产品族的时候,代码量会成倍增加,会使整个代码显得很笨重,并且会违反OCP,因为要修改所有的工厂。
2.代理设计模式:
什么是代理设计模式?
两个类共同实现一个接口,其中一个子类负责真实业务的实现,另外一个子类辅助真实业务主题的操作(类似于生活中代购的的例子)
举个例子:你想买一台外星人笔记本,但是你又不知道购买渠道,这时,你将你的想法告诉代理,有代理去完成这些操作
参考代码:
interface Isubject{
public void buyComputer();
}
class RealSubject implements Isubject{
public void buyComputer(){
System.out.println("买一台外星人电脑");
}
}
class ProxySubject implements Isubject{
private Isubject subject;
public ProxySubject(Isubject subject){
this.subject=subject;
}
public void produceComputer(){
System.out.println("1.生产外星人电脑");
}
public void afterSale(){
System.out.println("3.外星人电脑售后团队");
}
public void buyComputer() {
this.produceComputer();
this.subject.buyComputer();
this.afterSale();
}
}
class Factory{
public static Isubject getInstance(){
return new ProxySubject(new RealSubject());
}
}
public class TestFactory{
public static void main(String[] args) {
Isubject subject=Factory.getInstance();
subject.buyComputer();
}
}
单例:一个类只允许产生一个实例化对象
(1)饿汉式单例:不管是否使用户Singleton类的对象,只要该类加载了,那么一定会 自动创建一个公共的instance对象。
参考代码:
class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){
//构造方私有化化,外部无法调用构造方法产生实例化对象
//所以应该在类的内部产生实例化对象
}
public final static Singleton getInstance(){
return instance;
}
public void print(){
System.out.println("hello world");
}
}
public class TestSingleton{
public static void main(String[] args) {
Singleton singleton=null;//声明对象
singleton=Singleton.getInstance();
singleton.print();
}
}
懒汉式单例: 当第一次使用Singleton对象的时候才会为其产生实例化对象的操作
参考代码:
class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
public void print(){
System.out.println("hello world");
}
}
public class TestSingleton{
public static void main(String[] args) {
Singleton singleton=null;
singleton=Singleton.getInstance();
singleton.print();
}
}
单例模式的特点: 构造方法私有化, 外部无法产生新的实例化对象, 只能通过static方法取得实例化对象